0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js (SSR) × Rails API の CSRF 対策

Posted at

概要

Next(SSR)アプリケーションと、Rails APIを連携しています。

不正なリクエストを受け付けないために、CSRF対策が必要となったのですが、Rails 標準の仕組みが利用できなかったため、対応を検討する必要がありました。

1. CSRF 対策の概要

CSRF 対策には Railsで提供されているActionController::RequestForgeryProtectionモジュールを利用します。

[役割]

  • セッションで有効なトークンを発行する
  • リクエストヘッダーX-CSRF-Tokenに格納されたトークンを自動で検証する
  • トークンが一致しない場合は(不正なリクエスト)、422エラーとして処理する
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 22ms (ActiveRecord: 0.0ms)

2. 全体の流れ

実装前に全体の流れを見ていきましょう。

  1. [Rails] CSRF トークン発行
    • コントローラーでform_authenticity_token を使ってCSRFトークンを発行する
  2. [Rails] レスポンスヘッダにトークンをセット
    • X-CSRF-Token などのヘッダ名でレスポンス
  3. [Next] フォーム送信のリクエストヘッダーX-CSRF-Token に受け取ったトークンをセットしてリクエストを行う
  4. [Rails] CSRFトークンを検証
    • 一致すれば処理を続行、一致しなければ422エラーを発生

3. 実装

全体像を理解したところで実装に移ります。

Rails

まず ApplicationControllerActionController::RequestForgeryProtectionをMIX-INしてCSRFトークンを発行するメソッドを定義します。

class ApplicationController < ActionController::Base
  include ActionController::RequestForgeryProtection
  
  protect_from_forgery with: :exception

  private
    def set_csrf_token
      response.set_header('X-CSRF-Token', form_authenticity_token)
    end
end

次にCSRF検証を行いたいコントローラーでset_csrf_tokenを呼び出します。

class PostsController < ApplicationController
  before_action :set_csrf_token, only: [:new]

  def new
    # ...
  end
end

これにより、API コール時に、レスポンスヘッダーに CSRFトークンが含まれます。

Next.js

  1. トークンを取得する API(例: GET /posts/new) をコールします

  2. レスポンスヘッダーに格納されたトークンを、X-CSRF-Tokenに付与しPOSTリクエスト

    fetch('/posts', {
      method: 'POST',
      headers: {
        'X-CSRF-Token': token, // CSRFトークン
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        title: 'Title',
        content: 'Content...'
      })
    })
    
  3. Rails で検証
    createアクション実行時に、自動で X-CSRF-Token を検証されます。

    class PostsController < ApplicationController
      # 省略
    
      def create
        # POSTリクエスト時に X-CSRF-Token が正しければ通常どおり処理される
        # 不正な場合は 422 Unprocessable Entity エラー
      end
    end
    

まとめ

CSRF対策は完了です!
他にも良いやり方があれば是非コメントをいただきたいです🫡

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?