All properties live under the iam. prefix. Everything has a safe default — an empty config
plus dev-mode: true boots.
| Property |
Default |
Description |
iam.enabled |
true |
Master switch — false disables all IAM auto-configuration |
iam.dev-mode |
false |
Generate ephemeral JWT/OAuth2/admin secrets at boot. Local dev only — secrets are logged and don’t survive restarts |
The default algorithm is ES256 (asymmetric), which requires an EC P-256 keypair — a config
that sets only iam.jwt.secret will fail to boot. See Security.
| Property |
Default |
Description |
iam.jwt.algorithm |
ES256 |
ES256 (asymmetric, default — needs a keypair, publishes JWKS) or HS512 (symmetric shared secret) |
iam.jwt.private-key |
— |
ES256 only, required: active signing key, PEM PKCS#8 EC P-256 |
iam.jwt.public-key |
— |
ES256 only, required: public half, PEM X.509/SPKI — published at /.well-known/jwks.json |
iam.jwt.key-id |
— (blank) |
ES256 only: kid for token headers/JWKS; blank derives the RFC 7638 thumbprint |
iam.jwt.verification-keys |
{} |
ES256 only: rotation window, kid → public-key PEM; listed keys stay verifiable and are published in the JWK Set |
iam.jwt.secret |
— |
HS512 only, required: HMAC shared secret, minimum 64 bytes (512 bits), ≥ 8 distinct bytes |
iam.jwt.access-token-ttl |
15m |
Access token lifetime |
iam.jwt.refresh-token-ttl |
7d |
Refresh token lifetime |
iam.jwt.refresh-token-delivery |
BODY |
COOKIE | BODY | BOTH |
iam.jwt.refresh-cookie-name |
iam_refresh_token |
Cookie name when delivery includes COOKIE |
iam.jwt.refresh-cookie-path |
/ |
Path attribute of the refresh cookie |
iam.jwt.refresh-cookie-same-site |
Strict |
SameSite policy for the refresh cookie |
| Property |
Default |
Description |
iam.cache.enabled |
true |
false wires a no-op cache — permissions resolve fresh each request |
iam.cache.store |
memory |
memory (Caffeine, in-process) or redis (shared; requires the redis starter on your classpath) |
iam.cache.permissions-ttl |
5m |
TTL for resolved permissions |
| Property |
Default |
Description |
iam.database.vendor |
postgresql |
Selects the Flyway migration set under db/iam/migration/<vendor> (postgresql, mysql) |
iam.database.migrations-enabled |
true |
Run IAM’s schema migrations at startup via IAM’s own dedicated Flyway (history table iam_flyway_history; your spring.flyway.* is never touched). false = you apply IAM’s SQL yourself |
| Property |
Default |
Description |
iam.multi-tenancy.enabled |
false |
Turn multi-tenancy on |
iam.multi-tenancy.resolution |
[jwt] |
Ordered strategy chain: jwt | header | host | custom IamTenantResolver bean names. First Resolved wins; an unknown-tenant claim rejects the request with 404 (fail closed); no signal falls through to the default tenant |
iam.multi-tenancy.header-name |
X-Tenant-ID |
Header for the header strategy |
iam.multi-tenancy.base-domain |
— |
host strategy: acme.<base-domain> → tenant slug acme; unknown slugs under the base domain are rejected. Blank disables subdomain parsing (custom-domain lookup via IamTenantHostnameSource still applies) |
iam.multi-tenancy.isolation |
row-level |
row-level | schema | database |
iam.multi-tenancy.default-schema |
vendor default |
schema isolation: the schema the DEFAULT tenant (control plane) lives in — public on PostgreSQL when blank |
iam.multi-tenancy.write-guard-enabled |
true |
Reject writes whose tenant ≠ current tenant (row-level mode) |
iam.multi-tenancy.databases.<tenant-uuid> |
— |
database isolation: per-tenant url, username, password, max-pool-size |
| Property |
Default |
Description |
iam.auth.enabled-providers |
[password] |
Authentication providers accepted at /auth/login — built-in password, plus any strategy name of a host IamAuthenticationProvider bean (LDAP, SSO, …) |
| Property |
Default |
Description |
iam.field-security.validate-nullability |
true |
Boot-time fail-fast: refuse to start if any @FieldFiltered-filterable field maps to a NON-nullable response-DTO property (a caller without access would get a contract-violating null). Set false only as a deliberate escape hatch |
| Property |
Default |
Description |
iam.resources.enabled |
true |
Register host business resources at startup |
iam.resources.scan-annotations |
true |
Harvest @RequiresPermission from request handlers |
iam.resources.definitions |
[] |
Explicit declarations: code, display-name, description, actions, fields[code/display-name/sensitive] |
| Property |
Default |
Description |
iam.security.bcrypt-strength |
12 |
BCrypt cost factor (OWASP minimum 10) |
iam.security.cors-allowed-origins |
localhost dev origins |
CORS allow-list |
iam.security.additional-permit-all |
[] |
Extra public routes without replacing the filter chain |
| Property |
Default |
Description |
iam.rate-limit.enabled |
true |
Rate limiting on auth endpoints |
iam.rate-limit.store |
memory |
memory or redis |
iam.rate-limit.rules |
sensible auth defaults |
Per-path max-requests / window-seconds rules |
| Property |
Default |
Description |
iam.default-tenant.name |
Default |
Auto-created tenant’s name |
iam.default-tenant.admin-email |
admin@localhost |
Seeded admin user |
iam.default-tenant.admin-password |
— |
Required in production (dev-mode generates one) |
| Property |
Default |
Description |
iam.oauth2.enabled |
true |
OAuth2/OIDC login support |
iam.oauth2.callback-base-url |
http://localhost:8080 |
Where providers redirect back |
iam.oauth2.frontend-redirect-url |
http://localhost:3000/auth/callback |
Where the SPA receives the result |
iam.oauth2.client-secret-encryption-key |
— |
Exactly 32 bytes; encrypts provider secrets at rest |
iam.oauth2.state-ttl |
10m |
PKCE state lifetime |
iam.oauth2.token-exchange-enabled |
true |
Allow the SPA POST /auth/oauth2/token-exchange one-time-code exchange |
iam.oauth2.default-scopes |
openid email profile |
Default scopes requested from providers that don’t override them |
iam.oauth2.default-auto-provision |
false |
JIT-provision unknown users after OAuth2 login |
iam.oauth2.default-auto-link-by-email |
true |
Link OAuth2 identities to existing users by verified email |
| Property |
Default |
Description |
iam.two-factor.enabled |
false |
TOTP 2FA |
iam.two-factor.issuer |
IAM |
Issuer label shown in the authenticator app / TOTP URI |
iam.two-factor.backup-codes-count |
8 |
Backup codes issued |
iam.password-reset.token-ttl |
60m |
Reset token lifetime |
iam.password-reset.invalidate-sessions |
true |
Kill sessions on password reset |
iam.audit.enabled |
true |
Audit trail |
iam.audit.retention-days |
90 |
Retention window (null = keep forever) |
iam.audit.export-enabled |
true |
CSV export (max-export-rows default 10000) |
iam.token-cleanup.cleanup-enabled |
true |
Purge expired tokens (cleanup-retention default 30d) |
| Property |
Default |
Description |
iam.api.base-path |
/api/iam/v1 |
Base path for all IAM endpoints |
iam.api.swagger-group |
iam |
OpenAPI group name |
| Property |
Default |
Description |
iam.metrics.enabled |
true |
Emit IAM’s Micrometer meters (iam.resolve.duration, iam.cache, iam.check.denied). Meters appear only when micrometer-core + a MeterRegistry are on the classpath (e.g. the Actuator starter); false suppresses them even then. See Observability |
Correlation ids are always on and need no configuration — an inbound X-Correlation-Id header
is reused or a UUID generated, then echoed on responses, added to the SLF4J MDC as
iam.correlation_id, stamped on Problem-Details bodies, and carried onto audit rows.