一週間も間をおかずアドベントカレンダーの記事を書くのはしんどいですね笑
本当は認証サーバーの実装とかもやりたかったんですが、時間がなくてだいぶざっくりした内容になっちゃってます。概要を掴むのに使っていただければ幸いです。
Q. WebAuthnとは?
A. ざっくり言うとパスワードレス認証をwebで行えるようにしたJavascriptAPIです。
各種ブラウザで実装されています。
経緯などは特に役立つものではないので省きます。
知りたい方はこちらが詳しいです。
何ができるの?
A. 認証器と言われるデバイスを通して、パスワードなしで認証が行えます。
具体的には、webサイトのログイン画面で指紋認証やセキュリティーキーでの認証を使ってログインが出来ます。
↓指紋認証の認証器として使えるMacBook ProのTouch ID
何がいいの?
A. 楽で安全です。
なんで楽?
A. 長く複雑なパスワードをいちいち覚えておく必要がありませんし、入力する必要もありません。
必要なことは認証器に指を触れたり、短いPINを入力したりすることだけです。
なんで安全?
A. 後述しますが公開鍵認証を利用しているのでパスワード認証のように保護すべき情報がネットワークに流れません。
閑話休題
二段階認証や二要素認証の話題がたまにニュースになったりしてますが、違いをご存知でしょうか?
認証の際には、本人であることを確認するためにパスワードや指紋などが用いられますが、これらは以下の3種類に分類され、認証の三要素と言われています。
- 知っている要素 : パスワードやPINコードなどの記憶するもの
- 持っている要素 : セキュリティーカードやセキュリティーキーなど所持するもの
- 備えている要素 : 指紋認証や顔認証などの本人の身体的特徴
これらの安全性は"備えている要素 > 持っている要素 > 知っている要素"の順に高いです。
二要素認証とはこれら3つの内、2つを認証に用いる認証方式のことです。
二段階認証は、二要素認証も含まれますが、パスワード認証の後にメールアドレスにワンタイムパスワードを送って認証に用いる場合(どちらも知っている要素)なども含みます。
WebAuthnを用いれば、認証器を持っているという要素と指紋という備えている要素(もしくはPINという知っている要素)を一度に満たすことができます。
実際の処理
では、実際にはWebAuthnでどのような処理が行われているのか見ていきます。
当たり前ですが、登録と認証のフローがあります。
登録フロー
1 ) ユーザーが登録画面で登録を要求します。Webアプリなどを経由して最後には認証サーバーに要求が届きます。
2 ) 認証サーバーから公開鍵クレデンシャル生成オプションというものが返され、アプリケーションサーバーを通ってWebアプリに届きます。
公開鍵クレデンシャル生成オプションはWebAuthn APIを使う際に必要になるパラメータです。
オプションの中身については以下に載っています。
https://developer.mozilla.org/ja/docs/Web/API/PublicKeyCredentialCreationOptions
3 ) Webアプリが返ってきたオプションを引数にnavigator.credentials.create()
というWebAuthn APIのメソッドを叩きます。
4 ) APIが認証器に公開鍵クレデンシャル(後述)を要求します。
6 ) ユーザーが指紋認証・PINなどで本人確認を行います。
7 ) 認証器が本人情報を元に公開鍵クレデンシャルを生成し、APIなどを経由して最終的に認証サーバーに公開鍵クレデンシャルを渡します。
公開鍵クレデンシャルには、認証情報を元に生成された公開鍵や認証器自体の正統性を示す情報、送られてきたオプションのデータが含まれています。
詳細については以下に載っています。
https://developer.mozilla.org/ja/docs/Web/API/AuthenticatorAttestationResponse
8 ) 認証サーバーが公開鍵クレデンシャルの検証・登録を行い、OKだったらWebアプリまでOKのレスポンスを返します。
少し詳細なシーケンス図
認証フロー
1 ) ユーザーがログイン画面で認証を要求します。Webアプリなどを経由して最後には認証サーバーに要求が届きます。
2 ) 認証サーバーから公開鍵クレデンシャル要求オプションというものが返され、アプリケーションサーバーを通ってWebアプリに届きます。
公開鍵クレデンシャル要求オプションも公開鍵クレデンシャル生成オプションと同様にWebAuthn APIを使う際に必要になるパラメータです。
オプションの中身については以下に載っています。
https://developer.mozilla.org/ja/docs/Web/API/PublicKeyCredentialRequestOptions
3 ) Webアプリが返ってきたオプションを引数にnavigator.credentials.get()
というWebAuthn APIのメソッドを叩きます。
4 ) APIが認証器に公開鍵クレデンシャル(署名)を要求します。
今回の公開鍵クレデンシャルには登録時と異なり、デジタル署名も含まれています。この情報によって本人である正統性を証明します。
詳細については以下に載っています。
https://developer.mozilla.org/ja/docs/Web/API/AuthenticatorAssertionResponse
6 ) ユーザーが指紋認証・PINなどで本人確認を行います。
7 ) 認証器が本人情報を元に公開鍵クレデンシャルを生成し、APIなどを経由して最終的に認証サーバーに公開鍵クレデンシャルを渡します。
8 ) 認証サーバーが公開鍵クレデンシャルの検証を行い、OKだったらcookieやトークンを発行しWebアプリまで届けます。
少し詳細なシーケンス図
さいごに
自分のサービスにパスワードレス認証を組み込みたいという方は以下の参考情報が役に立つと思います。
特にWEB+DB PRESSの記事はフロント・バックエンドの実装のサンプルコードも載っているのでおすすめです。