Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@ All notable changes to this project are documented here. This project follows [S

## [5.3.0] - 2026-08-14

This release types the user.security.* configuration into strongly-typed @ConfigurationProperties, adds a secret-free ${userSecurity} model attribute for templates, and makes misconfigurations loud at startup. It also fixes a rare registration deadlock/misreport and a remember‑me kebab‑case binding regression, and restores two public LoginAttemptService accessors.
This release types the user.security.* configuration into strongly-typed @ConfigurationProperties, adds a secret-free ${userSecurity} model attribute for templates, and makes misconfigurations loud at startup. It also fixes a rare registration deadlock that could silently lose a registration behind a success page, and makes the kebab-case spelling of the remember‑me persistent-tokens option work (previously only the exact camelCase key did).

SemVer classification: minor — adds a new template attribute and startup validation while keeping all config keys stable; constructor signature changes affect only consumers that directly instantiate or subclass framework components.

Expand All@@ -24,17 +24,16 @@ SemVer classification: minor — adds a new template attribute and startup valid
- Remember‑me configuration clarity:
- Enabling remember‑me without a signing key, or setting usePersistentTokens=true without a PersistentTokenRepository bean, now logs explicit warnings (previously silent skip/downgrade).
- Apps using the kebab-case property user.security.remember-me.use-persistent-tokens now get a PersistentTokenRepository as intended; previously only the exact camelCase key user.security.rememberMe.usePersistentTokens triggered the condition, silently downgrading to hash-based tokens (no server-side revocation).
- Registration error semantics under rare database serialization failures: transient deadlocks during POST /user/registration are now retried in a fresh transaction (up to 3 attempts). A genuine same-email race still returns HTTP 409 (anti-enumeration). If retries are exhausted, the API now surfaces an error (HTTP 500) instead of a false success.
- Registration error semantics under rare database serialization failures: transient deadlocks during POST /user/registration are now retried in a fresh transaction (up to 5 attempts with jittered backoff). A genuine same-email race still returns HTTP 409 (anti-enumeration). If retries are exhausted, the API now surfaces an error (HTTP 500) instead of a false success.

### Features
- Typed configuration for user.security.*:
- New @ConfigurationProperties classes: UserSecurityConfigProperties (page/action URIs, URI lists, security scalars), PasswordPolicyConfigProperties (user.security.password.*), and RememberMeConfigProperties (user.security.remember-me.*). All existing config keys are unchanged and continue to bind via relaxed binding.
- Template convenience: a secret-free ${userSecurity} model attribute (UserSecurityUriView via UserSecurityUriControllerAdvice) exposes the configured page/action URIs to Thymeleaf without SpEL bean access. Enabled by default; opt out with user.security.expose-uris-to-model=false.

### Fixes
- Registration deadlock/misreport fixed: concurrent registrations of different emails could deadlock under SERIALIZABLE; the victim was misreported as “user already exists,” rendering the registration‑pending page while no account was created and no email sent. Serialization failures are now retried in a fresh transaction (up to 3 attempts); true duplicates still yield HTTP 409 (anti‑enumeration), and exhausted retries now return HTTP 500 instead of a false success.
- Registration deadlock/misreport fixed: concurrent registrations of different emails could deadlock under SERIALIZABLE; the victim was misreported as “user already exists,” rendering the registration‑pending page while no account was created and no email sent. Serialization failures are now retried in a fresh transaction (up to 5 attempts with jittered backoff); true duplicates still yield HTTP 409 (anti‑enumeration), and exhausted retries now return HTTP 500 instead of a false success. Affects all prior versions.
- Remember‑me kebab‑case binding honored: the persistent-token repository condition now uses the canonical kebab key user.security.remember-me.use-persistent-tokens and matches all relaxed spellings. Previously, only the exact camelCase user.security.rememberMe.usePersistentTokens created the repository; kebab-case silently fell back to hash‑based tokens.
- Public accessors restored for consumers reading lockout settings: LoginAttemptService.getMaxFailedLoginAttempts() and getAccountLockoutDuration() are reintroduced, delegating to UserSecurityConfigProperties.

### Refactoring
- Internal refactor of user.security.* to typed @ConfigurationProperties: UserSecurityConfigProperties (page/action URIs, URI lists, security scalars), PasswordPolicyConfigProperties, and RememberMeConfigProperties. Config keys are unchanged — no consumer configuration action required.
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -121,10 +121,10 @@ Choose the version that matches your Spring Boot version:

| Spring Boot Version | Framework Version | Java Version | Spring Security |
| ------------------- | ----------------- | ------------ | --------------- |
| 4.0.x – 4.1.x | 5.2.x | 21+ | 7.x |
| 4.0.x – 4.1.x | 5.3.x | 21+ | 7.x |
| 3.5.x | 3.6.x | 17+ | 6.x |

> **Versioning note:** This library follows Semantic Versioning for its **own** API; its major version is intentionally **not** aligned with Spring Boot's major version. The 5.2.x line is built and verified against **Spring Boot 4.1.0** and also runs on 4.0.x — all Spring Boot starters are `compileOnly`, so your application picks the exact Spring Boot patch version. The `5.0.x` line is a **breaking release** over `4.4.x`; read the **[Migration Guide](MIGRATION.md)** ("Migrating to 5.0.x") before upgrading — note especially the reverse-proxy `user.security.appUrl` requirement.
> **Versioning note:** This library follows Semantic Versioning for its **own** API; its major version is intentionally **not** aligned with Spring Boot's major version. The 5.3.x line is built and verified against **Spring Boot 4.1.0** and also runs on 4.0.x — all Spring Boot starters are `compileOnly`, so your application picks the exact Spring Boot patch version. The `5.0.x` line is a **breaking release** over `4.4.x`; read the **[Migration Guide](MIGRATION.md)** ("Migrating to 5.0.x") before upgrading — note especially the reverse-proxy `user.security.appUrl` requirement.

### Spring Boot 4.x (Latest)

Expand All@@ -135,13 +135,13 @@ Spring Boot 4.x brings significant changes including Spring Security 7 and requi
<dependency>
<groupId>com.digitalsanctuary</groupId>
<artifactId>ds-spring-user-framework</artifactId>
<version>5.2.0</version>
<version>5.3.0</version>
</dependency>
```

**Gradle:**
```groovy
implementation 'com.digitalsanctuary:ds-spring-user-framework:5.2.0'
implementation 'com.digitalsanctuary:ds-spring-user-framework:5.3.0'
```

#### Spring Boot 4.x Key Changes
Expand DownExpand Up@@ -171,7 +171,7 @@ testImplementation 'org.springframework.boot:spring-boot-starter-security-test'

For projects using Spring Boot 3.5.x with Java 17+:

> **Security-maintenance only.** The `3.6.x` line backports security fixes from the 5.x line that apply to Spring Boot 3.5; new feature development happens on `5.2.x`. If you are on Java 21 / Spring Boot 4, use `5.2.x`.
> **Security-maintenance only.** The `3.6.x` line backports security fixes from the 5.x line that apply to Spring Boot 3.5; new feature development happens on `5.3.x`. If you are on Java 21 / Spring Boot 4, use `5.3.x`.

**Maven:**
```xml
Expand DownExpand Up@@ -214,7 +214,7 @@ Follow these steps to get up and running with the Spring User Framework in your

**Spring Boot 4.0 / 4.1 (Java 21+):**
```groovy
implementation 'com.digitalsanctuary:ds-spring-user-framework:5.2.0'
implementation 'com.digitalsanctuary:ds-spring-user-framework:5.3.0'
```

**Spring Boot 3.5 (Java 17+):**
Expand Down
Loading