OpenAMでTOTP認証する

## 今日やること

これまでの記事では、IDとパスワードによる認証を経て、Policy Agentが導入されているWebサーバーにアクセスしてました。今日は、この認証にもう１要素加えて、多要素認証としてみたいと思います。
多要素認証ってわたしは呼んでますが、2段階認証とか、2要素認証とか認証サービスごとによっていろいろな呼び方をされてますね。なにか区別しているんでしょうか？

![001.jpg](https://qiita-image-store.s3.amazonaws.com/0/148404/eb683106-0d64-5390-c3ee-b2db65cdbca7.jpeg)

流れとしては、上記のような感じですね。ユーザーはOpenAMで認証して、認証済みのセッションを払いだしてもらうために、**1. IDとパスワードで認証**と**2. TOTPで認証**を行うという感じです。

## TOTPってなに？

TOTPはTime-Based One-Time Passwordの略です。[RFC](https://tools.ietf.org/html/rfc6238)で定義されています。**秘密鍵と現在時間を共有する一度きりのパワードを生成するアルゴリズム**みたいなもんです。あまり細かいことはわかってません(◞‸◟)

![001.jpg](https://qiita-image-store.s3.amazonaws.com/0/148404/d7bd0983-f16d-4a6c-f28a-e4cdd5d4232a.jpeg)

大まかな概要図はこのような感じだと思います。図から想像できるように、**KEY**は事前に共有しておく必要があります。

## OpenAMでTOTP認証を有効化する

それではやっていきましょう！

### ForgeRock Authenticator モジュールを追加する

OpenAMの管理コンソールに管理者アカウント（ユーザー名は`amadmin`）でサインインします。
Authentication => Modules => Add Moduleとアクセスします。

<img width="906" alt="0011.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/ef3a7d21-236a-9bea-1cfc-036a4f688fe7.jpeg">

モジュールの追加ウィザードが表示されます。以下のパラメータを入力し、**Create**をクリックします。

* Name
    - TOTP
* Type
    - ForgeRock Authenticator(OATH)

こんな感じです。

<img width="731" alt="002.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/c4dc1083-6aa6-98d1-d366-3ec6d41bae08.jpeg">

引き続きパラメータを入力し、**Save Changes**をクリックします。（変更点のみ記載）

* 使用するOATHアルゴリズム
    - TOTP
* Name of the issuer 
    - iam.example.com

こんな感じです。

<img width="731" alt="003.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/86198753-3575-625c-a789-ccad8d5a1b7a.jpeg">

Name of issuerは**発行元**みたいなイメージでしょうか。

### TOTPモジュールをチェーンに追加

OpenAMには認証のチェーン（連鎖）という仕組みがあります。「Aという認証が成功したらBという認証」、とか、「Aという認証が成功しても失敗してもBという認証」...とかいう感じで、認証の組み合わせを定義できます。

設定はAuthentication => Chainsから行うことができます。デフォルトでは、**ldapService**というチェーンが適用されていますので、これをクリックします。

<img width="733" alt="004.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/c42a6637-fc79-a3a4-9f03-5e813112be40.jpeg">

ん～(*´▽｀*)直観的でわかりやすいインターフェースだと思います。**Add a Module**から先ほど追加したモジュールを追加することができます。追加後は以下のような画面になります。

<img width="736" alt="006.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/e6ca01d6-f63c-c80b-acb2-87c36df0ccbe.jpeg">

ここで、**Require**とか**Requisite**とか表示されていますが、これは各モジュールの実行後の動作決める**条件**となります。以下のようなパラメータを設定することができます。

|条件|説明|
|:---|:---|
|requisite|モジュールは成功する必要があります。成功すると、チェーンの次のモジュールに進み、失敗すると、そこで認証失敗となります。|
|required|モジュールの成功が必要です。成功するかどうかに依らず、チェーンの次のモジュールに進みます。|
|sufficient|モジュールの成功は必須ではありません。成功すると、チェーンの次のモジュールに進まず、認証成功となります。失敗すると、チェーンの次の認証モジュールに進みます。|
|optional|モジュールの成功は必須ではありません。成功するかどうかに依らず、チェーンの次のモジュールに進みます。|

## ForgeRock Authenticatorのインストール

お手持ちのスマホに**ForgeRock Authenticator**をインストールします。
このアプリは**ユーザー側のOTPの生成器**みたいなものになります。（アップデートしたほうがいいですね...）

<img width="320" alt="007.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/8eb4de60-f656-5f01-4055-70b916b9a32e.png">

## 動作確認

それでは、試してみましょう。
Policy Agentを導入済みのWebサーバー`web.example.com`にアクセスします。
アクセス後、IDとパスワードによる認証画面が表示されますので、検証アカウント（ユーザー名は`johnd`）でサインインします。

<img width="489" alt="008.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/fffc9334-70e1-5a6e-560e-713341f04979.jpeg">

**ユーザー側でOTPを生成するために必要な鍵の事前共有**と**2要素目の認証**のプロセスが開始されます。**REGISTER DEVICE**をクリックします。

<img width="472" alt="009.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/ed491912-ee00-513b-fa2e-de54c6c0e114.jpeg">

先ほど、スマホにインストールした**ForgeRock Authenticator**を使って、鍵の登録をします。QRコードが表示されるので、このアプリで読み取ります。

<img width="506" alt="010.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/33f3c09c-ff36-b18d-7f36-32be961e94a0.jpeg">

読み取り後、**LOGIN USING VERIFICATION CODE**をクリックします。
ちなみに、**ForgeRock Authenticator**では、時間の経過とともに変化するOTPが表示されます。

<img width="320" alt="013.png" src="https://qiita-image-store.s3.amazonaws.com/0/148404/3eedabcf-8153-17dd-32a4-59439cfe441b.png">

ここで、表示されているOTPを入力するフォームが表示されるので、**ForgeRock Authenticator**に表示されているOTPを入力します。

<img width="492" alt="011.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/43234913-10aa-7604-56f3-3e953323fb11.jpeg">

認証に成功すると、**おなじみのApacheの画面**が表示され、認証が成功していることが確認できます。

<img width="999" alt="012.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/4a411d9d-6419-6d81-30f1-695a9fff57d5.jpeg">

1回目は**OTPを生成する鍵の共有**が必要だったので、QRコードの読み取りが必要でしたが、2回目以降は不要となります。

### はまるとこ

当然、時刻ベースでOTPを生成して、比較するという認証なので、**ForgeRock Authenticator**側と**OpenAM**側で時刻があっていないと、認証が成立しません。
気を付けされたし(´◉◞౪◟◉)

## 〆

まとめると、

* ForgeRock Authenticatorモジュールで、TOTPをつかった多要素認証を実装できる
* OpenAMには認証のモジュールを組み合わせて、認証機能を提供できる
* ForgeRock AuthenticatorはOTPを生成するのに必要な鍵共有のインターフェースもモジュール上で提供している

という感じですかね～。結構簡単にTOTPできました。
ただこのForgeRock Authenticatorで作られたQRコードですが、OTPの生成器アプリとして名高い**Google Authenticator**で読み取ることができません。なんだか特殊なURNで表現されてるのかな～？ま、いっか(*´▽｀*)

明日はなにしよう～？

ばい！