こんにちは。virapture株式会社でCEOしながらラグナロク株式会社でもCKOとして働いているもぐめっとです。
最近牛宮城へいったのですが、宮迫さんに遭遇することができました。もっとお話してみたかったです。
本日は先日のWWDCで発表があったパスワードを駆逐できるPasskeysについて仕組みや実装法を紹介します。
Passkeysの説明、仕組み、実装といった流れで紹介していきます!
Passkeysとは?
Passkeysはパスワード無しで認証ができてしまうすごい仕組みです。
どんなものか画像をもとに説明します。
サービスに作成されたアカウントにpasskeyを紐付けてみます。
アカウントに対して暗号化されたキーペアが生成され、iCloud keychainに保存されるのでどのapple deviceでも使えるようになります。
Passkeyを使ったサインインができるようになっております。
Webでもサインインが可能です。

友達のPCからログインすることもできます。

ログインするとQRが表示されるのでデバイスで読み取ります。

passkeyでののサイン員を求められるので続けるとサインインができます。

Airdropでpasskeyの共有も可能です。
パスワード一覧からpasskeyを選択します。
共有する相手を選択すると共有できます。

Passkeysの仕組み
Appleデバイスでの認証の仕組み
基本的にはFIDO(FIDO Allianceが策定、標準化する認証に関する仕様)の認証方式に則っています。
Passkeyで登録を始めると、デバイスでアカウントごとに秘密鍵と公開鍵が生成されます。

生成された公開鍵をサーバに保管します。秘密鍵はデバイスに保管されてサインインに使用されます。
サーバは秘密鍵を知ることはないのでデバイスは安全です!

クライアントからサインインを求められたらサーバはchallengeコードをクライアントに求めます
(ちなみにpasskeysはWebAuthnのES256を使ってます)
クライアントは秘密鍵を使ってchallengeコードを署名してサーバに送ります。
サーバは署名されたchallengeコードが正しいものかを公開鍵を使って検証します。
問題なければサインインさせます。

QRを使ったWeb認証の仕組み
認証してほしいクライアントでQRを表示します。
QRの中身は1回しか使えない暗号鍵のペアを暗号化したURLが含まれています。
デバイスはQRをスキャンしたらbluetoothを使ってサーバ情報やルーティング情報をクライアントに送ります。
(この辺のやり取りはローカルで完結するのでサーバは読むことができない)

proximity proofを確認することで、ちゃんと近くにデバイスがあって、メールとかで送られたQRを読み取ってないかチェックしている。
こうすることでフェイクのwebsiteじゃないかというのを確認している。
(リモートにあるフェイクサイトだとbluetooth advertisementで交換することはできない)

ローカルでの検証が終わったら、2つのデバイスはrelayサーバに繋げて、FIDO CTAP規格を使って認証します。

cf: CTAPはFIDO2対応デバイスがBluetooth、USB、または近距離無線通信(NFC)を介して外部/ローミングオーセンティケーターと通信するためのインターフェイスを提供する仕様
Passkeysのデザイン
どんな感じでPasskeysをデザインするかを紹介します。
新しくSF. symbolが使えるようになっているのでこれを使いましょう。

AutoFillを使ってpasskeysが使えるように見せましょう。

複数のアカウントや端末に対応しましょう。

Passkeysの実装方法
仕組みやUIがわかったところで実装方法を紹介します。
PasskeysはSign In With AppleなどのAPIが入っているASAthorization APIに追加されています。
ASAthorization APIを使って実装してく様子を紹介します。
サーバ側の実装
apple-app-site-associationのjsonをサーバに配置します。

チャレンジの発行や検証などのサーバ側の実装はAndroid版ですが、下記を参考にしたらできる・・・かもしれません。(時間がなくて未検証)
iOSの実装
textContentType = .usernameのテキストフィールドを準備します。

最初にサーバからチャレンジを取得します。
その後、Passkeyを実施するためにチャレンジからrequestとproviderを作り、ASAuthorizationControllerに渡してrequestします。

signinが成功するとdidCompleteWithAuthorization callbackが呼び出されるので、サーバに値を渡してあげてサーバで検証を行った上でサインインを完了させます。

その他の実装として、performRequestsにすると後述するnearby deviceなどのpasskeysの全ての機能が有効になります。

Webの実装
inputタグのautocompleteにusernameとwebauthnを指定します。

ブラウザがサポートしてるかチェックしした後に、iOSの時と同じ用にサーバから取得したチャレンジデータを指定してnavigator.credentioals.getを実行します。
その後帰ってきたオブジェクトをサーバに返して検証をした後にサインインさせます。

webでPasskeysを使う場合の補足としては、3点あります。
- Autofill-assistedリクエストをするときは、ページを作る早い段階でリクエストを作りましょう。
- モーダルのWebAuthnリクエストは、ボタンのクリックなど、ユーザの行動で行うようにしましょう。
- Safariの古い認証をリプレースします。既存の認証は引き続き機能し、作成されたデバイスにバインドされますが、新しいプラットフォームの認証はパスキーとして作成されます。パスキーは認証器の妥当性の検証(attestation-statement)を提供しないため、登録時に従来の認証と区別することができます。
様々なログイン方法の実装
ここからは他に3つのログイン方法の実装方法を紹介します。
1. passkeyで複数アカウント
一つのサービスでマルチアカウントを使うことができます。

実装としては、複数の認証情報をrequest.allowedCredentialsに指定してあげます。

2. passkeyを使わない認証に戻す
Passkeysを持っていない端末の場合、デフォルトはQRが表示されますが、そうさせず他の認証方法(今回はパスワードでの認証)を掲示するときに使うケースです。

passkeysでの認証をする際にオプションを指定します。
オプションを指定するとerrorがcallbackでかえってくるようになる

エラーの内容を見て、他の認証方法を表示してあげるかの制御をします。

3. 複合認証リクエスト
パスワードやSignInWithAppleなど複数のサインイン方法を掲示するケースの実装方法を紹介します。

ASAuthorizationControllerを生成するときに複数のauthorizationのrequestを指定するだけです。

callbackも複数のパターンになるのでいい感じに処理してあげましょう。

多要素認証のリスク比較
つまり、Passkeysはどのケースにも強いっす!

もぐめっとの所管
Androidは一足先にFIDOのAPIは持っているようです。
なので頑張ればandroidでもpasskeysのログインはできそうな雰囲気があります。
まとめ
Passkeysをまとめるとこんな感じになります。
- Passkeysはパスワードを駆逐する
- Passkeysはwebでも使える
- 公開鍵と秘密鍵の仕組みを使ってます
最後に、ワンナイト人狼オンラインというゲームを作ってます!よかったら遊んでね!
他にもCameconやOffcha、問い合わせ対応が簡単にできるCSmartといったサービスも作ってるのでよかったら使ってね!
また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。
ラグナロクでもエンジニアやデザイナーのメンバーを募集しています!!楽しくぶち上げたい人はぜひお話ししましょう!!