2025 Privacy & Security
WWDC25 · 22 min · Privacy & Security
What’s new in passkeys
Discover how iOS, iPadOS, macOS, and visionOS 26 enhance passkeys. We’ll explore key updates including: the new account creation API for streamlined sign-up, keeping passkeys up-to-date, new ways to drive passkey upgrades through automatic passkey upgrades and passkey management endpoints, and the secure import/export of passkeys. Learn how these improvements enhance user experience and security, and how to implement these updates in your apps to provide a smoother, more secure authentication experience. To get the most out of this video, first watch “Meet passkeys” from WWDC22.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 7 snippets
Account creation
// Account creation
(\.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 { ... }
} Changing the user name
// Changing the user name
try await ASCredentialUpdater()
.reportPublicKeyCredentialUpdate(
relyingPartyIdentifier: "example.com",
userHandle: userHandle,
newName: "[email protected]"
) Changing the user name
// Changing the user name
await PublicKeyCredential.signalCurrentUserDetails({
rpId: "example.com",
userId: userHandle,
name: "[email protected]",
displayName: "[email protected]"
}); Revoking a passkey
// Revoking a passkey
try await ASCredentialUpdater()
.reportAllAcceptedPublicKeyCredentials(
relyingPartyIdentifier: "example.com",
userHandle: userHandle,
acceptedCredentialIDs: acceptedCredentialIDs
) Revoking a passkey
// Revoking a passkey
await PublicKeyCredential.signalAllAcceptedCredentials({
rpId: "example.com",
userId: userHandle,
allAcceptedCredentalIds: acceptedCredentialIds
}); Removing a password
// Removing a password
try await ASCredentialUpdater()
.reportUnusedPasswordCredential(
domain: "example.com",
username: "[email protected]"
) Automatic passkey upgrade
// Automatic passkey upgrade
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 { ... }
} Resources
Related sessions
-
33 min -
14 min