特定の API がうまく動いていない?
調査したのはシンプルな API を提供するアプリで
- 認証 API を実行:セッションに認証済みの情報をセット
- 各種 API を実行:セッションを検証し、認証済みの場合のみ実行可
という仕組みのものでした。で、なぜか特定の API だけ認証済みでもエラーとなるので調査してちょうだいということでした。
エラー内容は「認証されてないよ」
その API からは「認証されてないよ」という旨のエラーが返却されていました。
なぜ?と思って調べを進めてみると、どうやらその API にアクセスする度に新しいセッションが生成されていて、認証済みの情報が消えているためだということが分かりました。
ログに「Can't verify CSRF token authenticity」
他の API との違いはなんだろう?と思いつつログとにらめっこ。
よく見るとうまく動いていない API を叩いた場合のみ「Can't verify CSRF token authenticity」が発生していました。ということは・・・
原因は reset_session
先のログは protect_from_forgery
で NG の場合に出力されます。で、その後 reset_session されているためセッションが再生成されていたようでした。
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
request_forgery_protection.rb
def protect_from_forgery(options = {})
self.request_forgery_protection_token ||= :authenticity_token
prepend_before_filter :verify_authenticity_token, options # <-- (1)
end
def verify_authenticity_token
unless verified_request?
logger.warn "WARNING: Can't verify CSRF token authenticity" if logger
handle_unverified_request # <-- (2)
end
end
def handle_unverified_request
reset_session # <-- (3) ここでセッションがリセットされる
end
verify_authenticity_token をスキップして解決
protect_from_forgery はシステムを堅牢にしてくれる仕組みなので重宝しますが、今回のように外部に公開する API には不要なので、その処理が走らないようにスキップしておきましょう。
hoge_controller.rb
class HogeController < ApplicationController
skip_before_filter :verify_authenticity_token
end