scramble cadenza

技術ネタのガラクタ置き場

authlogic で、ユーザーの password を編集した直後に強制ログアウトされる件

イントロ

authlogic でハマったネタ第二弾。
まとめると以下の様な感じ。

  1. authlogic でログインユーザーを作成
    • よくある 名前と password で認証するユーザー
  2. ログインユーザーを編集する画面を作る
    • password を編集可能にする
  3. ログインユーザーの password を更新すると、何故か強制的にログアウト状態になる
    • ログインを要求する url に強制 redirect される

解決法

class User < ActiveRecord::Base
  acts_as_authentic do |c|
    c.session_class = UserSession
  end
end

この解決方法はあくまで一例。

原因

  1. authlogic のログイン状態は、DB に保存されている persistence_tokensession[:user_credentials] の一致により判定される。
    • user_credentials という session の key はログイン用のモデルによって変更の可能性あり
  2. authlogic で password を更新すると、強制的に persistence_token も再生成される
    • この時 session の値も再生成された文字列に更新しなければならない
  3. 設定が甘くて、password を更新した時に session の値が更新されなかったため、ログイン状態が維持されなかった
    • authlogic がログイン画面にリダイレクト

のような感じ。

肝心の session の値も再生性された文字列で上書きしなければならない 設定は以下のメソッドで行っている。
恐らくこの値は true でなければいけないが、false になっているとこんなおかしな状況になる。

https://github.com/binarylogic/authlogic/blob/8e2acfe303ea68013ad5afa5b85c5569837a290d/lib/authlogic/acts_as_authentic/session_maintenance.rb#L87-L89

def update_sessions?
  !skip_session_maintenance && session_class && session_class.activated? && self.class.maintain_sessions == true && !session_ids.blank? && persistence_token_changed?
end

今回私が遭遇したケースでは session_class が何故か nil を返すようになっていたので、session が update されず、ログアウト状態になってしまっていた。

session_class について

session_class とは

  • Authlogic::Session::Base を継承した session クラスを返すメソッド
  • 普通は自動で判定される
    • Useracts_as_authentic なら UserSession という風に

ので、普段は意識しなくていいはず。

例えば Admin モデルを作って、Admin 専用の管理画面を作ろう、となった時に Session クラスを AdministratorSession としてしまうと、session_class を指定する必要がある。

設定を忘れるとこのような目にある。

まとめ

Authlogic::ActsAsAuthentic::SessionMaintenance::Methods#update_session? メソッドを調べればよろし