ID、パスワードによるサインインだけでは非常に脆弱で、今はTwitter、Facebook等のSNS、グーグル、アマゾン、マイクロソフトのアカウントなどが二段階認証を取り入れれいます。
この記事ではRuby on Railsで作られたサイトに、Devise、ActiveModel::Otp 、rqrcode及びグーグル認証システムによって二段階認証を実装する仕方を、段階を追って解説します。
devise、active_model_opt、rqrcode gemをインストール
まずは必要なgemを追加します。
users_controller.rbのアップデート
ここでは devise gemによって作成されるusers_controller.rbに2つの機能を追加します。
- 二段階認証を有効化するページの対応。有効化ページにはrqrcode gemによって作られたQRコードを表示します。このQRコードをグーグル認証システムで読むことになります。def activate_2faがその実装です
- ユーザーが二段階認証コード、つまりワンタイムパスワード(OTP)を送った時に、有効化のプロセスの対応。def activate_2fa_updateがその実装
二段階認証有効化ページ
users_controller.rbにあるdef activate_2fa によって作られるQRコードを表示するためのページです。ユーザーが、このQRコードをグーグル認証システムで読み込んでワンタイムパスワード(OTP)を得られます。
html_safe on @svgを読み込んでQRコードを表示させます。
ユーザーが送ったワンタイムパスワードはusers_controller.rb のdef activate_2fa_update で対応します。
devise gemのsessions_controller.rbのアップデート
ユーザーが二段階認証をセットアップ完了後は、サインインプロセスは以下2段階となります。
- IDとパスワードによる承認
- グーグル承認システムによるワンタイムパスワードによる承認
このプロセスに対応するようにsessions_controller.rbをアップデートします。
ここで行われているのは
- def createのオーバーライト
- ID、パスワードの承認が行われた後の対応
- ワンタイムパスワードを入力した後の対応
- ワンタイムパスワードの入力失敗は5回まで
- それぞれのプロセスで非承認のときはサインインページに転送
ワンタイムパスワードを入力するページ
ワンタイムパスワードを入力ページのテンプレート。
ユーザーのメールアドレスを隠しフィールドで使っています。
最後に
deviseによる二段階認証を実装すると言っているgemを色々と試したのですが、どれも上手くいきませんでした。
ActiveModel::Otpを使って、根本的に対応することで上手くいきました。
一番難しかったのは、やはりActiveModel::Otp と Devise での連携でしたが、ここをGemを使ってあれこれ出てくるエラーを直すより、自分でロジックを組んだほうが結局早かったです。
おまけ
ちなみに、この123ishのサイトはRuby on Railsで作られています。