WWDC Quick Look 💓 By SwiftGGTeam
What’s new in passkeys

What’s new in passkeys

元の動画を見る

ハイライト

iOS、iPadOS、macOS、visionOS 26 では、passkey のライフサイクルを「登録・メンテナンス・アップグレード・発見・移行」の 5 つのフェーズに分け、それぞれに新しい API が追加されました。


主要内容

従来のサインアップフローは、ユーザーにとって負担の大きいものでした。「メールで登録」をタップしたあと、メールアドレスを入力し、姓名を入力し、強力なパスワードを生成し、続行をタップする——少なくとも 4 ステップを踏む必要があります。FIDO Alliance の 2025 年の調査では、すでに 69% のユーザーが少なくとも 1 つの passkey を持っていると回答しています。Google の発表によると、パスワードユーザーのサインイン成功率は passkey ユーザーの 4 分の 1 にとどまります。TikTok では passkey でのサインイン成功率が 97% に達しています。それにもかかわらず、サインアップは依然としてパスワードフォームを通る形が一般的で、passkey は後付けの存在であり、出発点になっていませんでした。

Account Creation API はこのサインアップ体験を作り直すものです。ユーザーがサインアップをタップすると、システムが直接 Sheet を表示し、氏名・メールアドレス・これから作成される passkey がすべてプリフィルされた状態で出てきます。Face ID で認証すれば完了です(03:43)。プリフィルされたフィールドは編集可能で、フィールドをタップすると picker が表示され、システムが提案する候補値を選ぶことも、手入力することもできます。このやり取りは Apple 純正のパスワード App やサードパーティのクレデンシャルマネージャと連携しており、アカウントは最初の瞬間から passkey を持った状態で作成されます。一度パスワードアカウントを作ってから「アップグレード」する必要はありません。

残り 4 つのアップデートは、passkey のその後のフェーズに対応するものです。Signal API は、ユーザー名の変更、passkey の失効、パスワード削除といった操作が App 側で行われた際に、クレデンシャルマネージャに通知して古い情報が表示され続けることを防ぎます。Automatic Passkey Upgrade は、既存のパスワードアカウントでサインインに成功した直後に、UI を出さずに passkey をサイレントに生成します。Passkey Management Endpoints は well-known URL の標準仕様で、クレデンシャルマネージャが enroll/manage URL を読み取り、ユーザーに能動的にアップグレードを促すことができます。Import/Export はクレデンシャルを異なるクレデンシャルマネージャ間で直接移行するための仕組みで、中間ファイルが残りません。

詳細

サインアップの中核となるコードは 1 ブロックだけです(06:33)。ASAuthorizationAccountCreationProvider を生成し、createPlatformPublicKeyCredentialRegistrationRequest でリクエストを作り、ASAuthorizationController に渡して実行する、という流れです。

@Environment(\.authorizationController) var authorizationController

func performPasskeySignUp() async throws {
    let provider = ASAuthorizationAccountCreationProvider()
    let request = provider.createPlatformPublicKeyCredentialRegistrationRequest(
        acceptedContactIdentifiers: [.email, .phoneNumber],
        shouldRequestName: true,
        relyingPartyIdentifier: "example.com",
        challenge: try await fetchChallenge(),
        userID: try await fetchUserID()
    )

    do {
        let result = try await authorizationController.performRequest(request)
        if case .passkeyAccountCreation(let account) = result {
            // Register new account on backend
        }
    } catch ASAuthorizationError.deviceNotConfiguredForPasskeyCreation {
        showPasswordSignUpForm = true
    } catch ASAuthorizationError.canceled {
        showPasswordSignUpForm = true
    } catch ASAuthorizationError.preferSignInWithApple {
        await performSignInWithApple()
    } catch { ... }
}

ポイントは次のとおりです。

  • acceptedContactIdentifiers は、App が受け取れる連絡先識別子の種類を宣言します。ここでは .email.phoneNumber の 2 つを渡しています。最終的にユーザーから返ってくるのはどちらか 1 つで、その値はそのまま passkey の user name ラベルとしても使われます。
  • shouldRequestName は氏名を要求するかどうかのフラグです。必要でない限りオフにし、入力フィールドは 1 つでも減らすのが望ましいでしょう。
  • relyingPartyIdentifierchallengeuserID は通常の passkey 登録と同じ意味を持ちます。それぞれドメイン、サーバー側で発行する一度きりの challenge、安定した一意のアカウント ID です。
  • 3 つの特定エラーは個別に処理する必要があります。deviceNotConfiguredForPasskeyCreation はデバイスにパスコードが設定されておらず passkey を作成できない状態で、従来のフォームにフォールバックします。canceled はユーザーがシステム Sheet を閉じた場合で、こちらも同じくフォールバックします。preferSignInWithApple は、App が Sign in with Apple をサポートしている場合のみ投げられるエラーで、ユーザーがすでに Sign in with Apple のアカウントを持っていることを意味します。この場合は Sign in with Apple のリクエストを発行し、既存アカウントへ着地させます。
  • performRequest の戻り値である ASAuthorizationResult から .passkeyAccountCreation(let account) を unwrap することで、contact identifier、氏名(要求した場合)、passkey オブジェクトを取得できます。

2 つ目は Signal API です(12:3013:07)。ユーザーが App 内でメールアドレスを変更したら、ASCredentialUpdater().reportPublicKeyCredentialUpdate を呼び出して新しい名前をクレデンシャルマネージャに伝えます。passkey を失効させた場合は、reportAllAcceptedPublicKeyCredentials に有効な credential ID の集合を渡せば、クレデンシャルマネージャは集合に含まれない passkey を削除します。Web 側には対応する API として PublicKeyCredential.signalCurrentUserDetailssignalAllAcceptedCredentials が用意されています。

3 つ目は Automatic Passkey Upgrade です(15:36)。

func signIn() async throws {
    let accountDetails = try await signInWithPassword()
    guard !accountDetails.hasPasskey else { return }

    let provider = ASAuthorizationPlatformPublicKeyCredentialProvider(
        relyingPartyIdentifier: "example.com")

    let request = provider.createCredentialRegistrationRequest(
        challenge: try await fetchChallenge(),
        name: accountDetails.userName,
        userID: accountDetails.userID,
        requestStyle: .conditional
    )

    do {
        let passkey = try await authorizationController.performRequest(request)
        // Save new passkey to the backend
    } catch { ... }
}

ポイントは次のとおりです。

  • 起点はパスワードでのサインインに成功した直後です。アカウントに既存の passkey がないことを確認してから登録リクエストを発行し、重複作成を避けます。
  • requestStyle: .conditional がスイッチの役割を担います。これを指定したときだけ、システムはサイレント経路を辿ります。条件を満たさない場合(たとえばデバイスが passkey をサポートしていないなど)はサイレントに失敗し、UI は出ず、ユーザーの体験を妨げません。
  • 成功するとシステム通知が表示され、passkey が追加されたことがユーザーに知らされます。失敗時には何も表示されず、次のサインイン時に再度試せばよいので、コストはゼロです。

重要ポイント

  • やること: 新規サインアップ経路をすべて Account Creation API に切り替え、従来のフォームはフォールバックとして残します。

    • なぜやる価値があるか: サインアップ手順が 4 ステップから Face ID 1 回に圧縮され、ユーザーが手にするのはパスワードアカウントではなく passkey 付きアカウントになります。サインイン成功率は明確に向上します。
    • 始め方: ASAuthorizationAccountCreationProvider を使ったフローを実装し、deviceNotConfiguredForPasskeyCreationcanceled のときはフォームにフォールバックします。App が Sign in with Apple をサポートしている場合は、preferSignInWithApple も処理して既存アカウントへ誘導します。
  • やること: ユーザー名変更、アカウント削除、passkey 失効など、すべての関連動線で Signal API を呼び出し、クレデンシャルマネージャを常に最新状態に保ちます。

    • なぜやる価値があるか: クレデンシャルマネージャに古いユーザー名や失効済みの passkey が残っていると、サインインで詰まる原因になります。これは passkey 体験の中で最も起きやすい潜在的失敗点です。
    • 始め方: アカウント設定でメールアドレスを変更したら reportPublicKeyCredentialUpdate を呼び出します。失効リストを更新したら reportAllAcceptedPublicKeyCredentials に現時点で有効な ID の集合を渡します。ユーザーが完全に passkey へ移行したら reportUnusedPasswordCredential を呼び、古いパスワードをクレデンシャルマネージャから消します。
  • やること: 既存のパスワードユーザー向けに Automatic Passkey Upgrade を有効化し、パスワードでサインインするたびに 1 度試行します。

    • なぜやる価値があるか: 既存のパスワードアカウントは passkey 普及における最大の障壁です。サイレントアップグレードによりユーザーが意識することなく passkey に移行し、次のサインインから Face ID の恩恵を受けられます。
    • 始め方: パスワードサインイン成功時のコールバックで hasPasskey を確認し、なければ requestStyle: .conditional を指定した registration リクエストを発行します。失敗した場合は何もしません。
  • やること: サーバー側で /.well-known/passkey-endpoints を実装し、enroll と manage の URL を公開します。

    • なぜやる価値があるか: クレデンシャルマネージャがこのエンドポイントを参照できるようになり、ユーザーがまだパスワードを使っている段階で能動的に passkey へのアップグレードを促せます。サービス側にとっては実質的に無料の流入経路がもう 1 つ増える形です。
    • 始め方: well-known パスで JSON を返し、enroll と manage の 2 つの URL を列挙します。サインインページ側では、これらのディープリンクを受け取って対応する登録・管理フローへ着地させます。

関連セッション

  • Integrate privacy into your development process — プライバシー設計をプロダクト企画段階に前倒しする話で、passkey のプライバシーデフォルト思想と同じ系譜です。
  • Supercharge device connectivity with Wi-Fi Aware — Wi-Fi Aware のデバイス発見と passkey のクロスデバイス同期は補完関係にある機能です。
  • What’s new in UIKit — UIKit 26 の新しいメニューバーやテキストコントロールは、システム標準の passkey Sheet と組み合わせてサインインページの体験を向上させます。
  • Meet Passkeys (WWDC22) — 本セッションの予習にあたる回で、passkey の基本 API や prefer immediately available credentials を解説しています。

コメント

GitHub Issues · utterances