Railsにおける二段階認証
二段階認証を実装しやすくするGemは何種類か出回ってるようです。信頼感あるWEBサービスには、だいたい二段階認証機能が付いているんではないでしょうか?
- tinfoil/devise-to-factor https://github.com/tinfoil/devise-two-factor
- mdp/rotp https://github.com/mdp/rotp
この二つで迷ったのですが、プロジェクトでDeviseを使っているなら、Devise-Two-Factorのほうが相性いいんじゃないの?
ということでDevise-Two-Factorを採用することにしました。
実際にはDevise-Two-Factorはrotpをラップしたもので、ハッシュ値の作成時にもrotpが使用されています。
弊社のプロダクトに組み込んだら、また別にまとめを作ろうと思います。
環境・バージョン
Mac OS Ⅹ Yosemite
Rails: 4.1.0
Ruby: 2.1.5p273
手順
普通にレポジトリからgit clone
で落としてきて、とりあえずデフォルトのGemfileでbundle install
してみました。
するとpg(PostgreSQL)のconfigファイルがないやらでめっちゃ怒られます。PostgreSQLについてあまり明るくないので、自分はお手軽なSQLite3に変更しました。
DemoのデフォルトのDBがPostgreSQLになってます。コメントアウトしてSQLiteに変えちゃいましょう。
# gem 'pg'
gem 'sqlite3'
default: &default
adapter: sqlite3 # postgresql
encoding: unicode
# For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: 5
次にコマンドライン操作に移ります。
-
Demoディレクトリで
bundle install
-
bundle exec rake db:migrate
でDB,テーブルを作成します。 -
rails c
でUser
と入力し、ちゃんと属性が付いてるか確かめてみましょう。
-
rails s
でサーバー起動します。デフォルト3000番ポートを他プロジェクトで使っていたのでrails s -p 3003
で3003番にアクセス。 -
http://localhost:3003 にアクセス
すごくシンプルですが、無事ブラウザで表示されました。
Sign upしてみましょう。
![image](https://qiita-image-store.s3.amazonaws.com/0/80075/2677f550-9b4a-19f8-0a7b-b16eb4780653.png)
ログインに成功すると、Enable 2FAのボタンが出現します。
class UsersController < ApplicationController
#
# other code...
#
def enable_otp
current_user.otp_secret = User.generate_otp_secret
current_user.otp_required_for_login = true
current_user.save!
redirect_to home_index_path
end
end
二段階認証を有効化するのはenable_otp
メソッドです。
User.generate_otp_secret
でハッシュ値を作成して保存しています。
Enable 2FAを押してみましょう!
Demoにはハッシュ値をQRコードに変換してくれるgem 'rqrcode-rails3'が入っています。
最初からQRコードを生成してくれるようにViewに記載してあるので、Enable 2FAで次の画面に遷移するだけでQRコードが表示されます。
<% if current_user.otp_required_for_login %>
<%= button_to "Disable 2FA", users_disable_otp_path, :method => :post %>
<%= raw RQRCode::render_qrcode(current_user.otp_provisioning_uri(current_user.email, issuer: "Devise-Two-Factor-Demo"),
:svg,
:level => :l,
:unit => 2) %>
これをGoogleAuthenticatorで読み取ってみると...
やったぜ。
ここに表示されているアドレスは別の時にキャプチャしたものなので違ったものが入力されていますが、実際はサインアップ時に登録したアドレスが表示されます。
このワンタイムパスを入力することで、二段階認証が完了します。
一度ログアウトして、ちゃんと表示された番号でログインできるか確かめてみましょう。
まとめ
Deviseでログイン認証とかセッション管理してるなら、おすすめのGemだと思います。
もしSMSなどで番号を端末に通知する、などの機能を付けたい場合は各携帯キャリアへの料金や通信が発生するので、別サービスとの契約が必要です。
最近はTwilioなどがよく使われているみたいですね。
Twilio for KDDI Web Communications | クラウド電話API
QiitaやGithubも二段階認証を実装しているので、ぜひやってみるといいかもしれません!セキュリティが非常に大事なファクターである時代ですから...
それではまた。