2要素認証(2FA)を導入する方法 / SMS認証

## RingCaptchaを使った導入する方法を説明します。
[RingCaptchaとは](https://ringcaptcha.com/ja) 2要素認証(2FA)を簡単に導入できるツールです。ユーザーデータベースに電話番号をもたせたいときにも活用できます。

## 2FAはなぜ必要なのか？
2要素認証≒2段階認証には様々な方法があるが（ちなみに、2段階認証、2要素認証、2段階検証等表記にゆらぎがある場合が多いが、細かな違いが気になる方は[こちら](http://qiita.com/tienlen/items/9e1b58dd173472f071c0)）、最もシンプルで多くのサービスに導入されているがSMSによる検証です。ワンタイム・パスワード（One-Time Password, 以下OTP）を手元の携帯電話で受信し、WEBサイトへOTPを入力する手法です。自分自身の携帯電話番号がOTPを受信することのできる唯一の鍵となり、ユーザーが本人確認をすることができるようになります。

電話番号に紐づくSMSを用いた2要素認証は主に2つの目的があります。

- 1ユーザーが複数アカウントを作成するのを抑止する
- 問題発生時に電話にて連絡をとれるようにする

どちらの目的も健全なオンラインコミュニティ（例えば、シェアリングサービス、マーケットプレイス、SNS等）を確立する上で、又は顧客情報を重視するeコマース、フィンテックのようなサービスにおいても利用するユーザーと直接対話できるチャネルを持つことは非常に重要となります。実際にWhatsApp, Line, Uber等、著名なサービスは2FAを導入している場合が多い。


## 2FA導入の手間
WEBサービスへの2FA導入支援を行っているサービスは複数あります。これらのサービスは簡易に複数の国のキャリア対応、適宜最適なルートでOTPを送るルートを設定する等の機能を持っている場合が多い。
このようなサービスがあるにもかかわらず、2要素認証導入はまだ難しい部分がある。
典型的な2要素認証におけるユーザー、UI、バックエンド(BK)、2FAサービス間のワークフローは下記のようになる。

1. UI: ユーザーに電話番号を入力させる
2. UI: ユーザ名/電話番号をバックエンドに渡します
3. BK: DBにユーザー名と電話番号を紐付けたデータを作成する
4. BK: 2FAサービスにOTPをユーザーに送るようリクエストを投げる
5. UI: ユーザーにOTPを入力させる。また、1回目のリクエストが作動しない場合に再度OTPを送信するようユーザーがリクエストできるようにする。
6. UI: BKにOTPを渡す。BKは2FAがただしいか検証する
7. UI: 成功又は失敗のメッセージを表示し、次のステップに進む

![RingCapcha1.png](https://qiita-image-store.s3.amazonaws.com/0/192668/de21627b-96d0-ea3e-e7c6-52f9a16ec569.png)

シンプルなように見えて、導入に必要な要件を理解するのは非常に面倒です。

そこで、簡易に2FAを導入するRingCaptcha (ringcaptcha.com) をこれらの煩雑なアレコレを解消できます。英語ですがLiveでRingCaptchaへ質問できるチャット機能もあり、導入にスタックした場合は非常に助かります。
簡単にRingChaptchaの機能を説明したいと思います。
RingCaptchaは、UI処理に関わるワークフローを処理するJavascriptのスニペットを提供しています。また、バックエンド（BK）からJavascript UI（下の図を参照）を一つのブロックとして処理することで、ワークフローを簡易化します。これにより、RingCaptcha 2FA サーバーへのAPIコールのみでBK（[6]＆[7]）と成功/失敗の場合（[8]）の後に何をするかまで簡易に進めることができます。簡単な概念図は下記のようになります。
![RingCapcha2.png](https://qiita-image-store.s3.amazonaws.com/0/192668/1d0ffc39-fbdc-1992-4076-f72eeda04788.png)


---
## RingCaptchaの導入方法

サンプルとして、RingCaptchaのUI Javascript スニペット（サイド上はRingCaptcha ウィジットとも表記されている）がどのように見えるのか紹介します: 

ユーザーの電話番号を入力する (ステップ [1])
オプションでSMS又は、音声でOTPを受取るを選択する
<img width="558" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/192668/8ab40283-4736-9a07-3ac6-ff64da8fccf6.png">

ユーザーにOTPを入力させる (ステップ [5])
オプションで再度OTPを取得できる

<img width="556" alt="rc_widget_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/192668/11ffd485-fbf2-ef93-91b9-3905bbd7229e.png">

- RingCaptchaを導入するために必要なのは3ステップのみです。
ringcaptcha.comから登録する
- HTMLページにRingCaptcha widgetのコードスニペットを追加する
- バックエンドにRingCaptchaウィジェットとRingCaptcha APIサーバーと通信する環境を実装し、電話番号が確認されたときに必要な処理を行います。例えば、特定のページなどにリダイレクトする等。

**RingCaptchaアカウン開設から導入まで**
RingCaptcha [https://my.ringcaptcha.com/register](https://my.ringcaptcha.com/register?utm_source=qiita&utm_campaign=2fa&utm_content=article)
メール認証完了後、ログインしRingCaptcha アプリを作成します。‘Create New App’をクリックします。
![11.png](https://qiita-image-store.s3.amazonaws.com/0/192668/f6ebf9ee-811f-00c2-9612-c1cd5745d46e.png)

次の画面で、オレンジ色の‘Create new’をクリックします。

![22.png](https://qiita-image-store.s3.amazonaws.com/0/192668/0c979c86-761e-f525-6928-64c426bd1ac0.png)
ステップ1にて、 ‘App Type’ で ‘Web’ をドロップダウンで選択します。ステップ2で、ドメインネームを入力します。最後に、オレンジ色の ‘Create App’をクリックします。
![pasted image 0.png](https://qiita-image-store.s3.amazonaws.com/0/192668/fdecbd3a-08f6-e8aa-dcb9-c739ec63f7da.png)
これらのステップを完了するとダッシュボードから作成したアプリをみることができます。

![スクリーンショット 2017-07-10 18.56.34.png](https://qiita-image-store.s3.amazonaws.com/0/192668/284f2c3d-fe63-a456-9dce-aa131d88eb43.png)
 ‘App Key’は表示を隠しているため、クリックして確認する必要があります。

**RingCaptcha Widgetのコードスニペット**
Widgetを表示させたいHTMLページにコードスニペットを追加します:

```ruby
<!--- Place holder for RingCaptcha widget --->
<div id='widget-point'>
</div>

<!--- Script to mount RingCaptcha widget, and handle various RingCaptcha events --->
<script type='text/javascript'>
  $(document).ready(function() {
    $('#widget-point').append(
      '<div id="xyz" data-widget data-locale="en" data-mode="verification" data-type="dual"></div>'
    );

    const appKey = "Your RingCaptcha AppKey";

    var widget = new RingCaptcha.Widget('#xyz', {
      app: appKey,
      events: {
        verified: function(event) {
          console.log("Verified: event:", event);
          const yourBackendUrl = "Your backend server url";

          // Current user data in browser local storage
          const dataString = localStorage.getItem('ringcaptcha.widget.' + appKey);
          const data = dataString ? JSON.parse(dataString) : null;

          // Get PIN code
          const code = document.getElementsByName('ringcaptcha_pin_code')[0].value;

          // Communicate with backend server the fingerprint & token, and do whatever else but use setTimeout to give time for POST to be successful
          $.post( yourBackendUrl, { code: code, token: data.token } );
          // E.g., redirect to another page
          setTimeout(function () { window.location.replace("https://my.own.server?phone=" + data.phoneNumber); }, 2000);
        }
      }
    }).setup();
  });
</script>
```

**検証ナンバーを確認するためのバックエンドコード**


バックエンドサーバーはRingCaptchaウィジェットから'code'と特定のユーザーに属する'token'を受信します。バックエンドコードはこの情報からRingCaptcha APIサーバーからウィジェットによって検証された電話番号を検索することができます:

```ruby
POST https://api.ringcaptcha.com/Your RingCaptcha App Key/verify

code=...&token=...&api_key=Your RingCaptcha API Key

Which returns:
{ phone: …., status: …. } 
```
‘verify’のAPIエンドポイントの参考はこちらにご覧ください。‘Verifying the PIN Code’(  https://my.ringcaptcha.com/docs/api)

---
**REST API**
上級者向けに[RingCaptchaはRest API] (https://my.ringcaptcha.com/docs?utm_source=qiita&utm_campaign=2fa&utm_content=article)と複数の言語向けの[SDK](https://github.com/ringcaptcha) を提供しています。これらを使用することにより、自分のWEB又はモバイルサービスのUIに最適なフォームを作成することができます。RingCaptchaはAPI経由で検証に必要な部分のみ利用することも可能です。
より詳細は[こちら](https://ringcaptcha.com/ja?utm_source=qiita&utm_campaign=2fa&utm_content=article)ご確認お願いします。