Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2024 App ServicesSystem ServicesPrivacy & Security

WWDC24 · 14 min · App Services / System Services / Privacy & Security

Streamline sign-in with passkey upgrades and credential managers

Learn how to automatically upgrade existing, password-based accounts to use passkeys. We’ll share why and how to improve account security and ease of sign-in, information about new features available for credential manager apps, and how to make your app information shine in the new Passwords app.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

  • 0:00 — Introduction
  • 0:38 — Automatic passkey
 upgrades
  • 2:37 — The passkey journey
  • 4:18 — Automatic passkey upgrade sequence
  • 7:46 — Shipping and deploying passkey support
  • 9:17 — Improvements for
 credential managers
  • 10:14 — The new Passwords app!
  • 11:30 — Updating appearance in the Passwords app
  • 12:31 — One-tap verification code setup

Code shown on screen · 5 snippets

Offering a passkey upsell swift · at 0:01 ↗
// Offering a passkey upsell

func signIn() async throws {
    let userInfo = try await signInWithPassword()
    guard !userInfo.hasPasskey else { return }
    let provider = ASAuthorizationPlatformPublicKeyCredentialProvider(
        relyingPartyIdentifier: "example.com")

    guard try offerPasskeyUpsell() else { return }
    let request = provider.createCredentialRegistrationRequest(
        challenge: try await fetchChallenge(),
        name: userInfo.user,
        userID: userInfo.accountID)

    do {
        let passkey = try await authorizationController.performRequest(request)
        // Save new passkey to the backend
    } catch {  }
}
Automatic passkey upgrade swift · at 0:02 ↗
// Automatic passkey upgrade

func signIn() async throws {
    let userInfo = try await signInWithPassword()
    guard !userInfo.hasPasskey else { return }
    let provider = ASAuthorizationPlatformPublicKeyCredentialProvider(
        relyingPartyIdentifier: "example.com")

    let request = provider.createCredentialRegistrationRequest(
        challenge: try await fetchChallenge(),
        name: userInfo.user,
        userID: userInfo.accountID,
        requestStyle: .conditional)

    do {
        let passkey = try await authorizationController.performRequest(request)
        // Save new passkey to the backend
    } catch {  }
}
Modal passkey creation (web) javascript · at 0:03 ↗
// Modal passkey creation

const options = {
    "publicKey": {
        "rp": { … },
        "user": {
            "name": userInfo.user,
            …
        },
        "challenge": …,
        "pubKeyCredParams": [ … ]
    },
};

await navigator.credentials.create(options);
Automatic passkey creation (web) javascript · at 0:04 ↗
// Automatic passkey creation

let capabilities = await PublicKeyCredential.getClientCapabilities();
if (!capabilities.conditionalCreate) { return; }

const options = {
    "publicKey": {
        "rp": { … },
        "user": {
            "name": userInfo.user,
            …
        },
        "challenge": …,
        "pubKeyCredParams": [ … ]
    },
    "mediation": "conditional"
};

await navigator.credentials.create(options);
New Credential provider Info.plist keys xml · at 0:05 ↗
<dict>
	<key>NSExtensionAttributes</key>
	<dict>
		<key>ASCredentialProviderExtensionCapabilities</key>
		<dict>
			<key>ProvidesPasswords</key>
			<true/>
			<key>ProvidesPasskeys</key>
			<true/>
			<key>SupportsConditionalPasskeyRegistration</key>
			<true/>
			<key>ProvidesOneTimeCodes</key>
			<true/>
			<key>ProvidesTextToInsert</key>
			<true/>
		</dict>
	</dict>
</dict>

Resources