はじめに
これは Digital Identity技術勉強会 #iddance Advent Calendar 2023 23日目の記事です。
今年も2021年の「JWTの発音問題について」みたいに逆張りクソ野郎ムーブをしようと思います。
タイトルはclickbaitです
私自身業務でWebAuthnのRPを実装しており、WebAuthn Level 2はだいたい読んでおり、実装過程で気づいた記述の不備の指摘を行ったりしています。よって当然WebAuthn/FIDO/Passkeysのメリットは理解しており、タイトルから想像されるような「Passkeysをやめろ」という主張を行うつもりはありません1。一方で、Passkeysの推進を行う言論で見落とされている点がかなりある(ひいては一部ポジショントークのために一部意識的に触れられていない)と感じたので、Passkeysの解決しないもの、Passkeysの実装面で気に入っていない点について書くことにしました。
改めて書きますが、「Passkeysをやめろ」という主張ではなく、「Passkeysを使う上でのトレードオフは存在し、無視するべきでない」という主張です。パスワードを使うよりはPasskeysを使ったほうが遥かにセキュアでUXもよい、を否定するものではありません。DNSSECが万能な技術ではなく、使ったほうがいい場面はあるが、無視できないトレードオフが存在する、というような主張に近いです2。
あとエンドユーザーはPasskeysを使えるなら使ってください。
また、本記事に書かれている話の一部は(Twitter実況を見る限り) 次世代Webカンファレンス2023 の #nwc_passkey
で話されていそうな気がしていますが、私は現地には行けなかったのでTwitter実況でしか内容を把握していません。
きっかけ: 「PasskeyはOpenID Connect(OIDC)を置き換える」はlayer violationである
No, Passkeys is not a drop-in replacement of "Sign in with Google". Passkeys replaces your sign in password to Google. Then other services can use OpenID Connect to "sign in with Google" #rubyconftw
— sylph01 (@s01) 2023年12月15日
このtweetは RubyConf Taiwan 2023の"Let's pop into Passkeys"という発表 の質疑応答にて「PasskeysはLogin with Googleを置き換えるか」という質問を受けて書いた文章で、「PasskeysとOIDCは一対一対応する技術ではない」という趣旨で書きました。
でそれを受けて以下のtweetでコメントされるのですが、
No, on MoneyForward ID, it's replacement of "Sign-in with Google / Apple / Yahoo! JAPAN". https://t.co/gSQaYzt1Td
— nov matake (@nov) 2023年12月15日
こういったコメントはPasskeys推進論者から飛んでくるであろう想定問答には入っていたので
(yes, there is an argument of "do we even need OIDC if we can do passwordless login everywhere" but that's another topic)
— sylph01 (@s01) 2023年12月15日
というように、「Passkeysがあまねく行き渡れば別にOIDC要らなくね?」というのは別の話だよ、というコメントをつけていました。ここではそれについて触れようと思います。
17日目のritouさんの記事 で主要な部分はだいぶ触れられているのですが、OIDCの最も重要な点として、Identity Providerからユーザーに関する属性情報が降ってくるという点があります。アカウント新規登録の文脈ではIdPから到達確認済みのメールアドレスが降ってくるなど、連絡先の到達確認や本人確認といったアイデンティティの信頼度を高めるための情報を得ることは単なる認証であるPasskeysでは不可能です。ユーザーへの確実なコンタクト手段が必要なサービスにおいてこの性質は馬鹿になりません。
また、フェデレーション先にアカウントを持っている、ということが特定の意味を持つ場合があります。大学のドメインにアカウントを持っていることで学生であることを確認できる、特定の企業のドメインにアカウントを持っていることで契約の存在が確認できる、などがわかりやすい用途です。組織に紐付いた場合でなくても、SkebがMisskey連携ではなくmisskey.ioという特定のインスタンスへの連携を発表したのにも意味があるように3、フェデレーション先の選定が意味を持つ場合は存在します。
OIDCはPasskeysのカバーしていない機能もカバーしており、原tweetの主張するようにサービスの機能としてUXの観点からOIDCをやめてPasskeysで対応する、ということは理解できますが、1対1で置き換えられるものではなく、Passkeysのカバーしていない機能については別に実装することでカバーされる必要があります。
Q: でもIdPに頼ってるってことはbig techに頼ってるってことでしょ?self-sovereignじゃなくね?OIDCはオワコン、今どきアイデンティティは分散でself-sovereignよ
A: そのくらい本気でparanoia modeになるんだったらbig techあるいはquasi-big-techの提供するパスワードマネージャが提供する機能であるところのPasskeysに依存している時点で不十分です。Syncしないcredentialを使った認証をやっていきましょう4。
もっともKeePassXCで自分でPasskey managementをやる方法もあるので必ずしもsynced passkey即big-or-quasi-big-tech依存ではない、は事実ですが、まあそうするならがんばってください。
PasskeysがWebAuthnに対してPlatform Authenticatorを名乗るのはどうにかしてくれ
言い切ってもよい。Passkeysのこの部分だけはどうにかしてほしかった。
WebAuthnのPublicKeyCredentialには authenticatorAttachment
という値が存在し、 これはAuthenticator(認証器)がブラウザを表示しているデバイスから取り外し可能であるかどうかを示しています。これは platform
(Authenticatorはブラウザを表示しているデバイスの一部である、例としてはWindows Helloなど)と cross-platform
(Authenticatorはブラウザを表示しているデバイスの一部ではない、例としてはYubiKeyなど)のどちらかの値を取ります。1PasswordのPasskeysで動作を確認したところ、Passkeysを用いたPublic Key Credentialは platform
を返します。 確かにクラウドで同期されるcredentialを使っていても「ブラウザを表示しているデバイスの一部」から発されているのはそうなのだけど、このようなcredentialが想定されていなかった時点ではPlatform AuthenticatorはTPMのような5tamper-evidentな領域に秘密鍵が保管されておりそれをデバイスの外に取り出すことができないという性質を仮定していたはずで、このような強いセキュリティ性質を持つcredentialと秘密鍵が(暗号化されているとはいえ)外に出ているようなcredentialを同列に扱うことはTPMの価値を毀損しているといってよいでしょう。
いちおうPasskeysとは必ずしも同期するものを指すのではなく、デバイスに紐付いたものを作ることもできるのですが:
誤解 8: パスキーとは、同期する FIDO クレデンシャルのこと?
FIDO Alliance 公式では当初、「パスキー」を同期する FIDO クレデンシャル、言い換えると Discoverable な FIDO クレデンシャルであると定義していました (Discoverable クレデンシャルとは、ユーザー名の保存されたパスキーで、Android の場合同期のトリガーにもなります) 。しかしその後、すべての FIDO クレデンシャルと書き換えられました。そして、同期するパスキーをシンクパスキー (synced passkey)、デバイスに紐付くパスキーをデバイスバウンドパスキー (device-bound passkey) と言い分けるようになりました。
https://blog.agektmr.com/2023/12/passkey-mythbusting
…とはいえ、これらのPasskeysを区別することなくRPに対して一律に platform
を返してきている時点で標準化の失敗であると考えます。
TPMによって実現されるDevice-bound PasskeysとSynced Passkeysでは根本的に保証されるセキュリティ性質は異なると考えられます。Synced Passkeysは暗号化によってセキュリティが保証されている以上その暗号化キーを知っているかどうか、実質What you knowでしかなく、Device-bound PasskeysはTPMの性質によってWhat you haveの確認ができ、場合によっては指紋認証などを通してWhat you areの確認ができ、より強いセキュリティ保証が得られます6。なのでサービスとしてはこれらのPasskeysの区別がついてほしいと考えるのは自然ですが、一律にPlatform Authenticatorである、と名乗るので、区別をすることができません。
(ここから12/23 20時ごろの追記)
すごく厳密を期すならばWebAuthnのattestationを見ればTPMから来ているかどうかはTPM formatを取っているか(+attestationを通るか)で判別が可能。FIDO U2F Attestation Statement Formatをとる場合に限っても、Attested Credential Dataに載っているAuthenticatorのAAGUIDを見て、FIDO Metadata Serviceに問い合わせることでFIDO Authenticator CertificationのLevelを知ることができ、Level 3あるいはLevel 3+であればTPM-backedな認証器と同等の性質を持っているのでそれを以て区別することはできる。…とはいえ、synced passkeysという概念を持ち出す時点でsyncedとdevice-backedの区別が標準に欲しいということについては認証に関わってたら想像できてほしいな…。
まとめ
WebAuthnひいてはFIDOは素晴らしい技術だしPasskeysもUXの問題を解決しており素晴らしい技術なのだけど、実装者としては考慮しなければいけない性質があり、手放しにPasskeys導入ですべて解決、とはなりません。サービスを実装する人はサービスに求められる性質を本当にPasskeysが実現してくれるか見極めて技術を選択していきましょう。いつものことですね。
エンドユーザーとしてはPasskeysやっていきましょう。パスワードマネージャーもいいぞ。本格的にparanoia modeしたい人は素のWebAuthnをやっていきましょう。
もしかしたらここで触れられているPasskeysのcredentialの区別の話もAuthenticator Extensionsとかでなんとかできるのかもしれないけれどそこまでは観測できていません(一応書くにあたって多少掘った)。怖い人はイージーウィンなやつ殴るんじゃなくてそういう方面でのパトロール活動をしてください。
ちなみに
アドカレに登録した時点で書こうと思っていたのは JSON Web Proof vs SD-JWT。どっちにしろ逆張りクソ野郎じゃねえか!
- なのでいくらclickbait titleでも"Passkeys are dead" や "Passkeys considered harmful" というタイトルを選択していないことに注意↩
- その詳細についてはスコープ外なのでここでは触れません。こういう言い方をするというな先生の派閥の人らはPasskeys使うのやめちゃいそうだけど…↩
- クリエイター審査のためにクリエイターが多数存在する大規模インスタンスであるmisskey.ioに一旦限定する形をとっている、という記述がtweet threadから読める↩
-
後述するようにPasskeysとはClient-side discoverable credentialのことであり、自力でcredentialを保管できることが必要となっているため、
YubiKeyなどのU2Fデバイスは2要素目として使うことはできるがこれを認証の第一要素とすることはできず、WebAuthnのcredentialを作ることはできるがdiscoverableではないのでPasskeyになることはできないことに注意(追記12/23: YubiKeyでもU2FのみでなくFIDO2対応を謳っているものであればResident Keys = Discoverable Credentialを作ることができるという指摘がありました)↩ - 以降tamper-evidentな領域に秘密鍵が保管されておりAPIを経由してのみ暗号機能にアクセスが可能であるようなデバイスについて「一般語として」TPMという語を用います↩
- その点でいえば、hybrid transport (旧称caBLE) はTPMを持つデバイスを認証器として利用でき、鍵のsyncを発生させずに済むため、保証すべき性質を減らさずに認証できて都合がよいと言えます(追記12/23: とは言ったものの、結局これも裏で利用されているcredentialの正体についてサーバー側が確証を持つことができないのでダメそう)↩