feat(verifier): profile-free response verification helpers#877
Merged
Conversation
Companion of WebauthnOptionsResponse for the verification side. Single autowired entry point (WebauthnResponseVerifier) with forAttestation() / forAssertion() factories returning typed verifiers; verify() returns a WebauthnVerificationResult carrying the credential record, the deserialised PublicKeyCredential and the user entity. Auto-handles credential persistence on attestation (CanSaveCredentialRecord), auto-switches to the conditional creation ceremony when stored options carry mediation=conditional, and wraps validation failures in WebauthnAuthenticationFailureException so controllers can build Signal API payloads from the rich exception context. Pre-validation problems bubble up as BadRequestHttpException for HTTP 400 handling by the Symfony layer.
…rTest openssl_pkey_get_details() returns ec.x / ec.y as raw bigint bytes with leading zeros stripped, so roughly one ECDSA key out of 256 has a 31-byte coordinate. Ec2Key then rejects it with "Invalid length for x coordinate" and the happyPath / tampered tests fail flakily on CI. Pad both coordinates to 32 bytes before packing them into the COSE_Key.
Spomky
added a commit
that referenced
this pull request
May 5, 2026
…881) With the per-controller helpers (PR #876, #877, #880) and the per-verifier origin override (PR #879, #880) all shipped, the bundle's profile-driven configuration is fully redundant. Mark the relevant YAML nodes as deprecated so users get a clear migration message at boot, with no behaviour change. Deprecated YAML nodes (will be removed in 6.0): * webauthn.creation_profiles -> WebauthnOptionsResponse::forCreation() * webauthn.request_profiles -> WebauthnOptionsResponse::forRequest() * webauthn.controllers -> user-written controllers + WebauthnOptionsResponse + WebauthnResponseVerifier * webauthn.client_override_policy -> ClientOverridePolicy built inline + ->withClientOverrides() on the helper * webauthn.allowed_origins -> WebauthnAttestationVerifier / WebauthnAssertionVerifier::withAllowedOrigins(...) * webauthn.allow_subdomains -> WebauthnAttestationVerifier / WebauthnAssertionVerifier::withAllowSubdomains(bool) Single-origin apps that drop allowed_origins entirely keep the W3C-recommended same-origin fallback (CheckOrigin against the request host), which is the expected behaviour for that topology. webauthn.passkey_endpoints stays alive for now: its helper companion is on a separate branch and will arrive in a follow-up PR. webauthn.metadata is intentionally left alone (small, contained, no helper-vs-config duality). No behavioural change: the deprecated nodes still work exactly as before.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Companion of #876 (
WebauthnOptionsResponse) for the response side. Adds a single autowired entry point (WebauthnResponseVerifier) so applications can write their own response controllers without touchingcreation_profiles/request_profilesconfig or the bundle's profile-drivenAttestationResponseController/AssertionResponseController.Design
WebauthnAttestationVerifierandWebauthnAssertionVerifier(returned by the entry-point factories) so IDE autocomplete only proposes the methods relevant to each ceremony.CanSaveCredentialRecordby default. Opt out withwithSaveCredential(false)if your controller wants to own persistence (transactions, extra fields, etc.).mediation: conditional, the verifier transparently switches to the conditional creation ceremony manager (relaxes UV per the W3C spec). One call site, both flows.BadRequestHttpExceptionfor malformed inputs (wrong content type, empty body, deserialisation failure, unknown challenge, response/options type mismatch, RP ID mismatch). Symfony's HTTP layer turns these into HTTP 400 automatically.WebauthnAuthenticationFailureExceptionfor ceremony validation failures, carrying the deserialisedPublicKeyCredential, the underlyingAuthenticatorResponse, thePublicKeyCredentialOptionsand the user entity. Lets controllers build Signal API payloads (signalUnknownCredential, etc.) from a single exception.What's new
Webauthn\Bundle\Service\AbstractWebauthnVerifier(template method: deserialise body, load stored options, delegate validation)Webauthn\Bundle\Service\WebauthnAttestationVerifierWebauthn\Bundle\Service\WebauthnAssertionVerifierWebauthn\Bundle\Service\WebauthnResponseVerifier(autowired entry point)Webauthn\Bundle\Service\WebauthnVerificationResult(typed return value)SaveableInMemoryCredentialRepositoryfixtureDrive-by
@phpstan-ignore-next-lineinWebauthnSignalResponsethat no longer matched on PHP 8.4.Notes
The existing profile-driven controllers stay untouched and supported until 6.0; this is a strictly additive, opt-in API. Documentation PR is web-auth/doc#TBD (will link once opened).