😛

【Rails】【React】API開発の際のPOSTエラー [Can't verify CSRF token authenticity.]

2022/02/25に公開

直面したエラー

サーバー側をAPI化し、フロント側をReactでPOST機能を実装する際におきたエラーに直面しました。

なぜかPOSTができずに原因がしばらくわかりませんでしたが、ターミナルにて以下のエラーが表示されていることに気づきました。

Started POST "/api/v1/events" for ::1 at 2022-02-24 19:50:39 +0900
Processing by Api::V1::EventsController#create as HTML
  (省略)
Can't verify CSRF token authenticity.  ///エラー文
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms | Allocations: 277)
  ・
  ・
  ・ 

原因特定

まずはお馴染みのDeepLでエラーの意味を確認。

Can't verify CSRF token authenticity.
*CSRF トークンの信頼性を確認できません。

このエラー文をgoogleで検索すると以下の記事を発見
https://midorimici.com/posts/rails-api-csrf

またCSRFについて曖昧だったので
https://yamory.io/blog/about-csrf/

これらの記事によれば簡単に言うと、

  • CSRFはユーザーが意図しない通信リクエストと処理を実行させる脆弱性を利用した攻撃方法 
    ex)プロフィールを更新し、送信するボタンを決済するボタンへすり替える

  • Rails の場合、クライアントとの間で CSRF Token をやりとりして安全性を確認している

  • しかしRailsAPIモードだとその様な機能が無い

  • CSRF対策はサーバー側とクライアント側で設定可能

問題解決

今回はクライアント側で設定します。

///App.js///
import { csrfToken } from '@rails/ujs';  //①

axios.defaults.headers.common['X-CSRF-Token'] = csrfToken(); //②
 (省略)
const createEvent = () => {  
    axios.post('api/v1/events', {   //③
      event: {
        title: title, 

①RailsのCSRFトークン認証に使用するため

rails-ujs ・・・ Railsの一部のRESTfulな動作や非同期な処理などを実現するために、JavaScriptの送信に関する処理などが書かれたライブラリ
参照)https://www.inodev.jp/entry/2019/12/03/234210

②csrf-tokenが自動でリクエストヘッダーに入るよう設定

Request header (リクエストヘッダー) ・・・ リクエストヘッダーは、 HTTP リクエストで使用される HTTP ヘッダーであり、メッセージの内容には関連しないものです。 Accept, Accept-, If- などのリクエストヘッダーは、条件付きリクエストを行うことができます。
参照)https://developer.mozilla.org/ja/docs/Glossary/Request_header

③POSTリクエストなどをする前にヘッダにRails側から取得したTokenを設定する

これにてPOSTリクエストをすると、、、

Started POST "/api/v1/events" for ::1 at 2022-02-25 19:26:01 +0900
Processing by Api::V1::EventsController#create as HTML
(省略)
User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
Started GET "/" for ::1 at 2022-02-25 19:26:01 +0900
   (2.3ms)  BEGIN
  ↳ app/controllers/api/v1/events_controller.rb:14:in `create'
  Event Create (3.6ms)  INSERT INTO "events" ("user_id", "title", "content", "start", "end", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"

無事投稿できました!!

参考

https://midorimici.com/posts/rails-api-csrf
https://yamory.io/blog/about-csrf/
https://qiita.com/nishina555/items/4ffaf5cc57a384b66230
https://www.inodev.jp/entry/2019/12/03/234210
https://developer.mozilla.org/ja/docs/Glossary/Request_header

Discussion