FLINTERS Engineer's Blog

FLINTERSのエンジニアによる技術ブログ

パスキーについて諸々

こんにちは。河内です。 FLNTERS は2024年1月に10周年を迎えるにあたり全社員でブログを書くチャレンジをしています。 この記事は81日目の記事です。

最近パスワードに変わる認証手段としてパスキーという名前をよく聞くようになってきました。 私の生活範囲内だと任天堂アカウントやGoogle、GitHubなどなど、ログインする際にパスキーが選択肢できるサイトが増えてきています。 実際に使ってみたのですが、パスワードが必要なく指紋認証で済むので楽なものです。

私は新しいもの好きなのですぐに乗っかりたいのですが、同時に疑り深いので困った事態が起きないか気になります。 そのあたりについて簡単に調べてみました。

パスキーって?

まずパスキーって何者?という点について Wikipedia の引用です。

https://ja.wikipedia.org/wiki/%E3%83%91%E3%82%B9%E3%82%AD%E3%83%BC

パスキー(英語: Passkeys)は、FIDO Allianceが策定したパスワードレス認証技術。パスワードに代えて生体情報を用いる。

典型的には指紋認証など生体情報での認証後、公開鍵暗号を用いてサーバーとやりとりします。

記憶情報、所持情報、生体情報の複数を組み合わせて認証を強固にすることを多要素認証と言います。 スマートフォンで指紋認証する場合を考えると、スマートフォンの所持(所持情報)と指紋(生体情報)の2要素で認証していることになります。 パスワードは記憶情報のみ(1要素)なので、要素数の観点からパスキーのほうが優れているといえます。 また記憶情報を使わないということは、イコール覚えておくことが減るという意味ですので、人間に優しいと言えます。 人間が記憶できることには限りがありますからね。

公開鍵暗闘を用いるということは、秘密鍵と公開鍵のペアを持っていることになります。 秘密鍵はデバイス上に保存されているので、デバイスを紛失した場合はログインできなくなります。これは悲劇です。 そこでパスキーでは、秘密鍵をクラウドで同期することで様々なデバイスから同じ秘密鍵でアクセスできるようになっているようです。

GitHubでパスキーをつかってみた記事もご参照ください。

blog.flinters.co.jp

パスキーでロックアウトされないか?

私が利用者として一番心配なのは、何らかの事情でログインできなくなることです。 秘密鍵はクラウドで同期されるとのことですが、どの範囲で同期されるのでしょうか? いざ使いたいときに手元の端末に秘密鍵がなくてログインできない…という事態は避けたいです。

同期の範囲は秘密鍵を保存するプラットフォームによって変わります。 例えば iCloud keychain の場合は iCloud keychain が使える範囲、1Passwordなどのパスワードマネージャーの場合はそのパスワードマネージャーが使える範囲になります。 同期の範囲は限定的であり、現状では私にとって十分に広いとは言えなさそうです。

「えっ、じゃあAndroidスマートフォンに保存した秘密鍵(Googleで同期)は macOS の Safari では使えないの?」と思ってしまいますが、端末に秘密鍵が同期されていなくても認証を通す手段があるようです。 QR コードを用いる方法が用意されており、表示された QR コードを秘密鍵を保持する端末で読み取り、読み取った端末で認証する方法です。 (ただしカメラを起動して読み取る必要があるので少し面倒)

認証用QRコード

QRコードによる認証を前提に考えると、カメラの付いた端末に秘密鍵を保持して持ち歩けば、秘密鍵が手元に無くて困ることを防げそうです。 現実的にはスマートフォンになるでしょうか。 (ただし仕事で使う秘密鍵の保存は規定に従ってください。)

所持しているスマートフォンに秘密鍵を保存していた場合に、ログインできなくなることはあるでしょうか? ひとつはアカウントが ban される場合が考えられます。 スマートフォンから写真管理サービスに自動同期された写真が規約違反だと判定されてbanされたケースを見聞きしたこともあり、稀なケースだとは想いますが、可能性としてはゼロではありません。 ban に対応するには、他の認証手段(メールやSMSなど)を通じてパスキーを再設定できるようにしておく必要がありそうです。 また認証情報の定期的なエクスポート・バックアップも被害の軽減に有効だと思います。

以上より、いつでも使いたい秘密鍵については「普段持ち歩くスマートフォンに保存し、万が一のために他の認証手段を用意しておく」というのが良さそうだと思います。

自分が作っているサービスにも実装できる?

プラットフォームが秘密鍵を同期してくれることがわかったので、サービスに組み込む部分は少なそうです。 ウェブサービス提供側としては WebAuthn API による認証を実装すれば良さそうです。

WebAuthn の概要は以下のサイトがわかりやすかったです。

webauthn.guide

新規登録時は navigator.credentials.create() 、認証時は navigator.credentials.get() を使います。 当然ではありますが、APIからは秘密鍵にアクセスできないようになっており、悪意のある JavaScript が実行されても秘密鍵が漏れることは無いようになっています。

サーバー側では、クライアント入力の生成と出力の検証、公開鍵の保存などを実装する必要があります。

WebAuthn.io には WebAuthn API を利用するためのライブラリも紹介されているので、実装時には参考にすると良さそうです。

まとめ

  • パスキーによる秘密鍵の同期範囲は限定的
  • QRコードで他の端末で認証を委譲できる
  • 自前のサービスに対応するには WebAuthn API による認証を実装する