Rails & Mongoid で二段階認証実装

やりたかったこと

Railsのアプリケーションに二段階認証を入れたかった。

下記二つのサイトが分かりやすく、参考にしました。

Deviseを使っているRailsアプリに2段階認証を導入する - Qiita
deviseとGoogle Authenticatorを用いてRailsシステムに「二段階認証」を導入した話 - LiBz Tech Blog

今回利用したgem
github.com

しかし、今回mongodbを使っていて、結構詰まってしまったので備忘録メモ。

詰まったところ

Modelの設定

# Active Recordの場合は下記コマンドを叩くだけでOK!
$ bundle exec rails generate devise_two_factor MODEL ENVIRONMENT_VARIABLE

# こんな感じにModelが書き換えられる
class User
     devise :two_factor_authenticatable,
                 :otp_secret_encryption_key => "encryption_key"

Mongoidの場合は...

1. https://github.com/attr-encrypted/attr_encrypted のgemを追加。

2. Modelを書き換え。

Class User
    include Mongoid::Document
    include Mongoid::Timestamps

    # 自分でattr_encryptedを定義しない場合必要ない。
    extend AttrEncrypted

    # field定義。attr_encryptedより先に定義しておく必要がある
    field :encrypted_otp_secret,        type: String
    field :encrypted_otp_secret_iv,    type: String
    field :encrypted_otp_secret_salt, type: String
    field :consumed_timestep,           type: Time
    field :otp_required_for_login,        type: Boolean
    field :otp_backup_codes,              type: String

    # utf-8 のように設定しないとエラーが起きてしまったので、前もって設定しておく。
    # 設定しなければ、ここのURLの設定が利用される。
[https://github.com/tinfoil/devise-two-factor/blob/f3e40dc3ae5c26e42228d55d8df57cefab8eb167/lib/devise_two_factor/models/two_factor_authenticatable.rb#L15]
    
    attr_encrypted :otp_secret,
      encode: true, charset: "utf-8",
      key: 'please change your environment secret key',
      mode: :per_attribute_iv_and_salt unless self.attr_encrypted?(:otp_secret)

    # deviseは、attr_encryptedを設定した後で読み込む。
    devise :two_factor_authenticatable,
           # リカバリーコードを使う場合
           :two_factor_backupable, otp_number_of_backup_codes: 10

    # backup codeを利用したい場合、json型で保存されるので、取得するときに、parseするように設定
    # もっといい方法ありそうだけど、わからなかった...
    def otp_backup_codes
      JSON.parse(super)
    end

3. あとは上にリンクを貼ったサイトの通りにするとできました!

思ったこと

RailsのGemとか記事は、ActiveRecord前提で書かれているものが多く、調べるのに手こずった。
けど、device gem とかに少し詳しくなれたので、結果オーライ!
ただ、結構時間かかってしまったので、めんどくさがらずに最初からコード追っていけばよかったと公開。