mirror of
https://github.com/azaion/admin.git
synced 2026-06-21 18:01:10 +00:00
a77b3f8a59
Refreshes _docs/02_document/ to reflect the cycle-2 auth-modernization
+ CMMC hardening landings (AZ-531..AZ-538). Authoritative source for
the ripple set is ripple_log_cycle2.md.
Covered:
- architecture.md (section 1 rewritten, ADRs 6-9 added)
- data_model.md (sessions, audit_events, user columns, migrations)
- system-flows.md (F1 rewritten; F11-F17 added; F2/F7/F9 minor)
- module-layout.md (cycle-2 sub-component table)
- diagrams/flows/flow_login.md (dual-token + MFA)
- components/{01_data_layer,03_auth_and_security,05_admin_api}
- modules/ (12 new, 8 modified — full Argon2id/ES256/MFA/refresh
/mission/session/audit/jwks rollup)
- tests/{blackbox,security,traceability-matrix}
Step 13 (Update Docs) output for cycle 2.
Co-authored-by: Cursor <cursoragent@cursor.com>
3.9 KiB
3.9 KiB
Module: Azaion.Common.Configs.JwtConfig + SessionConfig
Purpose
Configuration POCOs for JWT signing/validation and refresh-token TTLs. Bound from appsettings.json sections JwtConfig and SessionConfig. Both classes live in Azaion.Common/Configs/JwtConfig.cs.
Cycle 2 (2026-05-14) note (AZ-531 / AZ-532) — major reshape:
- HS256 shared-secret signing is gone.
Secretis no longer read by any code path; the property is retained only as a temporary rollback escape hatch (AZ-532 spec).- New:
KeysFolder(PEM directory) andActiveKid(currently-signing key id) for ES256.- New:
AccessTokenLifetimeMinutes(default 15) replaces the oldTokenLifetimeHours(default 4) — short-lived access tokens are now paired with refresh-token rotation.- New companion class
SessionConfigcarries refresh-token TTLs.
Public Interface
JwtConfig
| Property | Type | Default | Description |
|---|---|---|---|
Issuer |
string |
(required) | Token iss claim. Validated by JwtBearer middleware. |
Audience |
string |
(required) | Token aud claim for interactive sessions. (Mission tokens override to satellite-provider; MFA step-1 tokens override to azaion-mfa-step2.) |
KeysFolder |
string |
secrets/jwt-keys |
Directory containing one ES256 PEM per key. The kid is the filename without .pem. |
ActiveKid |
string? |
null |
Kid currently used to sign new tokens. If null, falls back to the first PEM by ordinal filename order with a startup log warning. |
AccessTokenLifetimeMinutes |
int |
15 | Access-token TTL. |
SessionConfig
| Property | Type | Default | Description |
|---|---|---|---|
RefreshSlidingHours |
int |
8 | Each rotation extends expires_at by this many hours from now. |
RefreshAbsoluteHours |
int |
12 | Family is rejected past this many hours since family_started_at, regardless of sliding rotations. |
Internal Logic
None — pure data classes.
Dependencies
None.
Consumers
Program.cs- reads
JwtConfigeagerly to fail-fast on missing Issuer/Audience and to construct theJwtSigningKeyProviderbeforeapp.Build() - registers
Configure<JwtConfig>andConfigure<SessionConfig>for downstream injection
- reads
JwtSigningKeyProvider— readsKeysFolder,ActiveKidAuthService.CreateToken— readsIssuer,Audience,AccessTokenLifetimeMinutesRefreshTokenService— readsSessionConfig.RefreshSlidingHours,RefreshAbsoluteHoursMfaService.IssueMfaStepToken/ValidateMfaStepToken— readsIssuer(audience is hard-coded toazaion-mfa-step2)MissionTokenService.MintToken— readsIssuer(audience is hard-coded tosatellite-provider)
Data Models
None.
Configuration
Bound via builder.Configuration.GetSection(nameof(JwtConfig)) and Configure<SessionConfig>. Override via env vars:
JwtConfig__Issuer=…,JwtConfig__Audience=…,JwtConfig__KeysFolder=/var/lib/azaion/jwt-keys,JwtConfig__ActiveKid=kid-2026-05-14SessionConfig__RefreshSlidingHours=8,SessionConfig__RefreshAbsoluteHours=12
External Integrations
Filesystem (read-only on KeysFolder).
Security
- Private signing keys live on disk only; the JWKS endpoint exports only public components.
chmod 600is applied byscripts/generate-jwt-key.sh. - The legacy
Secretfield is retained but unused; remove on a follow-up cleanup ticket once the rollback window has closed. RefreshAbsoluteHoursis the hard cap on session lifetime — no rotation can extend past it. Bumping above 12 h needs a security review because it directly extends the leak-window of any one refresh token.
Tests
e2e/Azaion.E2E/Tests/JwksTests.cs— exercises the rotation overlap (AC-3) by manipulatingKeysFolderandActiveKid.e2e/Azaion.E2E/Tests/RefreshTokenTests.cs— exercises both the sliding and absolute caps (AC-4).