Spring Security&LINE FIDO2 Serverでパスキー認証を実装する #5 Conditional UI
Spring Security&LINE FIDO2 Serverでパスキー認証を実装してみるお勉強メモです。
今回はWebAuthn Level3 の新機能 Conditional UIを実装してみます。
はじめに
- これはどちらかというと自分用のメモです
- 超雰囲気で実装してます
- この実装が正しいかどうか全然わかっていません
- これまで
Conditional UIとは
WebAuthn Level3で新たに追加された機能で、より簡単にパスワードレスでログインできるUI です。
Conditional UIを使うと今までのモーダルダイアログでなく、パスワードマネージャと似たようなUIでログインできるようになります。
2022/10/1時点、W3Cのスペックで Conditional UI は Editor’s Draft のステータスですが、MacOS VenturaのSafariでは対応しているので早速使ってみたいと思います。
環境
- macOS Ventura beta でやります
- ブラウザは Safari(16.1) です
- LINE FIDO2 Serverはコンテナで動かします
- FIDO2セキュリティキーは mac のタッチIDを使います
作業開始前の状態
Username/Passwordでログインできる状態から作業を始めていきます。
- デモ用にアカウントを登録済みです、以下のいずれかのアカウントでログインできます。
-
user1/password1
,user2/password2
,user3/password3
-
- Source
画面遷移図
詳細図
Conditional UIを実装する
作業開始前の状態からConditional UIを実装しました。
-
基本的には Spring Security&LINE FIDO2 Serverで多要素認証を実装する #4 でやっていることと同じことをしています。
-
以下でConditional UIとしてのポイントだけ書いておきます。
-
Source
画面遷移図
以下図の赤いラインのように、webauthnでログインする経路を追加します。
詳細図
WebAuthn登録の実装
ログイン後のページでWebAuthnクレデンシャルの登録処理を実装します。
ポイント1: 登録時のオプション
WebAuthn登録は navigator.credentials.create()
で行いますが、ポイントは以下
- authenticatorAttachment を "platform" にする
- requireResidentKey を true にする
ポイント2: Attestationのtransports
WebAuthn登録が成功するとAttestationがGetできます。
macOS Ventura の Safari で登録すると transports に "internal" と "hybrid" が入ってきます。
この hybrid はLevel3で追加された項目になります。
hybridの説明を仕様で見てみると
hybrid
Indicates the respective authenticator can be contacted using a combination of (often separate) data-transport and proximity mechanisms. This supports, for example, authentication on a desktop computer using a smartphone.
ってことです。Touch IDで登録すると proximity(近接) ってことになるのでしょうか?ちょっとよくわかりませんがとにかくこういうものがついてきます。
で、問題なのが hybrid をつけたままのAttestationの場合 line-fido2-server でパースできません。(まだ対応していないようです)
なので、取っ払ってしまいます。
これで(無理やりですが)登録Successさせることができます。
WebAuthn認証の実装
WebAuthnでConditional UIを使って認証する部分を実装します。
ポイント1: フォームロード時に実行する
WebAuthnを使った認証は navigator.credentials.get()
を使いますが、これをフォームロード時に実行します。
ポイント2: 認証時のオプション
navigator.credentials.get()
のオプションに
- mediation = "conditional"
を追加します。
このオプションはLevel3で追加されたものです。
PublicKeyCredential.isConditionalMediationAvailable でチェックしてから追加します。
ポイント3: textのautocomplete属性
Login-fido2.html の username text の autocomple属性に webauthn を追加します。
動作確認
登録
認証
textをポイントすると「このユーザーでログインするなら指紋認証してねっ」っていうガイドが出てくるんですが、これがConditional UIだっていう理解です。
モーダルダイアログが出てくるより操作感がいいです。
よくわからなかったこと
とりあえず Conditional UI の動きは確認できましたが、今ひとつ解せない動作がアチコチにありました。
- autocomple属性に webauthn をつけてもつけなくても何も変わりませんでした。
- ↑と関係ありそうですが、一旦
navigator.credentials.get()
が走ってしまうと別のhtmlのtextにポイントしても Conditional UI が出てきてしまいます、これは操作感的には完全に意味不明です...(回避策は見つけられませんでした) - フォームロード時に
navigator.credentials.get()
して裏で非同期でタイムアウト無しで何かやっているんだと思うんですが、このPromiseをキャンセルする方法がありません。(何もしないで画面遷移させるときはキャンセルしときたい気持ち)abortController.abort() ってしても効かないようです。別の方法があるんでしょうか、見つけられませんでした... - textにカーソルがある状態でEnterを押すとWebAuthnのモーダルダイアログが出てきます。「何で?」ってなります。必要ない挙動です。
おつかれさまでした
とりあえず使ってみたかんじだとログインがやりやすくなっていると感じました。
SafariだけでなくChrome, Edgeでも実装されればいい感じになるんじゃないかと思います。
追記
ChromeでのConditional UI
2023/6/18日時点、Chrome(ver 114)でもConditional UIに対応しているため、動作検証を実施しました。
Safariよりもいい感じで動く印象です。
/login
の Username入力欄にConditional UIを仕込んでも違和感なく操作できるため、下図のように /login-fido2
を削除した 画面フローにしました。
ちなみにChromeで登録したパスキーは chrome://settings/passkeys から確認することができます。
各ブラウザでのConditional UI動作状況
2023/6/18時点
- macOS 13.4
- Chrome バージョン 114.0.1823.51 → ⭕対応済
- Safari: バージョン16.5 → ⭕対応済
- Edge: バージョン 114.0.1823.51 → ❌未対応
Discussion