entry-header-eye-catch.html
entry-title-container.html

entry-header-author-info.html
Article by

パスキーにデフォルトの名前をつける方法について 〜AAGUIDの活用とフォールバックの工夫〜

こんにちは、プラットフォーム開発部で認証認可基盤の開発を担当しているabcangです。

先日pixivでパスキーが利用できるようになりました。パスキーはパスワードに代わる認証方法で、顔認証・指紋認証・PINなどのデバイスの認証機能を使ってpixivや関連サービスにログインすることができます。

パスキーはデバイスやクラウドサービス(iCloudやGoogleなど)ごとに作成する必要があるため、1アカウントで複数のパスキーを作成することは一般的です。そのため、パスキーを削除するときなどに判別しやすくするには、パスキーに適切な名前をつけることが重要になります。しかし、ユーザーに適切な名前をつけてもらうのは大変なので、pixivでパスキーを作成した場合はそれらしい名前をデフォルトで設定しています。今回はそれらしい名前をどうやって設定しているかご紹介します。

AAGUIDを使用する

AAGUID(Authenticator Attestation Globally Unique Identifier)は認証器のモデルの種類を示す一意なIDで、パスキーを作成する際に取得できます。そして、passkeydeveloper/passkey-authenticator-aaguidsというコミュニティ主導のリポジトリがあり、これを使うことでAAGUIDからパスキーのプロバイダーの名前を取得することができます。

これについてはweb.devで紹介されています。 web.dev

AAGUIDが取得でき、それに対応する名前がpasskey-authenticator-aaguidsに登録されている場合、その名前をデフォルトの名前として採用しています。しかし、認証器によってはAAGUIDを取得できない場合があります。例えば、iCloud KeychaninのAAGUIDは2023年の終盤までは取得できませんでした。また、Windows HelloのAAGUIDは PublicKeyCredentialCreationOptions.attestationdirect の場合は取得できますが、 none の場合は取得できません。

attestation のオプションはAttestation(使用した認証器や生成したパスキーのデータの正当性を証明するために使われるデータ)の伝達方法を決めるもので、 Attestationをそのまま受け取りたい場合は direct を指定し、Attestationが不要な場合は none を指定します。

Attestationは主に利用可能な認証器を制限する目的で使われます。しかし、pixivでは認証器の制限の必要性を感じておらず、むしろ認証器を制限するとパスキーを使える機会が減ってしまうため、Attestationの要求自体が必要ないと考えていました。「Attestationを受け取りながらも認証器の制限を行わない」という選択肢もありますが、パスキーの仕様に従うためには受け取ったAttestationをきちんと検証する必要があるため、実装や保守の手間が増えてしまいます。そのため、AAGUIDを取得するためだけに direct を指定することに抵抗がありました。

また、プラットフォーム認証器(デバイスに内蔵されている認証器)ではattestationnone の場合にもAAGUIDを取得できるように仕様を改善する動きがあり、今後はAAGUIDを取得できないケースは減っていく予感がしました。 github.com github.com

そのため、attestation のオプションは none にしつつAAGUIDを取得できない場合はUserAgentを使ってフォールバックすることに決めました。

UserAgentを使う

UserAgentを使うと言っても、単純にUserAgentに含まれるOSやブラウザの名前をつけるのが適切とは限りません。例えば、Windows HelloのAAGUIDを取得できなかった場合にUserAgentをもとに「Windows (Edge)」のような名前をつけると、WindowsのChromeでも使えることに違和感が出てきてしまいます。他にも、iCloud KeychainはiOS、iPadOS、macOSで使えるため、パスキーを作成したときのOSの名前を採用することも必ずしも適切とは限りません。

そこで、OSに備わっているプラットフォーム認証器はある程度決まっているため、AAGUIDが取得できなかった場合はUserAgentのOSの情報からプラットフォーム認証器の名前を推測することにしました。先程挙げた例の場合、Windowsでパスキーを作成した場合は「Windows Hello」をデフォルトの名前にして、iOS、iPadOS、macOSでパスキーを作成した場合は「iCloud Keychain」をデフォルトの名前にします。

ただし、セキュリティキーなどのローミング認証器(デバイスに取り付けて使う認証器)やHybrid transport(プラットフォーム認証器がある別端末をローミング認証器として使う機能)を使う場合はUserAgentから正しく推測することができないため、プラットフォーム認証器で作成したパスキーでしかこの推測方法は使えません。プラットフォーム認証器で作成したかどうかは RegistrationResponseJSONauthenticatorAttachment フィールドが platform になっているかどうかで確認できます。また、そもそもパスキーを作成する際の authenticatorSelection.authenticatorAttachment オプションを platform にすることでプラットフォーム認証器でしかパスキーを作成できないようにするやり方もあります。

他にも注意点があり、OSに備わっているプラットフォーム認証器以外のブラウザ独自の認証器やサードパーティ製の認証器を使える場合は正しく推測できない場合があります。例えば、macOSのChromeではiCloud Keychain以外にChrome独自の認証器が使用できて、AAGUIDも取得できます。macOSのChrome独自の認証器のようにAAGUIDを取得できる場合は判別ができますが、AAGUIDが取得できない場合は判別できないため正しく推測できません。このようなケースは稀だとは思いますが、この場合はAAGUIDとそれに対応する名前が取得できるようになるまでの間はユーザー自身で適切な名前に変えてもらうしかなさそうです。

また、Linuxのようなプラットフォーム認証器がないOSの場合もブラウザ独自の認証器やサードパーティ製の認証器を使うことでパスキーを作成できますが、この場合はプラットフォーム認証器の名前を推測しようがないためやむを得ずUserAgentから抽出したOSやブラウザの名前を使用しています。この場合もAAGUIDとそれに対応する名前の取得ができるようになるまでの間はユーザー自身で適切な名前に変えてもらうしかなさそうです。

将来的な話

現在、認証器の表示名を取得するための拡張機能が提案されています。 github.com

WebAuthn Level 3の拡張機能の1つである credProps の仕様に追加されるようで、Editor’s Draft, 31 July 2024に記載がありました。この時点の仕様だと、credProps オプションを true にしてパスキーを作成すると、レスポンスの credProps.authenticatorDisplayName フィールドに認証器の表示名がセットされるようです。

今後この仕様が正式なものになって多くの認証器・ブラウザで利用可能になれば、パスキーのデフォルトの名前をつけるのがより簡単・正確になります。この仕様に限らず、今後パスキーがさらに便利になっていくのが楽しみですね。

ピクシブでは認証認可に興味のあるエンジニアを募集しています。 hrmos.co

20191219004549
abcang
2017年新卒としてピクシブ株式会社に入社。以前は主にRailsエンジニアとしてPawoo(Mastodon)やVRoid Hubなどを開発していましたが、現在はPHPとTypeScriptで認証認可基盤の開発をしています。