環境
- サーバーRails5
- フロントをReact/Angular
- Railsのdeviseのsign_outリクエストをX-CSRF-Tokenのヘッダーを付けて実行したときに発生
エラー
Started DELETE "/api/v1/users/sign_out" for 127.0.0.1 at 2018-11-29 11:26:51 +0900
Processing by Users::SessionsController#destroy as JSON
Parameters: {"session"=>{}}
User Load (2.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
↳ /Users/xxx/.rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
HTTP Origin header (http://localhost:3001) didn't match request.base_url (http://localhost:3000)
解決方法
- 開発環境なら config/environments/development.rbなんかに
config.action_controller.forgery_protection_origin_check = false
の設定を追加 - 本番環境であればnginxのリバースプロキシなどをごにょごにょ
エラー原因
- Rails5系ではデフォルトで
config.action_controller.forgery_protection_origin_check = true
になっている - その場合、X-CSRF-Tokenヘッダーを付けたリクエストを送ると以下のチェックが走る
actionpack/lib/action_controller/metal/request_forgery_protection.rb#L398
# Checks if the request originated from the same origin by looking at the
# Origin header.
def valid_request_origin?
if forgery_protection_origin_check
# We accept blank origin headers because some user agents don't send it.
request.origin.nil? || request.origin == request.base_url
else
true
end
end
- rails/actionpack/lib/action_controller/metal/request_forgery_protection.rb
- このチェックではportが異なっていても例外となる
- そのためSPAのようにブラウザのポートとAPIのポートが異なるようなSPAの開発環境でおこりがち