docs: note WebAuthn enrollment denial changed from 403 to 401+step-up-required in 5.3.4 - #373
Conversation
…-required in 5.3.4 #371 changed the stale/factorless-session denial on POST /webauthn/register from a bare HTTP 403 (the filter-chain authorization rule's default) to HTTP 401 with a JSON body carrying error code "step-up-required", matching the passkey delete/rename endpoints so a client can interpret it. That is a consumer-facing response-contract change with no migration note; a client that branched on the 403 for this endpoint (as the demo app's webauthn-register.js did) silently falls back to a generic error. Add a 5.3.3 -> 5.3.4 callout to the enrollment-gating section directing such clients to also treat a 401 with error code step-up-required as the stale-session case. Surfaced by the pre-release demo-app integration test (chromium-step-up E2E). Claude-Session: https://claude.ai/code/session_01KL5qvKVGQLLQDjHToy34vj
ReviewSmall, well-scoped docs-only change — verified the technical claims against the actual code and they check out. Verified correct:
Style/placement:
Minor nitpick (non-blocking): the note says the old response had "no interpretable body," which is accurate for the default Spring Security No code, tests, or security surface changed — nothing further to flag. LGTM. |
There was a problem hiding this comment.
🟡 Changes recommended
The new migration note’s JSON example uses ... (invalid JSON) and should be updated to a valid placeholder format to avoid clients copying an incorrect payload.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds a missing migration note documenting a consumer-facing behavior change in the WebAuthn enrollment endpoint denial response, so client apps can correctly detect the “stale session / step-up required” case when upgrading.
Changes:
- Document that
POST /webauthn/registerstale/factorless-session denial changed from bareHTTP 403toHTTP 401with astep-up-requiredJSON error contract in 5.3.4. - Provide client guidance to branch on the new
401+error=step-up-requiredcondition.
File summaries
| File | Description |
|---|---|
| MIGRATION.md | Adds a 5.3.3 → 5.3.4 callout describing the updated enrollment denial response contract for clients. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
|
||
| **Passkey enrollment is gated when step-up is enabled.** `POST /webauthn/register` now requires an authentication factor issued within `user.security.stepUp.enrollmentTtlSeconds` (default `600`). Without it the feature protected nothing: an attacker holding a session cookie could enroll their own passkey and assert with it to satisfy every other gate. Any factor counts, not the configured `factors` list, so a first passkey can still be registered after an ordinary password or social login. | ||
|
|
||
| > **5.3.3 → 5.3.4 note — enrollment denial response.** Through 5.3.3 the stale/factorless-session denial on `POST /webauthn/register` was a bare `HTTP 403` (the filter-chain authorization rule's default, with no interpretable body). As of 5.3.4 it is `HTTP 401` with a JSON body `{"message": ..., "error": "step-up-required"}`, matching the passkey delete/rename endpoints so a client can recognize it and prompt for a fresh sign-in instead of a passkey retry. If you wrote a client that branched on the `403` for this endpoint, update it to also treat a `401` with error code `step-up-required` as the stale-session case. Re-running the passkey ceremony cannot satisfy enrollment (it accepts any factor and the account may have no passkey yet), so the remedy is a fresh login. |
Summary
Adds a missing migration note for a consumer-facing behavior change introduced by #371.
#371 changed the stale/factorless-session denial on
POST /webauthn/registerfrom a bareHTTP 403(the filter-chain authorization rule's default, no interpretable body) toHTTP 401with a JSON body{"message": ..., "error": "step-up-required"}, via the newStepUpEnrollmentAccessDeniedHandler. This matches the passkey delete/rename endpoints so a client can recognize the denial and prompt for a fresh sign-in. The change shipped without a migration note.This adds a
5.3.3 → 5.3.4callout to the enrollment-gating section of MIGRATION.md telling clients that branched on the old403to also treat a401with error codestep-up-requiredas the stale-session case.How this was found
Surfaced by the pre-release demo-app release-integration test: the demo's
chromium-step-upPlaywright suite failed becausewebauthn-register.jsbranched on the old403and fell back to a generic message. The demo-side fix is in a companion PR on the demo repo; both now pass (step-up suite 8/8).Docs-only change.
https://claude.ai/code/session_01KL5qvKVGQLLQDjHToy34vj