Doorkeeperでパスワードが変更されたらクライアント側でログアウトさせる

Doorkeeperを使ったoauthの仕組みでプラットフォーム側でパスワード変更の処理を書いててパスワード変更しても現在ログイン状態のユーザーがログアウトされなくて久しぶりにどっぷりハマったのでメモ。


セッションストアであるredisを見ると同じユーザーで二つのブラウザでログインすると2つ違うsession keyで保持されている。
このセッションの中身は

一つ目はwarden key(そのままだとユーザID)
二つ目はencrypted_password

となっているようだ。

https://stackoverflow.com/a/23683925/2223472

Doorkeeperを使っているクライアントではoauth認証を使うのでパスワードを使っていない
そのため二つめencrypted_passwordの値は空になっている。

この二つの値を使って認証しているようだ。

プラットフォーム側でパスワードを変更しても二つ目の値は相変わらず空のためクライアント側ではセッションの状況に変化なしとなり
そのままログインが保持されてしまう。

tokenを使ったりパスワードを渡す等があったりしたがこうした。

まず、 パスワード変更時刻をプラットフォーム側にcolumnとして追加。
パスワード変更時にupdateするようにする。

1
2
3
4
5
6
class User < ApplicationRecord  
  def reset_password(*args)  
    self.password_changed_at = Time.current  
    super  
  end  
end  

そしてクライアントサイドでは連携されたpassword_changed_atを使うようにする。

1
2
3
4
5
class User < ApplicationRecord  
  def authenticatable_salt  
    password_changed_at  
  end  
end  

これでパスワードが変更されるとクライアントのセッションの中身も変わり、
他のブラウザでログインしていても適切にログアウトされる。

Comments