Pass-the-Passkey: A WebAuthn Security Testing Guide
Passkeys make phishing-resistant sign-in practical for more users, but adopting them does not finish the security work. A passkey proves possession of a credential in a particular authentication ceremony. The relying party still has to bind that ceremony to the right account, origin, browser session, and fresh server challenge. The endpoint also has to make it clear which application is asking the user to authenticate.
The Pass-the-Passkey attack class is a useful way to examine what happens when one of those surrounding controls fails. This guide explains the WebAuthn checks that matter, how to test them safely, and how to keep recovery and endpoint behavior from weakening the passkey flow.
What does Pass-the-Passkey mean?
Pass-the-Passkey describes ways attackers can abuse the authentication process around a passkey without extracting the credential's private key. Depending on the weakness, an attacker may target exposed assertion data, weak server-side replay controls, poor session binding, or a convincing native authentication prompt initiated by software the user did not intend to trust.
The name does not mean that passkeys are equivalent to passwords or that their cryptography is broken. Passkeys remain a strong defense against many forms of phishing. The lesson is that cryptographic key protection cannot compensate for a relying party that accepts the wrong assertion or an endpoint that lets malware manipulate the user into approving an unexpected sign-in.
How a secure WebAuthn login should work
A simplified passkey login has two sides:
- The application server creates a fresh challenge and associates it with the login attempt and expected account or user session.
- The browser requests an assertion from the authenticator for the relying party.
- The authenticator signs data that includes the challenge and relying-party context after the required user interaction.
- The browser returns the assertion to the application server.
- The server validates the challenge, origin, relying-party identifier, signature, credential-to-account association, and required authenticator flags.
- The server consumes the challenge and creates an authenticated session only after every check succeeds.
The challenge is not a reusable login token. It is a one-time value that binds a single authentication attempt to the server's current state. If the server accepts it again, accepts it in another session, or fails to validate the origin and relying party, the application can lose important protections even though the private key never leaves the authenticator.
The relying-party controls to verify
Fresh, one-time challenges
Generate unpredictable challenges with enough entropy and a short expiry. Store the challenge server-side or bind it to integrity-protected state that cannot be altered by the client. Mark it consumed after a successful assertion and reject it after expiry, account change, or a new login attempt.
Test both replay and race conditions. Two requests that submit the same assertion at nearly the same time should not create two valid sessions. A challenge should not remain usable after the user restarts the flow or signs out.
Session and account binding
Bind each challenge to the session that initiated it and to the expected account context. Do not accept an assertion created for one browser session in another session, another tenant, or another account's login transaction. Test parallel tabs, account switching, and login links opened in a second browser profile.
This is especially important in multi-tenant applications. A valid credential for one user must not authenticate a session that the application has already associated with a different tenant or identity.
Origin and relying-party validation
Validate the exact expected origin and relying-party identifier according to the WebAuthn flow you support. Do not accept a response just because its signature verifies. Review subdomain behavior, staging domains, custom domains, embedded web views, and mobile deep links so the configured trust boundary matches the product's actual login surface.
Credential, signature, and authenticator data
Confirm that the credential belongs to the account being authenticated, validate the assertion signature, and check the required authenticator data and user-verification policy. Keep registration, authentication, and account-recovery logic aligned so an attacker cannot switch identities between steps.
Replay signals and authenticator counters
A signature counter can help identify some cloned-authenticator or replay behavior, but counters are not uniform across passkey implementations. Synced credentials may not provide a monotonically increasing counter in the way older authenticators did. Treat counter changes as one risk signal where applicable; do not use the counter as a substitute for challenge freshness, single-use enforcement, and session binding.
Session creation and revocation
After successful verification, rotate the application session identifier and apply the same secure cookie, expiry, and revocation controls used for other strong authentication. A passkey assertion should not leave a pre-authentication session with elevated privileges. When the user removes a credential, disables an account, or reports a suspicious login, revoke relevant sessions and refresh tokens through the same identity-control plane.
Test account recovery and fallback authentication
A strong passkey flow can be undermined by a weaker recovery path. Review password reset, email-link recovery, help-desk verification, SMS fallback, remembered devices, and enrollment of a replacement passkey. Ask whether a user who cannot use a passkey can reach the same account with a less protected factor and whether that change is visible to security monitoring.
For each fallback path, document:
- What proof of identity it requires.
- Whether it changes authentication factors or recovery contacts.
- Which existing sessions remain valid afterward.
- Whether the user receives an alert and can reverse an unauthorized change.
- What events are available to the help desk and security team.
Do not disable recovery simply to make the passkey path look stronger. Make recovery proportionate to account risk, resistant to social engineering, and observable.
Endpoint prompts are part of the login surface
Operating-system passkey dialogs can look familiar and legitimate. Malware or an untrusted application may attempt to initiate an authentication prompt at a time the user does not expect. That does not automatically defeat WebAuthn: the user still has to interact, and the relying party still validates the resulting assertion. It does mean endpoint context and user expectations matter.
For managed devices, review which applications can initiate authentication, how application identity is shown, and what endpoint telemetry records. Make the expected sign-in journey predictable. Give users a direct way to report a prompt they did not initiate; do not teach them that every system dialog should be approved or that every dialog should be denied.
For high-value accounts, evaluate device-bound credentials, authenticator attestation, or managed-device requirements where supported. Consider the recovery, privacy, accessibility, and support tradeoffs before enforcing them. These controls can strengthen a passkey deployment but do not replace server-side WebAuthn verification.
A safe passkey security test plan
Run the assessment in staging with dedicated accounts and no real customer, payment, or administrator access. Coordinate with the application and identity owners before testing.
| Test case | Expected result | Evidence to retain |
|---|---|---|
| Submit an assertion with an expired challenge | Reject without creating an authenticated session | Challenge expiry and denial reason, with assertion data redacted |
| Reuse an assertion after a successful login | Reject the replay and preserve the original session state | Single-use challenge state and request correlation ID |
| Submit an assertion in a different browser session | Reject because the challenge is bound to the initiating session | Session IDs or non-sensitive correlation values |
| Change the account or tenant during the ceremony | Reject if the challenge's expected identity no longer matches | Account/tenant context and server decision |
| Use a mismatched origin or relying-party context | Reject according to the configured WebAuthn policy | Validated origin and RP ID, without private user data |
| Complete account recovery and enroll a new credential | Enforce the approved recovery policy and notify the user | Recovery decision, factor change, and notification event |
| Trigger a prompt without a corresponding user action | Surface a reportable event and investigate endpoint context | Process and provider telemetry available in the environment |
Record the challenge identifier or a safe correlation value, request time, origin, relying-party identifier, account context, and decision. Do not store private keys or retain raw assertions longer than your test requires. Never capture or reuse a real employee's authentication assertion.
After a fix, rerun the exact failed case and the neighboring flows: sign-in from another browser, account switching, recovery, credential removal, and session revocation. A code change is not verified until the relying party rejects the original invalid state and still supports the legitimate user journey.
Implementation mistakes that weaken passkeys
- Reusing a challenge across requests or leaving it valid after a login flow ends.
- Associating the challenge with a user but not the browser session or tenant.
- Validating the signature while omitting origin, relying-party, or account checks.
- Treating an authenticator counter as the only replay defense.
- Logging raw assertions or sensitive authenticator data for debugging.
- Leaving a weaker recovery or factor-enrollment path outside the security review.
- Allowing a pre-authentication session to become privileged without session rotation.
- Assuming a native prompt proves that the intended application initiated the sign-in.
Frequently asked questions
Are passkeys completely phishing-proof?
Passkeys are designed to resist common phishing attacks by binding authentication to the relying party. They do not remove risks from compromised endpoints, weak recovery, incorrect server validation, or users being manipulated into approving an unexpected authentication request.
Can a passkey assertion be replayed?
A properly designed relying party should reject a reused assertion by enforcing fresh, one-time challenges and binding each challenge to the initiating session and account context. Test those controls directly; do not assume signature verification alone prevents replay.
Should every organization require device-bound passkeys?
Not necessarily. Device-bound credentials can strengthen controls for high-value accounts, but availability, recovery, device replacement, accessibility, and support requirements differ. Choose policy based on account risk and test the complete enrollment and recovery journey.
What should be logged during WebAuthn authentication?
Log the decision, challenge lifecycle, origin and relying-party validation result, account context, credential identifier in a privacy-conscious form, and a request correlation ID. Avoid recording private keys or raw assertion values that could create new replay or privacy risk.
Passkeys provide a strong foundation when the complete login system preserves their guarantees. Eresus Security can test WebAuthn, recovery, session, and privileged-access flows as part of an application security assessment.
AI Security Starter Training
Request a practical checklist for prompt injection, RAG data leakage, MCP risks, and model-file security before launch.
Related Research
Authentication in AI Applications: LLM Sessions and Data Privacy
AI application authentication guide covering JWT validation, session binding, thread ID access, tenant isolation, RAG authorization, and agent tool permissions.
AI SecurityAI Agent Identity Security: Trace the Path Behind Every Tool Call
Secure AI agents by tracing who can invoke them, which identity they use downstream, and what each tool call can reach.
Related Services
Scope Estimator
Get a rough engagement size before the scoping call.
Estimated engagement
5–7 days