LoginSignup
2
2

More than 3 years have passed since last update.

Devise + Bootstrap3 + RailsLayoutにdevise-two-factorを使ってGoogle Authentificatorを追加する

Posted at

はじめに

以前の記事でDevise + Bootstrap3 + RailsLayout環境を作った。これにdevise-two-factorを使ってGoogle Authentificatorを追加してみる。参考記事はRails4なのでそのままでは動かない事に注意。

前提環境
Rails 5.2.2
Ruby 2.5.3
Devise-two-factor 3.0

セットアップ手順

1. 前の記事の手順でベースとなる環境を作る。

前の記事 DeviseのフォームをBootstrap3 + RailsLayoutでカッコ良くする
https://qiita.com/NYC-Blue/items/52fee61958a3a54d44d8

2. devise-two-factor gemをインストールする。

Gemをインストールします。QRコードも生成するのでrqrcodeも入れておきます。

/Gemfile
# Devise-two-factor 3.0
gem 'devise-two-factor', '~>3.0.0'
gem 'rqrcode-rails3'

$ bundle install

3. 環境変数を定義する。

環境変数名は何でも良いのですが、私はcredentials.yml.encにGOOGLE_AUTH_ENCRYPTION_KEYを作りました。32文字くらいにすれば良いと思います。

$ rails credentials:edit

結果
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: hoge...hoge
GOOGLE_AUTH_ENCRYPTION_KEY: foo...bar

4. セットアップを実行する。

$ rails generate devise_two_factor users GOOGLE_AUTH_ENCRYPTION_KEY

READMEの説明
MODEL: 認証対象のモデル(今回はUsers)
ENVIRONMENT_VARIABLE: 暗号化キーを入れる環境変数名(GOOGLE_AUTH_ENCRYPTION_KEY)
実行すると自動で次の処理が行われる。

app/models/users.rbのdeviseディレクティブ調整
:database_authenticatableを削除しようとするが、書き方によっては削除されない場合があるので、実行後要確認。削除されていなかったら手動で削除。
deviseの設定ファイルを調整
wardenの設定

Usersモデルに2段階認証関連のカラムを追加するためのマイグレーションファイルを生成するのでrake db:migrateを実行します。

db/migrate/20181231180452_add_devise_two_factor_to_users.rb
class AddDeviseTwoFactorToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :encrypted_otp_secret, :string
    add_column :users, :encrypted_otp_secret_iv, :string
    add_column :users, :encrypted_otp_secret_salt, :string
    add_column :users, :consumed_timestep, :integer
    add_column :users, :otp_required_for_login, :boolean
  end
end

$ rake db:migrate

5. Devise Userモデルを修正

私の環境ではDeviseを既にカスタマイズしてしまっているからだと思いますが、READMEには自動セットアップと書いてありますが、user.rbの自動修正はされませんでしたので手で修正します。

app/models/user.rb修正後
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :registerable,
         :recoverable, :rememberable, :validatable,
         :two_factor_authenticatable,
         :otp_secret_encryption_key => Rails.application.credentials.GOOGLE_AUTH_ENCRYPTION_KEY
end

6. recoverableを使う場合はパスワードリセット後の自動ログインをさせない。

config/initializers/devise.rb
  # When set to false, does not sign a user in automatically after their password is
  # reset. Defaults to true, so a user is signed in automatically after a reset.
  config.sign_in_after_reset_password = false   <=220行目あたり

7. applicationコントローラーをカスタマイズ

READMEの通りに行いました。Devise 4.0.0以上の場合は以下の通り。私は個別にコントローラーを書き換えるのが面倒なのでapplication_controller.rbに書きましたが、細かくやりたい場合はDeviseのコントローラーを生成($ rails gdevise:controllers Users)して、1つ1つ書いても良いでしょう。その場合はapp/controllers/users/にたくさんコントローラーのテンプレートができますので、必要なところを書き換えます。また、私のroute.rbはapp/controllers直下にDeviseのコントローラーを置く前提なので、rails gで作った場合は {users/sessions} のようにしてください。

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
    # Prevent CSRF attacks by raising an exception.
    # For APIs, you may want to use :null_session instead.
    protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?

    protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_in, keys: [:otp_attempt])
    devise_parameter_sanitizer.permit(:sign_up, keys: [:email_confirmation])
    devise_parameter_sanitizer.permit(:account_update, keys: [:email_confirmation])
  end
end

ここまでで基本的なセットアップは完了です。

カスタマイズ

ここからはやりたい動きに合わせてカスタマイズします。私がやったのは次の通り。

①サインアップしたらGoogle Authenticatorに読み込む為のQRコードを表示 => registrations_controller.rb
②サインインしてIDとパスワードが正しければGoogle Authenticatorのコードを入れる画面を表示 => sessions_controller.rb
③コードが間違っていたらコード入力画面に戻る => sessions_controller.rb

1. Sign-up後にGoogle AuthentificatorのQRコードを出す。

Sign-upでメールアドレスが得られるのでDeviseのregistrationコントローラーをカスタマイズしてQRコード生成画面に飛ばす。

app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
    protected

    def after_sign_up_path_for(resource)
        pages_googleauthqr_path
    end
end
config/routes.rb
Rails.application.routes.draw do
  root 'pages#index'
  get 'pages/googleauthqr' <=ここを追加
  devise_for :users, controllers: { registrations: 'registrations'} <=ここを修正
end
app/views/pages/googleauthqr.html.erb
<h2>Google Authentificator QR code</h2>
<% if current_user %>
  <p>emal : <%= current_user.email %></p>
  <%= raw RQRCode::render_qrcode(current_user.otp_provisioning_uri(current_user.email, issuer: "Your App"),
                                 :svg,
                                 :level => :l,
                                 :unit => 2) %>
<% end %>

ここまで書いて一旦お休み。気が向いたら続きを書きます。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2