Keeping the Authenticator and your Server in Sync
Your server and the user’s credential manager hold separate passkey records and they are not synchronized automatically. If they differ, the account chooser may offer a passkey that the server no longer accepts. The user can complete local device authentication before the login fails. The stale entry may also remain available on later attempts until the credential manager updates it. Where the platform and credential provider support it, signalling can reduce that gap. It is a progressive, best-effort lifecycle capability rather than a UI flow or authoritative source of truth; unsupported integrations must continue to work without it. In a native app the stale credential surfaces through Conditional UI and the app-start overlay, both of which offer whatever the credential manager holds regardless of what your server still accepts.Support (August 2026): Android 15+ via
androidx.credentials 1.6.0 (stable since 8 April 2026). Apple platforms support signalling from 26.0: use legacy ASCredentialUpdater on 26.0–26.1 and current ASCredentialDataManager on iOS, iPadOS, macOS and visionOS 26.2+. For the browser equivalent see the Web Signal API.The three signals
On Android all three are sent through
CredentialManager.signalCredentialState() and carry a JSON string rather than typed fields.
1
When the server rejects an unknown credential
- Send this signal only when the credential ID is conclusively absent from or no longer accepted by server state. Do not send it for invalid signatures, expired challenges, RP or origin mismatch, cancellation, network failure or other transport and verification errors.
- A provider may hide or remove the credential; some providers may later unhide it after a complete accepted-list signal, but do not rely on recoverability or claim that provider action occurred.
2
At an authenticated reconciliation point
- According to a documented schedule, send the complete set of credential IDs your server accepts for that user. Typical points include selected authenticated refreshes and server credential-set changes, subject to platform rate limits.
3
After a successful credential-set mutation
- After creation or server-side revocation, reconcile the complete server-side list while the user is authenticated, subject to availability, coalescing and rate limits. Revocation never waits for the signal.
4
After a profile change
- Report only the fields supported by the current platform so enabled credential managers can choose to update them. Do not block the profile change or claim that an update occurred.
Why server-side Revocation still needs Client Cleanup
Revoking the credential in authoritative server state makes it unusable immediately: every later assertion from it must be rejected. The server may retain an inactive record for audit. What revocation cannot do is remove the stale entry from the user’s locally installed credential manager, because your backend has no direct channel to the user’s password manager. Client-side cleanup can happen only when the user’s client runs again. Signal an unknown credential only after the server confirms that the submitted credential is unknown. Reconcile the complete accepted list on a documented authenticated schedule, including after authoritative credential-set changes and selected refresh points. The schedule should account for capability, coalescing and rate limits; revocation itself must never wait for signalling.Platform differences worth planning for
Apple cannot signal a display name change
Apple cannot signal a display name change
reportPublicKeyCredentialUpdate accepts only newName. The web and Android equivalents carry both name and displayName, so a display name change cannot be signalled from an iOS or macOS app.Android enforces a rate limit
Android enforces a rate limit
Android permits a maximum of 10 calls in any 120-second window; exceeding it results in throttling or rejection.
SignalCredentialRateLimitExceededException carries a retryMillis value, so back off by that amount rather than retrying blind. That exception only exists from 1.6.0, which is one reason to require the stable release rather than an earlier beta.Apple offers a signal with no web or Android equivalent
Apple offers a signal with no web or Android equivalent
reportUnusedPasswordCredential(domain:userName:) tells credential managers that a password is no longer in use. This is directly relevant when retiring passwords on accounts that have moved to passkeys.Background execution is supported on Android
Background execution is supported on Android
Android explicitly supports sending signals from a background context, within the rate limit. No user presence or user verification is required on any platform.
Acceptance criteria
Native signalling does not create or promote passkeys. It reduces stale credential choices after server credential state changes. A signal request is best effort and never proves that a credential provider changed anything.
References
- Relevant criteria:
N3.2-AC02–N3.2-AC04,N3.2-AC07–N3.2-AC10: Web Authentication Level 3: Signal Credential Changes to the Authenticator defines trigger-specific inputs, complete-list safety, metadata semantics and best-effort provider behavior. - Relevant criteria:
N3.2-AC01–N3.2-AC07,N3.2-AC09: Android Developers: Keep credentials consistent with credential providers defines native availability, request types, payloads, the ten-call rolling limit and testing; SignalCredentialRateLimitExceededException definesretryMillis. - Relevant criteria:
N3.2-AC01,N3.2-AC03,N3.2-AC06–N3.2-AC10: Apple Developer: ASCredentialDataManager defines the current interface, supported reports and result semantics; ASCredentialUpdater documents the deprecated 26.0–26.1 interface. - Relevant criteria:
N3.2-AC03–N3.2-AC04,N3.2-AC08: Corbado: WebAuthn Signal API provides implementation experience for reconciliation timing, complete-list safety and provider uncertainty.
Further reading
- Signal API for relying parties, Android Developers
- ASCredentialDataManager, Apple Developer
- What’s new in passkeys, WWDC25 session 279
- WebAuthn Signal API explained, Corbado blog