Railsの二段階認証Gem Devise-Two-FactorのDemoを触ってみた

# 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に変えちゃいましょう。

```rb:Gemfile
# gem 'pg'
gem 'sqlite3'
```

```rb:config/database.yml
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
```

次にコマンドライン操作に移ります。

1. Demoディレクトリで`bundle install`

2. `bundle exec rake db:migrate`でDB,テーブルを作成します。

3. `rails c`で`User`と入力し、ちゃんと属性が付いてるか確かめてみましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/80075/d042d4dc-19a3-83ca-c46a-4f5b44f5d05f.png)

3. `rails s`でサーバー起動します。デフォルト3000番ポートを他プロジェクトで使っていたので`rails s -p 3003`で3003番にアクセス。

4. http://localhost:3003 にアクセス

すごくシンプルですが、無事ブラウザで表示されました。
Sign upしてみましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/80075/1524253a-197a-4d21-d56d-4089347b94c8.png)
<hr>
![image](https://qiita-image-store.s3.amazonaws.com/0/80075/2677f550-9b4a-19f8-0a7b-b16eb4780653.png)

<hr>

![image](https://qiita-image-store.s3.amazonaws.com/0/80075/30f20f15-92bb-9683-7a84-4ee7201d444a.png)

<hr>

ログインに成功すると、Enable 2FAのボタンが出現します。

![image](https://qiita-image-store.s3.amazonaws.com/0/80075/3a6de2fb-0daa-d588-57ae-715a186a1aa5.png)

```rb:users_controller.rb
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を押してみましょう！

<hr>


![スクリーンショット 2015-09-18 16.10.32.png](https://qiita-image-store.s3.amazonaws.com/0/80075/d12479e5-0555-2368-dd8a-f8685b877c96.png)
Demoにはハッシュ値をQRコードに変換してくれるgem 'rqrcode-rails3'が入っています。　
最初からQRコードを生成してくれるようにViewに記載してあるので、Enable 2FAで次の画面に遷移するだけでQRコードが表示されます。


```erb:index.html.erb

<% 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) %>
```


<hr>

これをGoogleAuthenticatorで読み取ってみると...

![FullSizeRender.jpg](https://qiita-image-store.s3.amazonaws.com/0/80075/854124b1-d709-1582-9264-efdbefc606f3.jpeg)

やったぜ。
ここに表示されているアドレスは別の時にキャプチャしたものなので違ったものが入力されていますが、実際はサインアップ時に登録したアドレスが表示されます。

このワンタイムパスを入力することで、二段階認証が完了します。
一度ログアウトして、ちゃんと表示された番号でログインできるか確かめてみましょう。


# まとめ

Deviseでログイン認証とかセッション管理してるなら、おすすめのGemだと思います。

もしSMSなどで番号を端末に通知する、などの機能を付けたい場合は各携帯キャリアへの料金や通信が発生するので、別サービスとの契約が必要です。
最近はTwilioなどがよく使われているみたいですね。
[Twilio for KDDI Web Communications | クラウド電話API](http://twilio.kddi-web.com/)

QiitaやGithubも二段階認証を実装しているので、ぜひやってみるといいかもしれません！セキュリティが非常に大事なファクターである時代ですから...

それではまた。