deviseのlockableを使うときに意識しないといけないこと


つまり

config.unlock_strategy:time:noneにするときはよく考えて

バージョン

  • Rails 6.1.0
  • devise 4.7.3

lockableについて

deviseのlockableは、ログインに何回か失敗したらアカウントロックを行う、というもの。
注意すべきは、「ログインがロックされる」のではなく、「アカウントがロックされる」のだということ。
これは、アカウントロック中にアクセスしたログイン中セッションは、全て強制ログアウトされる動作になる。

これを利用して、次のようなイタズラをされると、結構困る。

  1. ユーザAがdeviseを使ったwebサービスにログインしている
  2. 他人がユーザAのメールアドレスでログインしようとするが連続で失敗して、ユーザAのアカウントロックされる
  3. ユーザAがアカウントロック中にwebサービスにアクセスする
  4. ログアウトされて、ユーザAはロック解除されるまでwebサービスが利用できなくなる

回避方法

同回避するか、3つほど考えた。

メールアドレスでアンロックできるようにする

deviseの設定にunlock_strategyという物があり、これには:email:time, :both, :noneが指定できる。

  • :email
    • アンロックするリンクをメールで送信する
  • :time
    • 指定時間が経過するまでロックされる
  • :both
    • :emailでアンロックするか、:timeで自然にアンロックされるか両方
    • デフォルトはこれなので、比較的安心か。
  • :none
    • アンロック方法は無い。アンロックにはDB直接いじるしかなさそう?

このうち、:email:bothの場合はロックされたアカウントの所有者が自分でロックを解除できるので、アカウントを使用できなくことに関する被害は少ない。
けど、:timeの場合は、イタズラでロックされたユーザがいた場合に、時間経過で解除されるのを待たないといけない(config.unlock_inのデフォルトは1時間)ので、困ることも発生する。

ログインだけロックする

「アカウントロック」ではなく、「ログインをロック」にする場合。
難易度が非常に高いからおすすめしないのだけれど、active_for_authentication?をオーバーライドする方法がある。
めっちゃ単純なアプリでlockableのみを使っている場合は、次のようにしても良いかもしれない。

  def active_for_authentication?
    true
  end

でも、confirmableとかも使っている場合は? 他にも色々なアカウントのアクティベーションに関する仕様がある場合は?
安易にactive_for_authentication?trueにしないようにしましょう、余計なセキュリティリスクが増えます。

deviseを使わない

例えば、deviseを避ける

終わりに

セキュリティに関する話なので、間違っているとまずい・・。
厳しいご指摘お待ちしております。