OpenAM で FIDO2(WebAuthn) ユースケースを考える

#FIDO2とは

**[FIDO2 ≠ WebAuthn]**　ではなくて、
**[FIDO2 ≒ WebAuthn + CTAP]**　こちらが近い

FIDO2とはFIDOアライアンスが考えた、パスワードレスでユーザーをパスワードの呪縛から解き放つ、より安全で使いやすい認証の仕組みです。
FIDOの頃のUAFとかU2Fの上位互換というわけではなく、普及しやすいように作り直した新規格です。
そして、FIDOアライアンスは FIDO2 の動作に必要な機能（ブラウザと認証サーバー間の部分　図1参照）をW3CへWebAuthn規格として提言しており、~~現在はCandidate Recommendation（勧告候補）まで進んでいます。~~ 
2019/3/4にW3C勧告になりました。
~~[https://www.w3.org/TR/webauthn/ W3C Candidate Recommendation, 7 August 2018](https://www.w3.org/TR/webauthn/)~~
[https://www.w3.org/TR/webauthn/ W3C Recommendation, 4 March 2019](https://www.w3.org/TR/webauthn/)


今年(2018)は、WebAuthnをW3Cの正式規格にするプロセスが進んできているおかげで、ブラウザ各社がWebAuthn対応バージョンをリリースし始めて、手元でも試せる環境が整い、いっそう身近になったのでは無いでしょうか。

**[FIDO2 ≒ WebAuthn + CTAP]** を前提に書いて行きます。
極力簡潔になるように少し意訳（約）している部分もありますのでご留意下さい。

## FIDO2の要素
構成要素は３つあります。
・認証デバイス（TPM内蔵PCの指紋リーダー、USBやBluetoothデバイスなど)
・ブラウザ（Firefox、Edge、Chromeなど)
・RPサーバー（FIDO2/WebAuthn 認証サーバー、サービスなど)
図1
![fido2.png](https://qiita-image-store.s3.amazonaws.com/0/316098/a2bfe7da-b2de-0fe4-4e62-58f399ad68e7.png)
**[WebAuthn]** はネットワークを流れるプロトコル部分で、**[CTAP]** はPC内でブラウザからUSBなどに接続されている **[認証デバイス]** を呼び出す部分を担当します。



## FIDO2のシーケンス
FIDO2のシーケンスは大きく**「認証」**と、認証デバイスの**「登録」**の２つあります。
認証のためには、あらかじめ認証デバイスを登録しておく必要があります。
### 登録
極限までシンプルに説明すると認証デバイスで生成した公開鍵をRPサーバーに登録します。
![fido2reg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316098/a3189895-134f-ed18-7f0c-cc49f982bf56.png)
認証デバイスにはRPID(≒RPサーバーのFQDN)とCredentialIDの組み合わせ毎に秘密鍵が保存されることになります。※デバイスによっては保存せず都度同じ鍵を生成するものもありますが、わかりやすく保存としています。
useridはRPサーバー内でログインIDと紐付けられ、credentialIdと公開鍵もRPサーバーに保存されます。

### 認証
極限までシンプルに説明するとRPサーバーから来るchallenge文字列を、認証デバイスに格納された秘密鍵で署名し返送します。サーバーはその署名を保存済みの公開鍵で検証します。
![fido2auth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316098/e3ae4e46-f2ad-cf18-f81c-97e6db1896d9.png)
秘密鍵は認証デバイス内の保護された領域にあるので、利用前にはPIN番号の入力や指紋などを認証デバイスのローカル認証を要求されるべきでしょう。
指紋は触れるだけで楽ですが、映画など見てると簡単に突破されているので盲信は禁物ですww

# エンプラ利用の認証サーバーに求められる要件
OpenAMは国や軍、ニューヨーク証券取引所などガチエンタープライズ領域で使われている
オープンソースの認証サーバーで、「認証に求められる要件」をクリアしています。
「認証に求められる要件」とは以下３つの要素のうち、２つの要素を組み合わせて使えることです。
・記憶（一般的なパスワードなど）
・所持（OTPのトークンやICカードなど）
・生体（指紋や顔認証など）
組み合わせの例としては、ユーザーIDとパスワード（記憶）でログインした後に、ワンタイムパスワード（所持)を入力するのが一般的で、２つの要素で認証することから多要素（MFA)と呼ばれています。
すなわち **記憶 + 所持** の組み合わせです。

## FIDO2はどうか？
FIDO2の場合、認証デバイスに鍵が入っていて、コレがないとそもそも認証できません。
FIDO2認証を使う時点で（所持）となり**[所持 ＋（？）]** の組み合わせです。

認証デバイスの利用にPINを要求するタイプは **[所持 + 記憶]** の組み合わせです。

指紋リーダーを使うタイプなら **[所持 + 生体]** の組み合わせです。

Windows HelloやFaceIDは **[所持 + 生体]** の組み合わせです。

FIDO2認証だけでMFAと呼んでしまって良いのかどうかは難しいですが、パスワード認証だけ、よりは安全な方式であると断言できます。

## エンプラでどうやって使おうか
認証サーバー要件以外にも運用に関する要件に対応する必要があります。
OpenAMを使うお客様（弊社の場合、主にエンタープライズ or 教育機関）で、
どのような要件があるのか今までの事例から検討しました。

**想定される要件**
(1)情報システム部門の手間がかからない運用
(2)ユーザーによって利用の許可、不許可を制御をしたい
(3)認証デバイスの機種によって利用可否を制限したい
(4)ログインIDを入れる手間も省きたい
(5)認証デバイス側の認証(PIN入力など)を必須にしたい

## 要件への対応例
**「RPサーバー実装」**で対応するもの、**「FIDO2のオプション」**を利用するものに分かれます。
**「RPサーバー実装」** は言うまでもなく、OpenAMなど認証サーバー側に組み込む機能です。
**「FIDO2のオプション」** とは、RPサーバー側から要求できる条件となり、RPサーバーの構築時に運用にあわせて決定する設定項目です。

###(1)情報システム部門の手間がかからない運用
この要件は**「RPサーバー実装」** で解決します。
ログインIDに紐付け登録してから認証デバイスを配っていると手間がかかります。
そもそも認証デバイスを登録済みで渡すというのもアリなのかと言うとナシでしょう。
なので、セルフで登録を行えるようにする必要があります。

**ログイン画面に登録ボタンを常に出す**
ログインか登録か選べるようにしておくと一目瞭然ですが、常に登録が出ているのもどうか？と言うご意見をいただく可能性が高いです。コレはナシの方向で解決します。
![fido2-login1.png](https://qiita-image-store.s3.amazonaws.com/0/316098/e3feb6ae-c7c5-f6db-0496-40b8fd376df9.png)

**ログインIDの状態（登録、未登録）を判断して画面遷移**
ユーザーの状態を判断して登録へ処理をしたいと思います。
最初のページは取り合えずログインIDだけ入れてもらう形にして、ログインIDの属性情報を参照しつつ遷移を変えます。
![fido2-loginflow2.png](https://qiita-image-store.s3.amazonaws.com/0/316098/ecf755f9-86b8-bca7-e9e4-881e05558540.png)


###(2)ユーザーによって利用の許可、不許可を制御をしたい
**「RPサーバー実装」** で解決する必要があります。
先の認証では公開鍵の登録有無で判断しましたが、もう一つフラグを用意する必要があります。
例えばFIDO2のデバイスを支給されている部署の人だけ、フラグを立てて登録することができるなどです。
![fido2-loginflow1.png](https://qiita-image-store.s3.amazonaws.com/0/316098/be43d003-9b35-5c5a-8214-7ced441169ed.png)


###(3)認証デバイスによって利用可否を制限したい
**「FIDO2のオプション」と「RPサーバー実装」** で解決します。
今はそれほど多くありませんが、今後はFIDO2の認証デバイスとして登録できる機器が増えるでしょう。
しかし組織が利用許可した認証デバイス以外は使ってほしくないケースもあると思います。
この場合は、**「FIDO2のオプション」**の **attestation** を使って解決します。　
**attestation** を **direct** にすると 認証デバイスの機器情報（機種毎に固有のAAGUID）を、RPサーバーが受け取れます。
B2Cの世界では、おそらく機器情報を収集するのはヨシとはしないと思います。
しかし、エンプラの場合は特定して絞るために活用できると思います。
ただし **attestation** の機器情報で、ホワイトリストを作成する必要があり、機器更新などの際はメンテナスが必要となります。(direct/indirect/none)
**attestation = direct の登録フロー**
![fido2reg-att.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316098/41367ceb-f242-e4f7-e895-e3ecb8632e0c.png)

またクライントがサポートしていれば、登録時にextentionsのauthnSelにAAGUIDを指定することができます。クライアント側で該当のAAGUIDに一致する認証デバイスがなければ、登録が開始されませんので、登録フローで拒否する上記の対応と組み合わせて使うことも出来ます。


参考までに、これ以外に **authenticatorAttachment** という認証デバイスの種類を固定化するオプションもあります。
(platform/cross-platform/本オプションの指定無し)
**authenticatorAttachment = platform**とすると、機器内蔵のセキュリティ(TPM等)が強制されます。
指定無しの場合は、platform(内蔵機器）ーー＞cross-platform(USBなど外部デバイス)の順で、どちらかがあれば動作します。


###(4)ログインIDを入れる手間も省きたい
**「FIDO2のオプション」Resident Key** を利用します。
 (true/false)
**residentkey = true の登録フロー**
RPサーバーからの登録処理時にresidentKey=trueであれば、認証デバイスの鍵ペア生成処理の時に鍵以外に、ログインIDに紐付いたuserid,name,displaynameも格納されます。このdisplaynameは認証デバイス利用時に鍵選択のリスト表示に使われます。管理者と一般ユーザー両方で鍵登録をしている場合などに、どちらがどのログインIDと紐付いているか分かる情報が入っていると好ましいです。
![fido2reg-resident.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316098/d250cee8-7807-c759-53aa-7ce967e0af9b.png)


**residentkey = true の認証フロー**
ログイン画面にログインIDの入力は不要です。ボタンを押すなどのアクションだけでFIDO2の認証シーケンスが開始可能です。
認証デバイスの動作に依存しますが、認証デバイスに格納されたログインID(name)、displaynameが選択肢の確認で表示されます。
![fido2auth-resident.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316098/a6aee0d0-d094-8cbb-b833-00aca3bc33ac.png)



###(5)認証デバイス側のローカル認証(PIN入力など)を必須にしたい
**「FIDO2のオプション」User Verification** を利用します。
RPサーバーからの認証要求に **userVerification = required** を含めると、
認証デバイスの署名処理の前に認証を要求されます。
この認証にパスすれば、認証に成功した旨がRPサーバーへの応答に含まれます。
 (discouraged/preferred/required)
**userVerification = required の認証フロー** 
![fido2auth-userVeri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316098/769e0211-bf5a-5f13-3051-4e19bdc8bedd.png)


##今後
今年リリースされたGoogleのPixel3(Titan M)や、Apple MacBook Air Retina(Apple T2)などモバイルデバイスへのセキュリティチップと指紋リーダーの搭載は進んでいます。
FIDO2でストレス無く認証が行える時代が来ていると思います。
個人的にはMacBook(12")に早く指紋リーダーとApple T2が載って欲しい...
あとTPM2+FingerPrintReaderがFIDO2 on Linuxで使えるようになって欲しい