React + Rails(API)で tokenを用いたCSRF対策の基礎(のメモ)

cookieを利用した認証を採用した場合、必然的にCSRFの対策を行う必要がある。 Railsのようなモノリシックなフレームワークを用いている場合、デフォルトでCSRF対策が入っている(ことが多い)ためCSRFの考慮する必要はないが、 React + RailsのようなSPA環境では、CSRF対策に関してもある程度自分で手を加える必要がある。 試しにやってみたので、軽くメモ。 とりあえず動く程度のメモなので、セキュリティ的に色々不都合はあるかもしれない。今後要調査。

やったこと

API

(準備) - CSRF用の機能を有効化する - include ActionController::RequestForgeryProtection(in application_controller.rb) - apiモードだとデフォルトで含まれていない様子なので、includeが必要そう

(tokenの生成) - ログイン時/ログイン確認時に、csrf tokenを生成 & レスポンスヘッダ(X-CSRF-Token)にcsrf tokenを挿入 - form_authenticity_token(ActionController::RequestForgeryProtectionの機能)を利用 - corsの設定で、expose: ['X-CSRF-Token']を追加(X-CSRF-Tokenヘッダをexposeする)

(tokenのチェック) - RailsCSRF tokenの確認を有効にする。 - protect_from_forgery with: :exception(in application_controller.rb, ActionController::RequestForgeryProtectionの機能) - ログイン時 のみCSRF tokenの確認を無効化 - skip_before_action :verify_authenticity_token, only: :create - verify_authenticity_tokenはprotect_from_forgeryの中で利用されている

フロント側

  • ログイン成功時、ログイン確認成功時に、axiosのデフォルトヘッダー(x-csrf-token)にAPIから受け取ったcsrf tokenを設定

実装例(github)

csrf api側 · takahiromasui001/spa_session_cookie_auth_trial@9c4017a · GitHub

csrf front側 · takahiromasui001/spa_session_cookie_auth_trial@5ee4a48 · GitHub

備考

  • 調査に時間はかかったが、実装はかなりシンプルになった。
  • セッション作成&セッションの確認毎にcsrf tokenを更新している。その点ではやや妥協。
  • ログイン時のcsrfも考慮していない。この辺りは今後の要改善点

参考にした情報

RailsのCSRF保護を詳しく調べてみた(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社 Railsそのもののtoken機能に関する詳しい説明。

Rails API mode+deviseなSPAでtokenによるCSRF対策をする - Qiita
方針の説明含め一番わかりやすい。サンプルコードもあり。 だいたいこれをパクった。

Cross-Site Request Forgery Prevention - OWASP Cheat Sheet Series
OWASPのCSRFに関する説明および対策を解説した資料。一通り目を通すだけでもCSRFの概略は掴める。 今回の実装ではここで示されている、synchronizer token pattern(を少し簡略化したもの)を採用

RailsでCORSのAccess-Control-Expose-Headersを設定する - Qiita
Rails APIにCORSアクセスした場合は、reseponseのヘッダーに表示する情報をあらかじめ設定しておく必要がある、という話。

AjaxにおけるCSRF攻撃対策 - バカンス駆動開発
Twitterのソース(?)をみた話とかが書いてある。csrf tokenはセッション単位で発行しているらしい。本記事もこれに倣った。