Skip to content

5.0.1

Latest

Choose a tag to compare

@devondragon devondragon released this 16 Jun 01:46

Maven Central: com.digitalsanctuary:ds-spring-user-framework:5.0.1


Features

  • WebAuthn credential-management re-authentication now returns distinct HTTP status codes
    • Affects: DELETE /user/webauthn/password, DELETE /user/webauthn/credentials/{id}, PUT /user/webauthn/credentials/{id}/label
    • Status mapping:
      • Missing/blank currentPassword → 400 Bad Request
      • Incorrect currentPassword → 401 Unauthorized
      • Account locked (too many failed attempts) → 423 Locked
    • Implementation details:
      • Added WebAuthnReauthenticationException (401) and WebAuthnAccountLockedException (423), both extend WebAuthnException (400 default).
      • WebAuthnManagementAPI.requireCurrentPasswordIfSet now:
        • Checks lock first; if locked, throws WebAuthnAccountLockedException (423) before any password verification.
        • Throws WebAuthnException (400) when currentPassword is missing/blank; this does not count toward lockout.
        • On wrong password, increments LoginAttemptService, then throws WebAuthnReauthenticationException (401).
        • On success, clears failed-attempt counter via LoginAttemptService.loginSucceeded to mirror login semantics.
      • WebAuthnManagementAPIAdvice maps subtypes to precise statuses; base WebAuthnException remains 400.
    • Client impact:
      • These endpoints were introduced in 5.0.0 and previously returned 400 for all failures; clients can now branch on 400/401/423 to give better UX.
      • If a client already treated any 4xx as “re-auth failed,” no change is required.

Fixes

  • Security: trustedHosts matching is now case-insensitive (RFC 4343)
    • AppUrlResolver normalizes configured user.security.trustedHosts to lower case and lower-cases X-Forwarded-Host during comparison.
    • Prevents legitimate mixed-case hosts (e.g., App.Example.Com) from being ignored on the CWE-640 path, which previously forced a fallback to the container’s server name.
    • Continues to honor only the first entry in a multi-valued X-Forwarded-Host (proxy chains).
  • Model: revert Role.privileges to FetchType.EAGER (User.roles remains LAZY)
    • Addresses LazyInitializationException footgun when calling role.getPrivileges() outside an open transaction/session, for negligible performance gain.
    • Rationale: privileges are small, static reference data; there’s no bulk-load path across many Roles.
    • Performance is preserved: the authentication path still loads User → roles → privileges in one round trip via UserRepository.findWithRolesByEmail using @EntityGraph.
    • Repository Javadoc clarified: the two-level entity graph yields a Cartesian product of roles × privileges that Hibernate de-duplicates via Sets; acceptable for a single user.

Breaking Changes

  • Refined HTTP statuses on WebAuthn credential-management re-authentication failures
    • In 5.0.0, missing/incorrect/locked cases all returned 400; in 5.0.1 they return 400/401/423 respectively.
    • These endpoints are new as of 5.0.0. Most clients won’t break if they handled any 4xx generically; update only if you explicitly expected 400 for all re-auth failures.

Documentation

  • CHANGELOG and MIGRATION updated to document:
    • New WebAuthn re-authentication status codes (400 missing, 401 incorrect, 423 locked) and endpoint list.
    • Role.privileges reverted to EAGER; guidance focuses on laziness only for User.roles.
    • Clarified that the entity-graph load is a “single round trip” (bounded, typically one query).
    • JPA note: @EntityGraph fetch results in a roles × privileges Cartesian product, de-duplicated by Sets; fine for single-user loads, not intended for bulk loads.
    • Tokens (PasswordResetToken, VerificationToken): getUser() is EAGER for detached access; the associated User’s roles remain LAZY—use findWithRolesByEmail when authorities are needed.
  • README updates for 5.0.0 release:
    • Installation snippets bumped to 5.0.0; compatibility table reworked (Spring Boot 4.0.x–4.1.x ↔ framework 5.0.x).
    • Notes that framework versioning is independent of Spring Boot’s major; 5.0.0 is a breaking release with a reverse-proxy configuration requirement (user.security.appUrl or trustedHosts).
    • Spring Boot badge updated to 4.0 | 4.1; spring-retry doc dependency adjusted to 2.0.13.

Testing

  • Added WebAuthnManagementAPIAdviceTest to verify precise exception-to-status mapping:
    • Base WebAuthnException → 400, WebAuthnReauthenticationException → 401, WebAuthnAccountLockedException → 423, WebAuthnUserNotFoundException → 404.
  • Tightened WebAuthn API unit tests to expect specific exception subtypes:
    • Locked accounts now raise WebAuthnAccountLockedException; wrong currentPassword raises WebAuthnReauthenticationException.
    • Verified loginAttemptService integration: wrong password increments failures; success resets.
  • Updated integration tests:
    • Incorrect currentPassword paths now assert 401 (previously 400) for delete/rename credential flows.
  • AppUrlResolverTest
    • New case-insensitivity test to confirm mixed-case allow-list and forwarded host match correctly.
  • Repository tests
    • UserRepositoryEntityGraphTest Javadoc/comments corrected to reflect Role.privileges EAGER and User.roles LAZY; continues to verify that plain findByEmail leaves roles uninitialized.