Rails

Rails 3.x で API がうまく動いていないのを調査したきの話

More than 3 years have passed since last update.

特定の API がうまく動いていない?

調査したのはシンプルな API を提供するアプリで

  1. 認証 API を実行:セッションに認証済みの情報をセット
  2. 各種 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

参考