@astram/guard 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/account.controller.d.ts +3 -1
- package/dist/auth/account.controller.d.ts.map +1 -1
- package/dist/auth/account.controller.js +12 -5
- package/dist/auth/auth.controller.d.ts +130 -21
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +537 -143
- package/dist/auth/auth.module.d.ts +15 -1
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +212 -30
- package/dist/auth/connections.d.ts +1 -1
- package/dist/auth/connections.d.ts.map +1 -1
- package/dist/auth/connections.js +14 -3
- package/dist/auth/default-session-facts-projector.d.ts +26 -0
- package/dist/auth/default-session-facts-projector.d.ts.map +1 -0
- package/dist/auth/default-session-facts-projector.js +21 -0
- package/dist/auth/mfa-step-up.d.ts +32 -0
- package/dist/auth/mfa-step-up.d.ts.map +1 -0
- package/dist/auth/mfa-step-up.js +109 -0
- package/dist/auth/pending-mfa-store.d.ts +50 -52
- package/dist/auth/pending-mfa-store.d.ts.map +1 -1
- package/dist/auth/pending-mfa-store.js +103 -61
- package/dist/auth/ports/session-facts-projector.d.ts +5 -0
- package/dist/auth/ports/session-facts-projector.d.ts.map +1 -1
- package/dist/auth/rate-limit/canonical-hint.d.ts +24 -0
- package/dist/auth/rate-limit/canonical-hint.d.ts.map +1 -0
- package/dist/auth/rate-limit/canonical-hint.js +63 -0
- package/dist/auth/rate-limit/trust-proxy-check.d.ts +46 -0
- package/dist/auth/rate-limit/trust-proxy-check.d.ts.map +1 -0
- package/dist/auth/rate-limit/trust-proxy-check.js +94 -0
- package/dist/auth/tokens.d.ts +70 -11
- package/dist/auth/tokens.d.ts.map +1 -1
- package/dist/auth/tokens.js +71 -12
- package/dist/authentication/log-email-sender.d.ts +9 -4
- package/dist/authentication/log-email-sender.d.ts.map +1 -1
- package/dist/authentication/mariadb-api-key-store.d.ts +4 -1
- package/dist/authentication/mariadb-api-key-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-api-key-store.js +31 -7
- package/dist/authentication/mariadb-credential-resolver.d.ts +79 -65
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-resolver.js +116 -73
- package/dist/authentication/mariadb-credential-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-or-totp-verifier.d.ts +21 -3
- package/dist/authentication/mariadb-or-totp-verifier.d.ts.map +1 -1
- package/dist/authentication/mariadb-or-totp-verifier.js +37 -6
- package/dist/authentication/mariadb-profile-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-session-sweeper.d.ts +14 -1
- package/dist/authentication/mariadb-session-sweeper.d.ts.map +1 -1
- package/dist/authentication/mariadb-session-sweeper.js +29 -11
- package/dist/authentication/noop-email-sender.d.ts +12 -0
- package/dist/authentication/noop-email-sender.d.ts.map +1 -0
- package/dist/authentication/noop-email-sender.js +9 -0
- package/dist/authz/cross-tenant-grant-writer.d.ts.map +1 -1
- package/dist/authz/manifest-operation-authority-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-cross-tenant-grant-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js +3 -1
- package/dist/authz/mariadb-policy-store.js +1 -1
- package/dist/authz/mariadb-record-rule-adapter.d.ts.map +1 -1
- package/dist/authz/mariadb-record-rule-adapter.js +1 -4
- package/dist/authz/permission-version-cache.d.ts +38 -0
- package/dist/authz/permission-version-cache.d.ts.map +1 -0
- package/dist/authz/permission-version-cache.js +81 -0
- package/dist/authz/wire-record-authorization.d.ts +25 -1
- package/dist/authz/wire-record-authorization.d.ts.map +1 -1
- package/dist/authz/wire-record-authorization.js +55 -2
- package/dist/completeness/catalog-reconciler.d.ts.map +1 -1
- package/dist/config/app-config.d.ts +36 -0
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js +44 -4
- package/dist/encryption/local-kek-crypto.d.ts.map +1 -1
- package/dist/enforcement/enforcement.module.d.ts.map +1 -1
- package/dist/enforcement/enforcement.module.js +9 -0
- package/dist/enforcement/engine-error.filter.d.ts +57 -0
- package/dist/enforcement/engine-error.filter.d.ts.map +1 -0
- package/dist/enforcement/engine-error.filter.js +118 -0
- package/dist/enforcement/global-enforcement.guard.d.ts +29 -2
- package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
- package/dist/enforcement/global-enforcement.guard.js +143 -5
- package/dist/identity/auth-facts.controller.d.ts.map +1 -1
- package/dist/identity/permission-facts.adapter.d.ts.map +1 -1
- package/dist/identity/permission-facts.adapter.js +2 -3
- package/dist/index.d.ts +12 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -25
- package/dist/module/shield.module.d.ts +9 -2
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +47 -38
- package/dist/request-auth/session-facts-als.d.ts +16 -1
- package/dist/request-auth/session-facts-als.d.ts.map +1 -1
- package/dist/request-auth/session-facts-als.js +23 -0
- package/dist/request-auth/session-token-binder.d.ts +166 -10
- package/dist/request-auth/session-token-binder.d.ts.map +1 -1
- package/dist/request-auth/session-token-binder.js +408 -28
- package/dist/secrets/encrypted-file-secrets.d.ts.map +1 -1
- package/dist/secrets/encrypted-file-secrets.js +9 -3
- package/dist/session/hot-revoking-session-record-store.d.ts +46 -0
- package/dist/session/hot-revoking-session-record-store.d.ts.map +1 -0
- package/dist/session/hot-revoking-session-record-store.js +58 -0
- package/dist/session/index.d.ts +3 -1
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +8 -1
- package/dist/session/mariadb-session-record-store.d.ts +6 -0
- package/dist/session/mariadb-session-record-store.d.ts.map +1 -1
- package/dist/session/mariadb-session-record-store.js +16 -1
- package/dist/session/session-lifetimes.d.ts +30 -0
- package/dist/session/session-lifetimes.d.ts.map +1 -0
- package/dist/session/session-lifetimes.js +21 -0
- package/dist/session/session-restriction-store.d.ts +43 -0
- package/dist/session/session-restriction-store.d.ts.map +1 -0
- package/dist/session/session-restriction-store.js +35 -0
- package/package.json +3 -3
- package/dist/auth/account.controller.js.map +0 -1
- package/dist/auth/auth.controller.js.map +0 -1
- package/dist/auth/auth.module.js.map +0 -1
- package/dist/auth/connections.js.map +0 -1
- package/dist/auth/dto.js.map +0 -1
- package/dist/auth/pending-mfa-store.js.map +0 -1
- package/dist/auth/persistence.module.js.map +0 -1
- package/dist/auth/ports/audit-sink.js.map +0 -1
- package/dist/auth/ports/credential-writer.js.map +0 -1
- package/dist/auth/ports/email-sender.js.map +0 -1
- package/dist/auth/ports/membership-checker.js.map +0 -1
- package/dist/auth/ports/mfa-device-store.js.map +0 -1
- package/dist/auth/ports/profile-writer.js.map +0 -1
- package/dist/auth/ports/recovery-code-store.js.map +0 -1
- package/dist/auth/ports/reset-token-store.js.map +0 -1
- package/dist/auth/ports/scope-subtree-resolver.js.map +0 -1
- package/dist/auth/ports/session-facts-projector.js.map +0 -1
- package/dist/auth/ports/session-sweeper.js.map +0 -1
- package/dist/auth/profile-resolver.js.map +0 -1
- package/dist/auth/rate-limit/attempt-limiter.js.map +0 -1
- package/dist/auth/tokens.js.map +0 -1
- package/dist/auth/totp-enrollment.js.map +0 -1
- package/dist/authentication/argon2id-password-hasher.js.map +0 -1
- package/dist/authentication/log-email-sender.js.map +0 -1
- package/dist/authentication/mariadb-credential-resolver.js.map +0 -1
- package/dist/authentication/mariadb-credential-writer.js.map +0 -1
- package/dist/authentication/mariadb-mfa-device-store.js.map +0 -1
- package/dist/authentication/mariadb-or-totp-verifier.js.map +0 -1
- package/dist/authentication/mariadb-profile-resolver.js.map +0 -1
- package/dist/authentication/mariadb-profile-writer.js.map +0 -1
- package/dist/authentication/mariadb-recovery-code-store.js.map +0 -1
- package/dist/authentication/mariadb-reset-token-store.js.map +0 -1
- package/dist/authentication/mariadb-session-sweeper.js.map +0 -1
- package/dist/authz/cross-tenant-grant-writer.js.map +0 -1
- package/dist/authz/list-scope-sql.js.map +0 -1
- package/dist/authz/manifest-operation-authority-adapter.js.map +0 -1
- package/dist/authz/mariadb-cross-tenant-grant-adapter.js.map +0 -1
- package/dist/authz/mariadb-list-scope-adapter.js.map +0 -1
- package/dist/authz/mariadb-policy-store.js.map +0 -1
- package/dist/authz/mariadb-record-rule-adapter.js.map +0 -1
- package/dist/authz/mariadb-record-share-adapter.js.map +0 -1
- package/dist/authz/record-share-cascade.js.map +0 -1
- package/dist/authz/record-share-writer.js.map +0 -1
- package/dist/authz/wire-record-authorization.js.map +0 -1
- package/dist/boot/boot-sequence.js.map +0 -1
- package/dist/boot/boot.module.js.map +0 -1
- package/dist/completeness/catalog-reconciler.js.map +0 -1
- package/dist/completeness/operation-inventory-scanner.js.map +0 -1
- package/dist/completeness/ports/catalog-store.js.map +0 -1
- package/dist/config/app-config.js.map +0 -1
- package/dist/config/config.module.js.map +0 -1
- package/dist/enforcement/classification.decorator.js.map +0 -1
- package/dist/enforcement/core-seam.js.map +0 -1
- package/dist/enforcement/enforcement.module.js.map +0 -1
- package/dist/enforcement/global-enforcement.guard.js.map +0 -1
- package/dist/enforcement/reenroll-allowlist.js.map +0 -1
- package/dist/identity/auth-facts.controller.js.map +0 -1
- package/dist/identity/identity-actions.js.map +0 -1
- package/dist/identity/module-registry.bridge.js.map +0 -1
- package/dist/identity/permission-facts.adapter.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/migrations-dir.js.map +0 -1
- package/dist/module/shield-tokens.js.map +0 -1
- package/dist/module/shield.module.js.map +0 -1
- package/dist/request-auth/request-principal.js.map +0 -1
- package/dist/request-auth/session-facts-als.js.map +0 -1
- package/dist/request-auth/session-token-binder.js.map +0 -1
- package/dist/request-auth/tokens.js.map +0 -1
- package/dist/scope/closure-builder.js.map +0 -1
- package/dist/session/crypto-adapters.js.map +0 -1
- package/dist/session/index.js.map +0 -1
- package/dist/session/mariadb-session-record-store.js.map +0 -1
- package/dist/session/redis-hot-session-store.js.map +0 -1
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
*/
|
|
45
45
|
import type { FactorVerifier, PasswordHasher } from '@astram/core';
|
|
46
46
|
import type { SessionTokenBinder } from '../request-auth/session-token-binder.js';
|
|
47
|
+
import type { SessionRestrictionStore } from '../session/session-restriction-store.js';
|
|
47
48
|
import type { CredentialWriter } from './ports/credential-writer.js';
|
|
48
49
|
import type { MfaDevice, MfaDeviceStore } from './ports/mfa-device-store.js';
|
|
49
50
|
import type { CurrentUserProfile, ProfileResolver } from './profile-resolver.js';
|
|
@@ -60,7 +61,8 @@ export declare class AccountController {
|
|
|
60
61
|
private readonly profileResolver?;
|
|
61
62
|
private readonly profileWriter?;
|
|
62
63
|
private readonly mfaDevices?;
|
|
63
|
-
|
|
64
|
+
private readonly sessionRestrictions?;
|
|
65
|
+
constructor(binder?: SessionTokenBinder | undefined, hasher?: PasswordHasher | undefined, writer?: (CredentialWriter | null) | undefined, sweeper?: (SessionSweeper | null) | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, totpVerifier?: (FactorVerifier | null) | undefined, profileResolver?: (ProfileResolver | null) | undefined, profileWriter?: (ProfileWriter | null) | undefined, mfaDevices?: (MfaDeviceStore | null) | undefined, sessionRestrictions?: (SessionRestrictionStore | null) | undefined);
|
|
64
66
|
/**
|
|
65
67
|
* Resolve a human-readable otpauth account LABEL for the caller (email, else display
|
|
66
68
|
* name) via the profile resolver. Best-effort: no resolver / null profile / a thrown
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAiBH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAa,MAAM,cAAc,CAAC;AAI9E,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"account.controller.d.ts","sourceRoot":"","sources":["../../src/auth/account.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -122,7 +122,8 @@ let AccountController = class AccountController {
|
|
|
122
122
|
profileResolver;
|
|
123
123
|
profileWriter;
|
|
124
124
|
mfaDevices;
|
|
125
|
-
|
|
125
|
+
sessionRestrictions;
|
|
126
|
+
constructor(binder, hasher, writer, sweeper, recoveryCodes, totpVerifier, profileResolver, profileWriter, mfaDevices, sessionRestrictions) {
|
|
126
127
|
this.binder = binder;
|
|
127
128
|
this.hasher = hasher;
|
|
128
129
|
this.writer = writer;
|
|
@@ -132,6 +133,7 @@ let AccountController = class AccountController {
|
|
|
132
133
|
this.profileResolver = profileResolver;
|
|
133
134
|
this.profileWriter = profileWriter;
|
|
134
135
|
this.mfaDevices = mfaDevices;
|
|
136
|
+
this.sessionRestrictions = sessionRestrictions;
|
|
135
137
|
}
|
|
136
138
|
/**
|
|
137
139
|
* Resolve a human-readable otpauth account LABEL for the caller (email, else display
|
|
@@ -290,9 +292,7 @@ let AccountController = class AccountController {
|
|
|
290
292
|
this.enforceReenroll(claims, false);
|
|
291
293
|
// Normalize: treat only non-empty string fields as a real change (trim so a
|
|
292
294
|
// whitespace-only value is not a change).
|
|
293
|
-
const name = typeof body?.name === 'string' && body.name.trim().length > 0
|
|
294
|
-
? body.name.trim()
|
|
295
|
-
: undefined;
|
|
295
|
+
const name = typeof body?.name === 'string' && body.name.trim().length > 0 ? body.name.trim() : undefined;
|
|
296
296
|
const email = typeof body?.email === 'string' && body.email.trim().length > 0
|
|
297
297
|
? body.email.trim()
|
|
298
298
|
: undefined;
|
|
@@ -446,6 +446,11 @@ let AccountController = class AccountController {
|
|
|
446
446
|
if (claims.mustReenroll === true && this.binder !== undefined && this.binder !== null) {
|
|
447
447
|
await this.binder.clearReenroll(claims.sessionId);
|
|
448
448
|
}
|
|
449
|
+
// Durable side (Phase 3B review P1). Best-effort: a failed clear only means a binding rebuilt
|
|
450
|
+
// after a Redis loss is restricted again (the safe direction); the user re-confirms.
|
|
451
|
+
if (claims.mustReenroll === true && this.sessionRestrictions) {
|
|
452
|
+
await this.sessionRestrictions.clearMustReenroll(claims.sessionId).catch(() => undefined);
|
|
453
|
+
}
|
|
449
454
|
if (wasFirst) {
|
|
450
455
|
const recoveryCodes = await this.replaceRecoveryCodes(claims.id, recoveryStore, hasher);
|
|
451
456
|
return { recoveryCodes };
|
|
@@ -657,7 +662,9 @@ exports.AccountController = AccountController = __decorate([
|
|
|
657
662
|
__param(7, (0, common_1.Inject)(tokens_js_2.SHIELD_PROFILE_WRITER)),
|
|
658
663
|
__param(8, (0, common_1.Optional)()),
|
|
659
664
|
__param(8, (0, common_1.Inject)(tokens_js_2.SHIELD_MFA_DEVICE_STORE)),
|
|
660
|
-
|
|
665
|
+
__param(9, (0, common_1.Optional)()),
|
|
666
|
+
__param(9, (0, common_1.Inject)(tokens_js_2.SHIELD_SESSION_RESTRICTIONS)),
|
|
667
|
+
__metadata("design:paramtypes", [Function, Object, Object, Object, Object, Object, Object, Object, Object, Object])
|
|
661
668
|
], AccountController);
|
|
662
669
|
/**
|
|
663
670
|
* A deliberately-minimal email shape check (non-empty, a single `@`, a `.` in the
|
|
@@ -14,10 +14,13 @@
|
|
|
14
14
|
* ── OUTCOME → HTTP STATUS MAP (the security contract) ────────────────────────
|
|
15
15
|
* login authenticated → 200 SessionSuccess { session(no-secret), tokens }
|
|
16
16
|
* login mfa_required → 200 MfaChallengeResponse { mfaRequired, challengeToken }
|
|
17
|
+
* (a Redis challenge: principal + hint + credential
|
|
18
|
+
* fingerprint, never the password — M6)
|
|
17
19
|
* login invalid_credentials → 401 GENERIC ← unknown-user AND wrong-password IDENTICAL
|
|
18
20
|
* login auth_unavailable → 503 RETRYABLE ← transient blip is NOT a credential deny
|
|
19
21
|
* mfa success → 200 SessionSuccess
|
|
20
22
|
* mfa wrong/expired/forged → 401 GENERIC ← indistinguishable from a bad code
|
|
23
|
+
* mfa TOTP step locked (#9) → 401 GENERIC (5 wrong codes / 15 min per account)
|
|
21
24
|
* mfa auth_unavailable → 503 RETRYABLE
|
|
22
25
|
* refresh ok → 200 SessionSuccess (new tokens, rotated session)
|
|
23
26
|
* refresh reuse/invalid → 401 GENERIC session_rejected (lineage-kill is the engine's)
|
|
@@ -50,12 +53,17 @@
|
|
|
50
53
|
* composed engines via DI tokens; it never news-up an engine or an adapter.
|
|
51
54
|
*/
|
|
52
55
|
import type { Authenticator, PasswordHasher, SessionAuthority } from '@astram/core';
|
|
56
|
+
import type { SessionRestrictionStore } from '../session/session-restriction-store.js';
|
|
57
|
+
import type { SessionRecordStore } from '@astram/core';
|
|
58
|
+
import type { Clock, SessionLifetimeConfig } from '@astram/core';
|
|
59
|
+
import { type MfaStepUp } from './mfa-step-up.js';
|
|
53
60
|
import type { SessionFactsProjector } from './ports/session-facts-projector.js';
|
|
54
61
|
import type { ScopeSubtreeResolver } from './ports/scope-subtree-resolver.js';
|
|
55
62
|
import type { MembershipChecker } from './ports/membership-checker.js';
|
|
56
63
|
import type { AttemptLimiter } from './rate-limit/attempt-limiter.js';
|
|
64
|
+
import { TrustProxyBootCheck } from './rate-limit/trust-proxy-check.js';
|
|
57
65
|
import { PendingMfaStore } from './pending-mfa-store.js';
|
|
58
|
-
import type
|
|
66
|
+
import { type SessionTokenBinder } from '../request-auth/session-token-binder.js';
|
|
59
67
|
import type { CurrentUserProfile, ProfileResolver } from './profile-resolver.js';
|
|
60
68
|
import type { CredentialResolver } from '@astram/core';
|
|
61
69
|
import type { ResetTokenStore } from './ports/reset-token-store.js';
|
|
@@ -87,6 +95,8 @@ export declare class AuthController {
|
|
|
87
95
|
private readonly resetLinkBaseUrl?;
|
|
88
96
|
private readonly recoveryCodes?;
|
|
89
97
|
private readonly loginLimiter?;
|
|
98
|
+
private readonly loginIpLimiter?;
|
|
99
|
+
private readonly trustProxyCheck?;
|
|
90
100
|
private readonly recoveryLimiter?;
|
|
91
101
|
private readonly forgotLimiter?;
|
|
92
102
|
private readonly forgotHintLimiter?;
|
|
@@ -96,23 +106,28 @@ export declare class AuthController {
|
|
|
96
106
|
private readonly scopeSubtreeResolver?;
|
|
97
107
|
private readonly membershipChecker?;
|
|
98
108
|
private readonly permissionFacts?;
|
|
99
|
-
|
|
109
|
+
private readonly mfaLimiter?;
|
|
110
|
+
private readonly mfaStepUp?;
|
|
111
|
+
private readonly clock?;
|
|
112
|
+
private readonly lifetimes?;
|
|
113
|
+
private readonly rootIds?;
|
|
114
|
+
private readonly sessionRecords?;
|
|
115
|
+
private readonly sessionRestrictions?;
|
|
116
|
+
constructor(authenticator: Authenticator, sessionAuthority: SessionAuthority, pendingMfa: PendingMfaStore, tokenBinder?: SessionTokenBinder | undefined, profileResolver?: ProfileResolver | undefined, credentialResolver?: (CredentialResolver | null) | undefined, resetTokenStore?: (ResetTokenStore | null) | undefined, emailSender?: (EmailSender | null) | undefined, credentialWriter?: (CredentialWriter | null) | undefined, sessionSweeper?: (SessionSweeper | null) | undefined, passwordHasher?: PasswordHasher | undefined, resetLinkBaseUrl?: string | undefined, recoveryCodes?: (RecoveryCodeStore | null) | undefined, loginLimiter?: (AttemptLimiter | null) | undefined, loginIpLimiter?: (AttemptLimiter | null) | undefined, trustProxyCheck?: (TrustProxyBootCheck | null) | undefined, recoveryLimiter?: (AttemptLimiter | null) | undefined, forgotLimiter?: (AttemptLimiter | null) | undefined, forgotHintLimiter?: (AttemptLimiter | null) | undefined, resetLimiter?: (AttemptLimiter | null) | undefined, auditSink?: (AuditSink | null) | undefined, sessionFactsProjector?: (SessionFactsProjector | null) | undefined, scopeSubtreeResolver?: (ScopeSubtreeResolver | null) | undefined, membershipChecker?: (MembershipChecker | null) | undefined, permissionFacts?: (MariaDbPermissionFactsAdapter | null) | undefined, mfaLimiter?: (AttemptLimiter | null) | undefined, mfaStepUp?: (MfaStepUp | null) | undefined, clock?: (Clock | null) | undefined, lifetimes?: (SessionLifetimeConfig | null) | undefined, rootIds?: (readonly string[] | null) | undefined, sessionRecords?: (Pick<SessionRecordStore, "findSessionById"> | null) | undefined, sessionRestrictions?: (SessionRestrictionStore | null) | undefined);
|
|
117
|
+
/**
|
|
118
|
+
* The access-token binding TTL for an establishment (security hardening #8):
|
|
119
|
+
* `clamp(session.expiresAtMs − now, 1, accessTtlMs)` — on login AND refresh. Never derived
|
|
120
|
+
* from `issuedAtMs` (the original login), which made refresh-minted tokens live for the
|
|
121
|
+
* session's age.
|
|
122
|
+
*/
|
|
123
|
+
private accessTtlFor;
|
|
100
124
|
/**
|
|
101
125
|
* Bind the established session's access token to the principal's claims (the
|
|
102
|
-
* request-auth layer). The access-token TTL is
|
|
103
|
-
*
|
|
126
|
+
* request-auth layer). The access-token TTL is {@link accessTtlFor} (≤ the access TTL).
|
|
127
|
+
* Best-effort: a binding failure must not fail the login (the caller still
|
|
104
128
|
* gets valid tokens); the guard fails closed if the binding is absent.
|
|
105
129
|
*/
|
|
106
130
|
private bindSession;
|
|
107
|
-
/**
|
|
108
|
-
* Project the principal's coarse grants for the session binding (ADR-0011), via the
|
|
109
|
-
* OPTIONAL {@link SessionFactsProjector} seam. Returns the {@link CoarseGrants} to
|
|
110
|
-
* cache, or `undefined` when there is no projector, the projection yielded nothing,
|
|
111
|
-
* OR it threw — every "no facts" path collapses to `undefined` so the caller simply
|
|
112
|
-
* omits `cachedFacts` and the request DB-reloads (fail-closed; a projection failure
|
|
113
|
-
* NEVER fails the login/refresh and never fabricates a grant).
|
|
114
|
-
*/
|
|
115
|
-
private projectFacts;
|
|
116
131
|
/**
|
|
117
132
|
* Project coarse grants for a principal id + tenant (ADR-0011), distinguishing THREE
|
|
118
133
|
* outcomes for the REFRESH path (which must know whether to carry the existing cache
|
|
@@ -148,6 +163,16 @@ export declare class AuthController {
|
|
|
148
163
|
* bumped by moveNode/deleteNode) re-derives its CORRECT subtree here, closing the
|
|
149
164
|
* stale-subtree-after-move window (bounded by the access-token lifetime — ADR-0011).
|
|
150
165
|
*/
|
|
166
|
+
/**
|
|
167
|
+
* The permission version of `tenantId`, read just BEFORE its subtree is resolved, to stamp the
|
|
168
|
+
* binding (`scopeSubtreeVersion`, security hardening Phase 1C): when gate 5 later reloads facts
|
|
169
|
+
* at a newer version, the enforcement guard re-derives the subtree. Read before the resolve so a
|
|
170
|
+
* racing bump leaves the stamp too old (one extra re-derive), never too new. Only when a
|
|
171
|
+
* subtree resolver is wired (no subtree → nothing to stamp, no extra read). Best-effort: no
|
|
172
|
+
* facts adapter, a non-integer, or a throw → `undefined` (unstamped → the guard re-derives once
|
|
173
|
+
* at the next reload). One indexed read at login/refresh/scope-switch, never per request.
|
|
174
|
+
*/
|
|
175
|
+
private subtreeVersionFor;
|
|
151
176
|
private resolveScopeSubtreeFor;
|
|
152
177
|
/**
|
|
153
178
|
* Compute the caller's OWN auth-facts projection to INLINE into a login/mfa success
|
|
@@ -183,12 +208,33 @@ export declare class AuthController {
|
|
|
183
208
|
* never a claim), matching the internal adapter's root-safety.
|
|
184
209
|
*/
|
|
185
210
|
private principalFromClaims;
|
|
211
|
+
/**
|
|
212
|
+
* The account (principal id) a typed hint resolves to, for keying the per-account
|
|
213
|
+
* limiters (review F1). Goes through the SAME injected {@link CredentialResolver} the
|
|
214
|
+
* composed authenticator uses — the default is the indexed
|
|
215
|
+
* `WHERE ic_identity_hint = ? LIMIT 1` on the `utf8mb4_unicode_ci` column — so the DB
|
|
216
|
+
* collation, not client-side normalisation, decides which spellings are one account.
|
|
217
|
+
* No new access path. The RAW hint is passed (never normalised).
|
|
218
|
+
*
|
|
219
|
+
* Returns `null` for an unknown hint, a blank hint, or when no resolver is wired (→ the
|
|
220
|
+
* canonical-hash fallback key). A store ERROR propagates (the caller fails closed).
|
|
221
|
+
*/
|
|
222
|
+
/**
|
|
223
|
+
* The ONE gate for every per-IP limiter (login failures, forgot-password, reset-password):
|
|
224
|
+
* returns the limiter only when bootstrap confirmed an explicit Express `trust proxy`
|
|
225
|
+
* ({@link TrustProxyBootCheck.perIpLimitingEnabled}); otherwise `null` (limiter OFF).
|
|
226
|
+
* Without it every client behind a proxy shares one `req.ip`, so enforcing a per-IP
|
|
227
|
+
* limit would block everyone (an unauthenticated global DoS). Per-account limits are
|
|
228
|
+
* never routed through here.
|
|
229
|
+
*/
|
|
230
|
+
private perIp;
|
|
231
|
+
private lookupAccount;
|
|
186
232
|
/**
|
|
187
233
|
* `POST /auth/login` — verify a password credential and either establish a
|
|
188
234
|
* session, issue an MFA challenge, deny generically, or signal a transient
|
|
189
235
|
* outage. NEVER logs the request body.
|
|
190
236
|
*/
|
|
191
|
-
login(body: LoginRequest): Promise<LoginResponse>;
|
|
237
|
+
login(body: LoginRequest, ip: string): Promise<LoginResponse>;
|
|
192
238
|
/**
|
|
193
239
|
* `GET /auth/me` — the signed-in user's **display profile** (name, email, active
|
|
194
240
|
* company name, role names) for the UI header/card. Fills the flagged gap: login
|
|
@@ -269,12 +315,27 @@ export declare class AuthController {
|
|
|
269
315
|
forgotPassword(body: {
|
|
270
316
|
identityHint?: string;
|
|
271
317
|
}, ip: string): Promise<void>;
|
|
318
|
+
/**
|
|
319
|
+
* The detached per-account half of {@link forgotPassword} (review F1):
|
|
320
|
+
* 1. resolve the RAW hint through the same {@link CredentialResolver} the authenticator
|
|
321
|
+
* uses (the DB collation decides which spellings are one account);
|
|
322
|
+
* 2. meter the per-account budget — `forgot:pid:<principalId>`, or the canonical-hash
|
|
323
|
+
* fallback key for an unknown hint — and audit `auth.forgot_password.hint_throttled`
|
|
324
|
+
* ONCE on the edge (distinct from the IP site's `throttled`, so "one account bombed
|
|
325
|
+
* across rotating IPs" is visible). No notify (it would itself be the email-bomb);
|
|
326
|
+
* 3. send only when both budgets allow, the account resolved, and the reset seams exist.
|
|
327
|
+
* A lookup error still meters (fallback key) and skips the send (still 204).
|
|
328
|
+
*/
|
|
329
|
+
private meterAndDeliverReset;
|
|
272
330
|
/**
|
|
273
331
|
* The detached found-path work for {@link forgotPassword}: mint a raw token, issue
|
|
274
332
|
* its SHA-256 hash to the store (30-min TTL), resolve the recipient email via the
|
|
275
333
|
* profile resolver, and send the framework-composed reset link. Runs OUTSIDE the
|
|
276
|
-
* request/response timing (fire-and-forget) so it cannot form a timing oracle.
|
|
277
|
-
*
|
|
334
|
+
* request/response timing (fire-and-forget) so it cannot form a timing oracle. This
|
|
335
|
+
* method itself writes no log line — but the raw token and the email ARE handed to the
|
|
336
|
+
* bound {@link EmailSender}, and the dev-only `LogEmailSender` (the default ONLY when
|
|
337
|
+
* NODE_ENV is `development`/`test`) prints the whole message, link included, to stdout.
|
|
338
|
+
* Any other environment must supply a real sender or `emailSender: 'disabled'`.
|
|
278
339
|
*/
|
|
279
340
|
private deliverResetLink;
|
|
280
341
|
/**
|
|
@@ -298,9 +359,9 @@ export declare class AuthController {
|
|
|
298
359
|
* `POST /auth/mfa` — complete a pending MFA login. Consumes the single-use
|
|
299
360
|
* challenge handle (unknown/expired/forged → same generic 401 as a bad code),
|
|
300
361
|
* then BRANCHES on the presented factor:
|
|
301
|
-
* • `'totp'` →
|
|
302
|
-
*
|
|
303
|
-
*
|
|
362
|
+
* • `'totp'` → the MFA STEP-UP (M6): verify ONLY the code against the principal the
|
|
363
|
+
* password step recorded (no password is held or re-run). Rate-limited per account
|
|
364
|
+
* (#9). See {@link completeViaTotp}.
|
|
304
365
|
* • `'recovery_code'` → the lost-device escape hatch: verify a one-time
|
|
305
366
|
* recovery code (a separate branch, NOT the core factor loop — recovery codes
|
|
306
367
|
* are N single-use Argon2 hashes, incompatible with the pure one-secret
|
|
@@ -308,9 +369,25 @@ export declare class AuthController {
|
|
|
308
369
|
* • any other factor → generic 401 (no leak of "unsupported factor").
|
|
309
370
|
*
|
|
310
371
|
* Anti-enumeration: unknown/forged/expired challenge, unknown hint, wrong code,
|
|
311
|
-
* and wrong recovery code ALL return the identical generic 401.
|
|
372
|
+
* a locked TOTP step, and a wrong recovery code ALL return the identical generic 401.
|
|
373
|
+
* A challenge-store outage is a retryable 503.
|
|
312
374
|
*/
|
|
313
375
|
mfa(body: MfaRequest): Promise<SessionSuccess>;
|
|
376
|
+
/**
|
|
377
|
+
* The `/auth/mfa` TOTP branch (M6 + #9). The consumed challenge proves the password
|
|
378
|
+
* step passed for `pending.principalId`; this verifies ONLY the code, through the
|
|
379
|
+
* {@link MfaStepUp} (same `OrTotpVerifier` + replay guard as the authenticator, principal
|
|
380
|
+
* minted by the identity broker).
|
|
381
|
+
*
|
|
382
|
+
* - `mfa:pid:<principalId>` is checked BEFORE verifying: locked → generic 401 and the
|
|
383
|
+
* step-up is never consulted.
|
|
384
|
+
* - a rejected code records a failure; the edge where the count first reaches the
|
|
385
|
+
* threshold audits `auth.mfa.locked` ONCE (no notify — pre-auth, see recovery lockout).
|
|
386
|
+
* - a transient outage → 503, never counted.
|
|
387
|
+
* - success → establish + bind, then reset the TOTP counter AND the login counter (the
|
|
388
|
+
* login counter is reset only here, once authentication fully succeeded).
|
|
389
|
+
*/
|
|
390
|
+
private completeViaTotp;
|
|
314
391
|
/**
|
|
315
392
|
* The `/auth/mfa` RECOVERY-CODE branch (spec §3). The lost-device user completes
|
|
316
393
|
* login with a pre-issued single-use recovery code instead of a TOTP.
|
|
@@ -383,11 +460,43 @@ export declare class AuthController {
|
|
|
383
460
|
/**
|
|
384
461
|
* `POST /auth/refresh` — rotate the refresh token. Reuse/invalid/expired →
|
|
385
462
|
* generic 401 (`session_rejected`; the engine already killed the lineage,
|
|
386
|
-
* ADR-0015
|
|
463
|
+
* ADR-0015, and `HotRevokingSessionRecordStore` unbinds it in Redis so the live access
|
|
464
|
+
* token dies on its next request — M-A). The new access token is bound for ≤ the access
|
|
465
|
+
* TTL; the previous one keeps a 30 s grace (#8, D7). If the session's claims cannot be
|
|
466
|
+
* carried forward (`rebindOnRotate` → false) the refresh is a generic 401 — never an
|
|
467
|
+
* unbound token. ⚠ See the class header: the engine's rotate collapses a transient
|
|
387
468
|
* store outage into the SAME reject, so refresh cannot emit the ADR-0016 503 from
|
|
388
469
|
* this seam today (flagged core-API gap).
|
|
389
470
|
*/
|
|
390
471
|
refresh(body: RefreshRequest): Promise<SessionSuccess>;
|
|
472
|
+
/**
|
|
473
|
+
* The refresh-time projection for one node: coarse grants + live roles (ADR-0035) and the
|
|
474
|
+
* subtree with its version stamp (Phase 1C: the version is read FIRST). Each part is best-effort
|
|
475
|
+
* exactly as at login (`undefined` = carry / omit, `null` facts = strip).
|
|
476
|
+
*/
|
|
477
|
+
private projectForNode;
|
|
478
|
+
/**
|
|
479
|
+
* SILENT RECOVERY of a lost session binding (invariant #12, ADR-0013, ADR-0035, GAPS #5).
|
|
480
|
+
* `rotate()` has already proved the durable session is active and inside its idle and absolute
|
|
481
|
+
* windows, and returned its principal + tenant. The rebuilt claims NEVER carry more authority
|
|
482
|
+
* than the session had (Phase 3B review P1); they come from durable sources only:
|
|
483
|
+
* - principal + tenant: the durable session record (the LOGIN node; a scope-switch is not
|
|
484
|
+
* durable, so a rebuilt session returns to the node it was opened on);
|
|
485
|
+
* - the RE-ENROLL restriction: `shield_identity.session.s_must_reenroll`, set at a
|
|
486
|
+
* recovery-code login. A restricted session rebuilds `mustReenroll: true` and NEVER root
|
|
487
|
+
* (exactly how the recovery login bound it);
|
|
488
|
+
* - the account status: a disabled user gets no rebuild;
|
|
489
|
+
* - roles: the live projection (ADR-0035) — `[]` when none is available (non-widening; the
|
|
490
|
+
* first request's gate-5 reload fills them, because no facts are cached then);
|
|
491
|
+
* - `isRoot` (unrestricted sessions only): the server-side root allowlist, never a claim;
|
|
492
|
+
* - subtree: the resolver (absent → the self-node fallback, non-widening);
|
|
493
|
+
* - kind `user` (sessions are human; service accounts authenticate with keys).
|
|
494
|
+
* No restriction store, or any error reading it → no rebuild (fail closed). The claims entry is
|
|
495
|
+
* written with `NX`, then the durable session is READ AGAIN: if a logout or revoke landed
|
|
496
|
+
* meanwhile, the rebuilt binding is dropped and the refresh fails. Returns `true` when the
|
|
497
|
+
* session is bound and still active. Any error → `false` (the caller answers 401).
|
|
498
|
+
*/
|
|
499
|
+
private rebuildBinding;
|
|
391
500
|
/**
|
|
392
501
|
* `POST /auth/logout` — revoke the session. Idempotent + leak-free: revoking an
|
|
393
502
|
* unknown or already-revoked session still returns 204 (the engine's `revoke`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":"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"}
|