Upgrade to Pro — share decks privately, control downloads, hide ads and more …

認証体験向上のために passkeys (パスキー) に対応する 〜 メリット・対応方法について / iosdcjapan-2023-passkeys

認証体験向上のために passkeys (パスキー) に対応する 〜 メリット・対応方法について / iosdcjapan-2023-passkeys

iOSDC Japan 2023 の トーク「認証体験向上のためにpasskeys(パスキー)に対応する 〜 メリット・対応方法について」の発表資料です。

プロポーザル

https://fortee.jp/iosdc-japan-2023/proposal/b603f798-e7f5-487d-a8f0-7d48d952fad1

kotetu (kotetuco)

September 03, 2023
Tweet

More Decks by kotetu (kotetuco)

Other Decks in Technology

Transcript

  1. 栗山 徹 (@kotetu) - iOSDC Japan 2023 (2023/09/03) 認証体験向上のために passkeys

    (パスキー) に対応する 〜 メリット・対応方法について 1
  2. (くりやま とおる) • X (Twitter) : @kotetu • 株式会社アンドパッド テックリード

    • パンフレット原稿も書きました! • Swift Markdownを使ったMarkdown アプリ開発 栗山 徹 3
  3. • 認証器 (iOS/iPadOS/macOSが担当) • 生体認証 (Face ID or Touch ID)

    • 暗号鍵(公開鍵・秘密鍵)の生成と管理 • サーバー • IDと認証器で作成された公開鍵のペアを認証情報として保持 • アプリ • 認証器 - サーバー間の中継 passkeysにおける登場人物 22
  4. ೝূث ೝূ੒ޭ ൿີ伴ɾެ։伴 ੜ੒ ΞϓϦ ೝূɾ νϟϨϯδ΁ͷॺ໊Λཁٻ αʔόʔ ॺ໊͞Εͨ νϟϨϯδ

    Λݕূ Ϣʔβʔ αΠϯΞοϓૢ࡞ νϟϨϯδཁٻ Face ID, Touch ID ೝূ νϟϨϯδฦ٫ ೖྗ ެ։伴ͱ ൿີ伴Ͱॺ໊͞ΕͨνϟϨϯδ Λฦ٫ ެ։伴ͱ ॺ໊͞ΕͨνϟϨϯδ Λ౉͢ ݕূ੒ޭ ೝূ੒ޭ αΠϯΞοϓ੒ޭදࣔ • チャレンジ • ランダムな文字列、リクエスト 毎に生成 • 認証(証明書の検証)で使用 • 署名されたチャレンジの検証 • 一緒に渡された公開鍵を使用  して検証 サインアップの流れ 23
  5. ೝূث ೝূ੒ޭ ΞϓϦ ೝূɾ νϟϨϯδ΁ͷॺ໊Λཁٻ αʔόʔ ॺ໊͞Εͨ νϟϨϯδ Λݕূ Ϣʔβʔ

    αΠϯΠϯૢ࡞ νϟϨϯδཁٻ Face ID, Touch ID ೝূ νϟϨϯδฦ٫ ೖྗ ൿີ伴Ͱॺ໊͞ΕͨνϟϨϯδ Λฦ٫ ॺ໊͞ΕͨνϟϨϯδ Λ౉͢ ݕূ੒ޭ ೝূ੒ޭ αΠϯΠϯ੒ޭදࣔ • 保存済みpasskeyの選択 • Face ID / Touch ID認証の前に 選択を行う • 署名されたチャレンジの検証 • サインアップ時に保存された 公開鍵を使って検証を行う サインインの流れ 24
  6. • Associated Domains を設定する必要がある • AuthenticationServices フレームワークを使用する • アプリ -

    認証器間のやり取りのためのI/F • ユーザーへ認証UIを表示 • アプリ - サーバー間のやり取りのための I/F は含まれない • 自前で用意する必要がある 対応手順概要 26
  7. • サーバーから challenge を取得する • ASAuthorizationRequest を取得する • 認証画面を表示し、FaceID or

    TouchID で認証 • ASAuthorizationControllerDelegate で認証結果を受け取る • サーバーへリクエストを送り、最終的な認証結果を受け取る 対応手順 (サインアップ) 30
  8. • ASAuthorizationPlatformPublicKeyCredentialProvider を使用する • createCredentialRegistrationRequest メソッド • name : ユーザー名

    (表示名なので一意でなくても良い) • userID : 一意のID (一意である必要がある) 対応手順 (サインアップ) ASAuthorizationRequest を取得する let publicKeyCredentialProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: domain) let registrationRequest = publicKeyCredentialProvider.createCredentialRegistrationRequest( challenge: challenge, name: userName, userID: userID ) 32
  9. • ASAuthorizationController を使用する • delegate (ASAuthorizationControllerDelegate) を設定 • presentationContextProvider (ASAuthorizationControllerPresentationContextProviding)

    を設定 • performRequests メソッドを呼び出すと表示される 対応手順 (サインアップ) 認証画面を表示し、FaceID or TouchID で認証 let authController = ASAuthorizationController(authorizationRequests: [ registrationRequest ] ) authController.delegate = self authController.presentationContextProvider = self authController.performRequests() 33
  10. • authorizationController(controller:didCompleteWithAuthorization:) • authorization.credential を ASAuthorizationPlatformPublicKeyCredentialRegistration へキャスト 対応手順 (サインアップ) ASAuthorizationControllerDelegate

    で認証結果を受け取る func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let credentialRegistration as ASAuthorizationPlatformPublicKeyCredentialRegistration: . . . default: fatalError("Received unknown authorization type.") } } 34
  11. • ASAuthorizationPlatformPublicKeyCredentialAssertion から下記3プロパテ ィを取り出してサーバーへ送る • rawAttestationObject / rawClientDataJSON / credentialId

    • サーバーから認証結果を受け取り、画面に反映する 対応手順 (サインアップ) サーバーへリクエストを送り、最終的な認証結果を受け取る let rawAttestationObject = credentialRegistration.rawAttestationObject let credentialID = credentialRegistration.credentialID let rawClientDataJSON = credentialRegistration.rawClientDataJSON // TODO: αʔόʔ΁্هσʔλΛૹΓɺฦ͖ͬͯͨೝূ݁ՌΛը໘΁൓ө͢Δ 35
  12. • createCredentialRegistrationRequest メソッド • createCredentialAssertionRequest メソッドへ変更 • challenge のみ指定 対応手順

    (サインイン) モーダル画面を表示して認証 (1 / 2) let publicKeyCredentialProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: domain) let assertionRequest = publicKeyCredentialProvider.createCredentialAssertionRequest(challenge: challenge) let authController = ASAuthorizationController(authorizationRequests: [ assertionRequest ] ) authController.delegate = self authController.presentationContextProvider = self authController.performRequests() 37
  13. • authorizationController(controller:didCompleteWithAuthorization:) • authorization.credential を ASAuthorizationPlatformPublicKeyCredentialAssertion へキャスト 対応手順 (サインイン) モーダル画面を表示して認証

    (2 / 2) func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let credentialAssertion as ASAuthorizationPlatformPublicKeyCredentialAssertion: let credentialID = credentialAssertion.credentialID let rawClientDataJSON = credentialAssertion.rawClientDataJSON let signature = credentialAssertion.signature let rawAuthenticatorData = credentialAssertion.rawAuthenticatorData let userID = credentialAssertion.userID // TODO: αʔόʔ΁ϦΫΤετ default: fatalError("Received unknown authorization type.") } } 38
  14. QuickType バーに passkey 情報を表示して認証 (1 / 2) • ユーザ名を入力する UITextField

    の textContentType を .username に設定す る • 設定した UITextField にフォーカスする と QuickType バーに登録済み passkey 情報が表示される 対応手順 (サインイン) userNameField.textContentType = .username 39
  15. • performAutoFillAssistedRequests メソッドを呼び出す • performAutoFillAssistedRequests メソッドを呼び出さないと QuickType バーに表示されない 対応手順 (サインイン)

    QuickType バーに passkey 情報を表示して認証 (2 / 2) let publicKeyCredentialProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: domain) let assertionRequest = publicKeyCredentialProvider.createCredentialAssertionRequest(challenge: challenge) let authController = ASAuthorizationController(authorizationRequests: [ assertionRequest ] ) authController.delegate = self authController.presentationContextProvider = self authController.performAutoFillAssistedRequests() 40
  16. • passkeys はパスワード認証の置き換えを目指して考案された • passkeys に対応することのメリット • セキュリティ面 (フィッシング等の被害を防止できる) •

    ユーザビリティ面 (パスワード管理の手間から解放される) • アプリの実装には AuthenticationServices フレームワークを使用 • アプリ - サーバー間のI/Fは自前で用意する必要がある まとめ 42
  17. 後夜祭 iOSDC Japan 2023 • 9/26 19:00 ʙ 20:30 •

    オンライン開催 アフターイベント開催します! 44 connpassはこちら! アンドパッド 西 登壇!