Direct Answer
Safari provides no API for a relying party to delete or revoke a stored WebAuthn credential, and there is no documented method to inject expiration alerts into Safari's native WebAuthn UI. Credentials persist in the Secure Enclave or iCloud Keychain until the user manually removes them via Settings → Passwords (iOS) or Safari → Preferences → Passwords (macOS).
Why the Browser Keeps Showing Revoked Credentials
WebAuthn credentials in Safari are scoped to the eTLD+1 and stored in platform authenticators (Secure Enclave on device, synced via iCloud Keychain). The WebAuthn specification does not define a native expiration field, and Safari implements no automatic purge or revocation signaling mechanism. After a relying party revokes a credential server-side, Safari's account chooser will continue to present that credential until:
- The relying party rejects the authentication assertion during the ceremony, and
- The user manually deletes the credential from their device's password manager.
What a Relying Party Can Do
1. Reject Revoked Credentials at Assertion Time
When navigator.credentials.get() returns an assertion, verify the credentialId against your revocation list. If revoked, return an error response (e.g., HTTP 401 with a custom error code) and display your own UI instructing the user to delete the credential.
2. Provide Platform-Specific Deletion Instructions
Because the manual deletion path differs by platform, your error UI should include:
- iOS/iPadOS: Settings → Passwords → [your domain] → Delete Passkey
- macOS: Safari → Settings (or Preferences) → Passwords → [your domain] → Delete Passkey
3. Implement Your Own Expiration Policy
Store a registration timestamp with each credential record. Before initiating navigator.credentials.get(), check whether the credential has exceeded your policy window (e.g., 90 days, 1 year). If expired, show a custom modal or banner before calling the WebAuthn API, then allow the ceremony to proceed or block it per your policy.
What You Cannot Do
- Call any WebAuthn API to remove a credential from the authenticator.
- Send a signal (push, header, JavaScript event) that causes Safari to hide or delete the credential.
- Customize the text, icons, or behavior of Safari's native account chooser dialog.
- Rely on a standard
credential.expiration field—none exists in the current spec.
Practical Verification Steps
- Register a passkey in Safari on a test domain.
- Record the
credentialId returned by navigator.credentials.create().
- Revoke that
credentialId in your RP database.
- Call
navigator.credentials.get() and observe that Safari still lists the passkey in the account chooser.
- Submit the assertion; your server rejects it and returns a custom error.
- Open Settings → Passwords (iOS) or Safari → Preferences → Passwords (macOS) and confirm the passkey remains listed until manually deleted.
- Delete it manually, then repeat
get()—the credential no longer appears.
Assumptions and Uncertainty
- This behavior is consistent across Safari 16+ on iOS 16+, iPadOS 16+, and macOS 13+ (Ventura). Older versions may not support passkeys at all.
- iCloud Keychain sync means a credential deleted on one device may disappear from others, but the timing is not guaranteed and is outside RP control.
- Future WebAuthn levels or Safari releases could introduce a
credentialId exclusion list or revocation signaling, but nothing is standardized or shipped as of the current release train.
One Diagnostic Detail That Changes the Recommendation
If you are using a platform-specific authenticator API (e.g., Apple's ASAuthorizationPlatformPublicKeyCredentialProvider in a native iOS/macOS app rather than Safari WebAuthn), the deletion behavior may differ. Confirm whether your integration is purely web-based (Safari WebAuthn) or includes a native app component.