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
12 changes: 8 additions & 4 deletions CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ Welcome to the User Framework SpringBoot Configuration Guide! This document outl

## Security Settings

- **Failed Login Attempts (`spring.security.failedLoginAttempts`)**: Number of failed login attempts before account lockout. Set to `0` to disable lockout.
- **Account Lockout Duration (`spring.security.accountLockoutDuration`)**: Duration (in minutes) for account lockout.
- **BCrypt Strength (`spring.security.bcryptStrength`)**: Adjust the bcrypt strength for password hashing. Default is `12`.
- **Failed Login Attempts (`user.security.failedLoginAttempts`)**: Number of failed login attempts before account lockout. Set to `0` to disable lockout.
- **Account Lockout Duration (`user.security.accountLockoutDuration`)**: Duration (in minutes) for account lockout.
- **BCrypt Strength (`user.security.bcryptStrength`)**: Adjust the bcrypt strength for password hashing. Default is `12`.
- **Canonical App URL (`user.security.appUrl`)**: Canonical base URL for security email links (password reset, verification). Set this to prevent Host-header poisoning of those links (CWE-640); when it is unset the framework logs a startup warning and derives the host from the (spoofable) request `Host` header. This demo sets it per profile — `http://localhost:8080` for local/E2E, and an `${APP_URL}` env var in `prd`.
- **Trusted Hosts (`user.security.trustedHosts`)**: Alternative to `appUrl` — a comma-separated allow-list of hosts honored for email links when `appUrl` is not set; a non-allow-listed request host falls back to the first trusted host.
- **Require Canonical App URL (`user.security.requireCanonicalAppUrl`)**: When `true`, startup **fails** unless `appUrl` or a non-empty `trustedHosts` is configured (fail-fast instead of a warning). The `prd` profile enables this.
- **Allow Initial Password Set Without Step-Up (`user.security.allowInitialPasswordSetWithoutStepUp`)**: Controls `POST /user/setPassword`, which lets a passwordless (passkey-only) account set an initial password. As of the framework's SUF-02 hardening this endpoint is **disabled by default** (returns `HTTP 403`) unless you provide a `StepUpService` bean or set this to `true`. This demo sets it `true` in the interactive profiles (`local`, `mfa`, `playwright-test`) so the passkey "set a password" flow works, and leaves it `false` (secure default) in `prd`.

## Mail Configuration

- **From Address (`spring.mail.fromAddress`)**: The email address used as the sender in outgoing emails.
- **From Address (`user.mail.fromAddress`)**: The email address used as the sender in outgoing emails.

## Copyright

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ This demo application tracks the latest version of the Spring User Framework:

| Demo App Version | Spring Boot | Spring User Framework | Java | Branch/Tag |
|------------------|-------------|----------------------|------|------------|
| main (current) | 4.0.x | 4.0.x | 21+ | `main` |
| main (current) | 4.0.x | 5.1.x | 21+ | `main` |
| 1.0.0-springboot3 | 3.5.x | 3.5.x | 17+ | [`v1.0.0-springboot3`](https://github.com/devondragon/SpringUserFrameworkDemoApp/tree/v1.0.0-springboot3) |

### Using Spring Boot 3.x?
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ repositories {

dependencies {
// DigitalSanctuary Spring User Framework
implementation 'com.digitalsanctuary:ds-spring-user-framework:5.0.1'
implementation 'com.digitalsanctuary:ds-spring-user-framework:5.1.0'

// WebAuthn support (Passkey authentication)
implementation 'org.springframework.security:spring-security-webauthn'
Expand Down
7 changes: 7 additions & 0 deletions src/main/resources/application-local.yml-example
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,13 @@ user:
googleEnabled: true # Enable Google registration
facebookEnabled: true # Enable Facebook registration
security:
# Canonical base URL for security email links (SUF-01 / CWE-640). Inherits http://localhost:8080 from
# application.yml; if you expose the app via a tunnel (e.g. ngrok) for OAuth/WebAuthn testing, set this to that
# public URL so emailed reset/verification links are clickable and match your webauthn.allowedOrigins, e.g.:
# appUrl: https://your-tunnel.ngrok.io
# Allow the passkey-only "set initial password" flow to run without a StepUpService (SUF-02). Convenient for local
# demoing; in production provide a StepUpService bean and leave this false.
allowInitialPasswordSetWithoutStepUp: true
# unprotectedURIs: /,/index.html,/favicon.ico,/css/*,/js/*,/js/user/*,/js/event/*,/img/*,/user/registration,/user/resendRegistrationToken,/user/resetPassword,/user/registrationConfirm,/user/changePassword,/user/savePassword,/oauth2/authorization/*,/login,/user/login,/user/login.html,/swagger-ui.html,/swagger-ui/**,/v3/api-docs/**
mail:
fromAddress: you@test.com # From address for outbound mail
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/application-mfa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ user:
mfa:
enabled: true
security:
# Allow the passkey-only "set initial password" flow to run without a StepUpService (SUF-02); the demo has no
# StepUpService bean, so without this the flow returns HTTP 403. In production, provide a StepUpService instead.
allowInitialPasswordSetWithoutStepUp: true
unprotectedURIs: /,/index.html,/favicon.ico,/apple-touch-icon-precomposed.png,/css/*,/js/*,/js/user/*,/js/event/*,/js/utils/*,/img/**,/user/registration,/user/registration/passwordless,/user/resendRegistrationToken,/user/resetPassword,/user/registrationConfirm,/user/changePassword,/user/savePassword,/oauth2/authorization/*,/login,/user/login,/user/login.html,/swagger-ui.html,/swagger-ui/**,/v3/api-docs/**,/event/,/event/list.html,/event/**,/about.html,/error,/error.html,/webauthn/authenticate/**,/login/webauthn,/webauthn/register/options,/webauthn/register
6 changes: 6 additions & 0 deletions src/main/resources/application-playwright-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ user:
googleEnabled: false
facebookEnabled: false
security:
# E2E runs against http://localhost:8080; pin appUrl here so it wins over any ngrok appUrl a developer's
# application-local.yml sets (this profile is typically activated as local,playwright-test).
appUrl: http://localhost:8080
# Allow the passkey-only "set initial password" flow to run without a StepUpService (SUF-02); the demo has no
# StepUpService bean, so without this the flow returns HTTP 403.
allowInitialPasswordSetWithoutStepUp: true
# Test API endpoints are handled by TestApiSecurityConfig with IP whitelist restriction
unprotectedURIs: /,/index.html,/favicon.ico,/apple-touch-icon-precomposed.png,/css/*,/js/*,/js/user/*,/js/event/*,/js/utils/*,/img/**,/user/registration,/user/resendRegistrationToken,/user/resetPassword,/user/registrationConfirm,/user/changePassword,/user/savePassword,/oauth2/authorization/*,/login,/user/login,/user/login.html,/swagger-ui.html,/swagger-ui/**,/v3/api-docs/**,/event/,/event/list.html,/event/**,/about.html,/error,/error.html

Expand Down
8 changes: 8 additions & 0 deletions src/main/resources/application-prd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ user:
rpName: ${WEBAUTHN_RP_NAME:Spring User Framework Demo}
allowedOrigins: ${WEBAUTHN_ALLOWED_ORIGINS:https://example.com}
security:
# Canonical base URL for security email links; driven by an env var in production so links can never derive
# their authority from a spoofable Host header (SUF-01 / CWE-640).
appUrl: ${APP_URL:https://example.com}
# Fail startup unless a canonical appUrl (or trustedHosts) is configured - a hard guarantee for production.
requireCanonicalAppUrl: true
Comment on lines +45 to +49
# NOTE: allowInitialPasswordSetWithoutStepUp is intentionally left at its secure default (false) here. In
# production, setting an initial password on a passkey-only account should require step-up (a StepUpService bean),
# not just an authenticated session (SUF-02).
disableCSRFdURIs: # No CSRF disabled URIs in production for better security
4 changes: 4 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ user:

# Centralizing the URIs of common pages to make changing paths easier. You can leave this section alone if you use the default page locations from this project. These URLs do NOT have to be included in the unprotectedURIs list above as they will automatically be handled.
security:
# Canonical base URL for security email links (password reset, verification). Setting this prevents Host-header
# poisoning of those links (SUF-01 / CWE-640) and silences the library's startup warning. Override per profile
# (e.g. your public/ngrok URL in local, an env var in prod). See application-prd.yml for the fail-fast option.
appUrl: http://localhost:8080
failedLoginAttempts: 10 # The number of failed login attempts before the user account is locked out. Set this to 0 to disable account lockout.
accountLockoutDuration: 30 # The number of minutes to lock the user account after the maximum number of failed login attempts is reached. Set this to 0 to disable account lockout. Set this to -1 to lock the account until an administrator unlocks it.
bcryptStrength: 12 # The bcrypt strength to use for password hashing. The higher the number, the longer it takes to hash the password. The default is 12. The minimum is 4. The maximum is 31.
Expand Down
Loading