devise-two-factorでの2要素認証設定時にdigestを変更したい

こんにちは!kossyです!




今回はdevise-two-factorでの2要素認証設定時にdigestを変更する方法について、ブログに残してみたいと思います。



環境

Ruby 2.6.9
Rails 6.0.4
MacOS BigSur
devise-two-factor 4.0.1



otpメソッドのオーバーライド

devise-two-factorは内部でrotpというGemを使っているのですが、ソースコードを見てみると、デフォルトでは暗号化にSHA1を用いています。

initializeでインスタンスを作成する際に、optionsでdigestを指定してやれば、SHA256等のSHA1以外のアルゴリズムも設定できるようになっていますので、

今回はotpメソッドをオーバーライドする形で実現したいと思います。

# devise-two-factor を使っているモデルと仮定

class User
  def otp(otp_secret = self.otp_secret)
    options = { digest: 'sha256' }
    ROTP::TOTP.new(otp_secret, options)
  end
end

これで、validate_and_consume_otp!メソッドが呼ばれた際に、digestにSHA256が設定されます。

github.com


動作確認

動作を確認してみます。確認のため、validate_and_consume_otp!メソッドをUserモデルに定義し、binding.pryを挟みます。

  def validate_and_consume_otp!(code, options = {})
    otp_secret = options[:otp_secret] || self.otp_secret
    return false unless code.present? && otp_secret.present?

    totp = otp(otp_secret)
    binding.pry
    if totp.verify(code.gsub(/\s+/, ""), drift_behind: self.class.otp_allowed_drift, drift_ahead: self.class.otp_allowed_drift)
      return consume_otp!
    end

    false
  end
$ totp
=> #<ROTP::TOTP:0x00007fa7328a1458 @digest="SHA256", @digits=6, @interval=30, @issuer=nil, @secret="35FZU6MQ3CAVSJWWN4VUAPVW">

digestにsha256が設定されていることが確認できました。