@astram/guard 0.19.0 → 0.20.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 +79 -6
- package/dist/auth/admin-signin-controls.d.ts +80 -0
- package/dist/auth/admin-signin-controls.d.ts.map +1 -0
- package/dist/auth/admin-signin-controls.js +91 -0
- package/dist/auth/auth-audit.d.ts +59 -0
- package/dist/auth/auth-audit.d.ts.map +1 -0
- package/dist/auth/auth-audit.js +93 -0
- package/dist/auth/auth.controller.d.ts +53 -6
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +330 -44
- package/dist/auth/auth.module.d.ts +49 -0
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +149 -4
- package/dist/auth/captcha-gate.d.ts +103 -0
- package/dist/auth/captcha-gate.d.ts.map +1 -0
- package/dist/auth/captcha-gate.js +245 -0
- package/dist/auth/dto.d.ts +22 -1
- package/dist/auth/dto.d.ts.map +1 -1
- package/dist/auth/login-name-count-boot.d.ts +24 -0
- package/dist/auth/login-name-count-boot.d.ts.map +1 -0
- package/dist/auth/login-name-count-boot.js +47 -0
- package/dist/auth/logout-proof.d.ts +55 -0
- package/dist/auth/logout-proof.d.ts.map +1 -0
- package/dist/auth/logout-proof.js +127 -0
- package/dist/auth/pending-mfa-store.d.ts +5 -0
- package/dist/auth/pending-mfa-store.d.ts.map +1 -1
- package/dist/auth/pending-mfa-store.js +2 -0
- package/dist/auth/ports/audit-sink.d.ts +5 -2
- package/dist/auth/ports/audit-sink.d.ts.map +1 -1
- package/dist/auth/ports/mfa-device-store.d.ts +7 -0
- package/dist/auth/ports/mfa-device-store.d.ts.map +1 -1
- package/dist/auth/profile-resolver.d.ts +6 -0
- package/dist/auth/profile-resolver.d.ts.map +1 -1
- package/dist/auth/rate-limit/attempt-limiter.d.ts +6 -0
- package/dist/auth/rate-limit/attempt-limiter.d.ts.map +1 -1
- package/dist/auth/rate-limit/attempt-limiter.js +14 -0
- package/dist/auth/tokens.d.ts +59 -0
- package/dist/auth/tokens.d.ts.map +1 -1
- package/dist/auth/tokens.js +61 -1
- package/dist/authentication/credential-provisioner.d.ts +7 -0
- package/dist/authentication/credential-provisioner.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-provisioner.d.ts +1 -0
- package/dist/authentication/mariadb-credential-provisioner.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-provisioner.js +7 -0
- package/dist/authentication/mariadb-credential-resolver.d.ts +23 -2
- package/dist/authentication/mariadb-credential-resolver.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-resolver.js +45 -1
- package/dist/authentication/mariadb-mfa-device-store.d.ts +7 -0
- package/dist/authentication/mariadb-mfa-device-store.d.ts.map +1 -1
- package/dist/authentication/mariadb-mfa-device-store.js +32 -0
- package/dist/authentication/mariadb-mfa-requirement-source.d.ts +55 -0
- package/dist/authentication/mariadb-mfa-requirement-source.d.ts.map +1 -0
- package/dist/authentication/mariadb-mfa-requirement-source.js +164 -0
- package/dist/authentication/mariadb-mfa-resetter.d.ts +42 -0
- package/dist/authentication/mariadb-mfa-resetter.d.ts.map +1 -0
- package/dist/authentication/mariadb-mfa-resetter.js +59 -0
- package/dist/authentication/mariadb-profile-writer.d.ts.map +1 -1
- package/dist/authentication/mariadb-profile-writer.js +5 -0
- package/dist/authentication/sign-in-with.d.ts +14 -0
- package/dist/authentication/sign-in-with.d.ts.map +1 -0
- package/dist/authentication/sign-in-with.js +36 -0
- package/dist/authz/core-access.d.ts +11 -0
- package/dist/authz/core-access.d.ts.map +1 -0
- package/dist/authz/core-access.js +14 -0
- package/dist/authz/list-scope-sql.d.ts.map +1 -1
- package/dist/authz/list-scope-sql.js +15 -5
- package/dist/authz/wire-record-authorization.d.ts.map +1 -1
- package/dist/authz/wire-record-authorization.js +21 -3
- package/dist/captcha/captcha.providers.d.ts +18 -0
- package/dist/captcha/captcha.providers.d.ts.map +1 -0
- package/dist/captcha/captcha.providers.js +78 -0
- package/dist/captcha/recaptcha-verifier.d.ts +20 -0
- package/dist/captcha/recaptcha-verifier.d.ts.map +1 -0
- package/dist/captcha/recaptcha-verifier.js +48 -0
- package/dist/captcha/siteverify.d.ts +47 -0
- package/dist/captcha/siteverify.d.ts.map +1 -0
- package/dist/captcha/siteverify.js +98 -0
- package/dist/captcha/turnstile-verifier.d.ts +18 -0
- package/dist/captcha/turnstile-verifier.d.ts.map +1 -0
- package/dist/captcha/turnstile-verifier.js +41 -0
- package/dist/config/captcha-config.d.ts +47 -0
- package/dist/config/captcha-config.d.ts.map +1 -0
- package/dist/config/captcha-config.js +163 -0
- package/dist/config/reserved-principal-ids.d.ts +15 -0
- package/dist/config/reserved-principal-ids.d.ts.map +1 -1
- package/dist/config/reserved-principal-ids.js +20 -3
- package/dist/enforcement/global-enforcement.guard.d.ts +9 -1
- package/dist/enforcement/global-enforcement.guard.d.ts.map +1 -1
- package/dist/enforcement/global-enforcement.guard.js +52 -10
- package/dist/enforcement/reenroll-allowlist.d.ts +5 -0
- package/dist/enforcement/reenroll-allowlist.d.ts.map +1 -1
- package/dist/enforcement/reenroll-allowlist.js +5 -0
- package/dist/identity/auth-facts.controller.d.ts +31 -4
- package/dist/identity/auth-facts.controller.d.ts.map +1 -1
- package/dist/identity/auth-facts.controller.js +46 -11
- package/dist/identity/identity-actions.d.ts +2 -2
- package/dist/identity/identity-actions.d.ts.map +1 -1
- package/dist/identity/module-registry.bridge.d.ts.map +1 -1
- package/dist/identity/module-registry.bridge.js +3 -6
- package/dist/identity/permission-facts.adapter.d.ts +22 -0
- package/dist/identity/permission-facts.adapter.d.ts.map +1 -1
- package/dist/identity/permission-facts.adapter.js +26 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -10
- package/dist/internal.d.ts +27 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +36 -1
- package/dist/module/shield.module.d.ts +27 -0
- package/dist/module/shield.module.d.ts.map +1 -1
- package/dist/module/shield.module.js +10 -0
- package/dist/request-auth/request-principal.d.ts +8 -1
- package/dist/request-auth/request-principal.d.ts.map +1 -1
- package/dist/request-auth/request-principal.js +11 -4
- package/dist/request-auth/session-token-binder.d.ts +82 -0
- package/dist/request-auth/session-token-binder.d.ts.map +1 -1
- package/dist/request-auth/session-token-binder.js +203 -1
- package/dist/session/mfa-requirement-service.d.ts +168 -0
- package/dist/session/mfa-requirement-service.d.ts.map +1 -0
- package/dist/session/mfa-requirement-service.js +461 -0
- package/dist/session/session-restriction-store.d.ts +36 -0
- package/dist/session/session-restriction-store.d.ts.map +1 -1
- package/dist/session/session-restriction-store.js +57 -6
- package/dist/session/session-restriction.d.ts +22 -0
- package/dist/session/session-restriction.d.ts.map +1 -0
- package/dist/session/session-restriction.js +23 -0
- package/package.json +5 -5
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
*/
|
|
65
65
|
import { type DynamicModule, type Provider } from '@nestjs/common';
|
|
66
66
|
import type { CredentialResolver, HmacSha1, FactorVerifier } from '@astram/core';
|
|
67
|
+
import { type SignInMethod } from '../authentication/sign-in-with.js';
|
|
68
|
+
import { type ShieldCaptchaOption } from '../captcha/captcha.providers.js';
|
|
67
69
|
import type { SessionFactsProjector } from './ports/session-facts-projector.js';
|
|
68
70
|
import type { ScopeSubtreeResolver } from './ports/scope-subtree-resolver.js';
|
|
69
71
|
import type { MembershipChecker } from './ports/membership-checker.js';
|
|
@@ -107,6 +109,26 @@ export declare function resolveTotpVerifier(override: FactorVerifier | null | un
|
|
|
107
109
|
* consumer's built CJS dist. Async because of {@link loadCore}.
|
|
108
110
|
*/
|
|
109
111
|
export declare function makeDefaultTotpVerifier(): Promise<FactorVerifier>;
|
|
112
|
+
/**
|
|
113
|
+
* Mandatory 2FA (R2.3–R2.5, R2.7): the service the login, the request path, device confirm and
|
|
114
|
+
* device removal use — bound ONLY when `@astram/identity` signals its security-policy feature
|
|
115
|
+
* ({@link SHIELD_MFA_POLICY_FEATURE}); otherwise `null` and the guard behaves exactly as before (no
|
|
116
|
+
* evaluation, no extra read, no new claim). Grants come from the session-facts projector (the
|
|
117
|
+
* decision authority's own `loadCoarseGrants`); the self-authenticating routes read the version
|
|
118
|
+
* from Redis (miss ⇒ one DB fill, Redis error ⇒ deny), as gate 5 does.
|
|
119
|
+
*/
|
|
120
|
+
export declare const mfaRequirementProvider: Provider;
|
|
121
|
+
/**
|
|
122
|
+
* Admin sign-in controls (auth capabilities R11.2): the admin's own TOTP step-up, over the device
|
|
123
|
+
* store, the replay-guarded login verifier and the `mfa:pid` limiter (the same three the code-gated
|
|
124
|
+
* `/account` routes use). For `@astram/identity`'s `/identity/users/:uuid/*` controls.
|
|
125
|
+
*/
|
|
126
|
+
export declare const adminStepUpProvider: Provider;
|
|
127
|
+
/**
|
|
128
|
+
* Admin sign-in controls (R11.1 unlock): clears one principal's `login:pid`, `mfa:pid`,
|
|
129
|
+
* `recovery:` and CAPTCHA account counters on the guard's one Redis client (fails closed).
|
|
130
|
+
*/
|
|
131
|
+
export declare const accountUnlockerProvider: Provider;
|
|
110
132
|
/** DI token for the single-layout privilege probe hook (a no-op in the four layout). */
|
|
111
133
|
export declare const SHIELD_SINGLE_LAYOUT_PROBE: unique symbol;
|
|
112
134
|
/**
|
|
@@ -238,6 +260,27 @@ export interface AuthModuleOptions {
|
|
|
238
260
|
* `emailSender: 'disabled'` (Phase 13 #1; `RESET_LINK_BASE_URL` follows the same rule).
|
|
239
261
|
*/
|
|
240
262
|
readonly emailChangeLinkBaseUrl?: string;
|
|
263
|
+
/**
|
|
264
|
+
* R15.1 / D-9: require proof for `POST /auth/logout` (a refresh token of the session, or an
|
|
265
|
+
* access token bound to it). `false` (default, this release): an unproven logout still revokes,
|
|
266
|
+
* counted as `auth.logout.unproven` with a one-time deprecation warning. `true`: an unproven
|
|
267
|
+
* logout revokes nothing (204). Becomes `true` by default at the next guard major.
|
|
268
|
+
*/
|
|
269
|
+
readonly logoutRequiresProof?: boolean;
|
|
270
|
+
/**
|
|
271
|
+
* R1.8: the sign-in forms `POST /auth/login` accepts. `['email']` (default) is today's
|
|
272
|
+
* behaviour; `['email', 'username']` also accepts the user's login name (`users.u_login_name`,
|
|
273
|
+
* set by an admin or `bootstrap:org`). Validated at registration: an unknown value, an empty
|
|
274
|
+
* list or a list without `'email'` throws. Applies to the framework-default credential
|
|
275
|
+
* resolver; a consumer `credentialResolver` decides for itself.
|
|
276
|
+
*/
|
|
277
|
+
readonly signInWith?: readonly SignInMethod[];
|
|
278
|
+
/**
|
|
279
|
+
* Auth capabilities R7: `'env'` turns CAPTCHA on for `/auth/login`, `/auth/forgot-password` and
|
|
280
|
+
* `/auth/reset-password` from `CAPTCHA_*` (`loadCaptchaConfig`; a missing or invalid value fails
|
|
281
|
+
* the boot). Omitted ⇒ off, every route answers exactly as before.
|
|
282
|
+
*/
|
|
283
|
+
readonly captcha?: ShieldCaptchaOption;
|
|
241
284
|
}
|
|
242
285
|
/**
|
|
243
286
|
* The per-account email-change REQUEST limiter (Phase 12) — `email-change:pid:<id>`, 3 per 60-min
|
|
@@ -251,6 +294,12 @@ export declare const attemptLimiterFactoryProvider: Provider;
|
|
|
251
294
|
* the unit test only — not part of the package's public surface.
|
|
252
295
|
*/
|
|
253
296
|
export declare function resolveDefaultEmailSender(rawNodeEnv: string | undefined): EmailSender;
|
|
297
|
+
/**
|
|
298
|
+
* The auth audit sink (R12.1, B-3): the app-supplied `auditSink` wins; else the framework default
|
|
299
|
+
* on {@link SHIELD_DEFAULT_AUTH_AUDIT_SINK} (bound globally by `@astram/identity`), injected
|
|
300
|
+
* optionally; else `null` (un-audited, as before).
|
|
301
|
+
*/
|
|
302
|
+
export declare function makeAuditSinkProvider(override?: AuditSink): Provider;
|
|
254
303
|
/**
|
|
255
304
|
* The auth composition module. Imports {@link PersistenceModule} (the live
|
|
256
305
|
* connections) and provides the adapters + composed engines. Exports the two
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAEH,OAAO,EAGL,KAAK,aAAa,EAElB,KAAK,QAAQ,EACd,MAAM,gBAAgB,CAAC;AAaxB,OAAO,KAAK,EAGV,kBAAkB,EAOlB,QAAQ,EACR,cAAc,
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":"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"}
|
package/dist/auth/auth.module.js
CHANGED
|
@@ -104,10 +104,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
104
104
|
})();
|
|
105
105
|
var AuthModule_1;
|
|
106
106
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
107
|
-
exports.AuthModule = exports.attemptLimiterFactoryProvider = exports.singleLayoutProbeProvider = exports.SHIELD_SINGLE_LAYOUT_PROBE = exports.hmacSha1 = void 0;
|
|
107
|
+
exports.AuthModule = exports.attemptLimiterFactoryProvider = exports.singleLayoutProbeProvider = exports.SHIELD_SINGLE_LAYOUT_PROBE = exports.accountUnlockerProvider = exports.adminStepUpProvider = exports.mfaRequirementProvider = exports.hmacSha1 = void 0;
|
|
108
108
|
exports.resolveTotpVerifier = resolveTotpVerifier;
|
|
109
109
|
exports.makeDefaultTotpVerifier = makeDefaultTotpVerifier;
|
|
110
110
|
exports.resolveDefaultEmailSender = resolveDefaultEmailSender;
|
|
111
|
+
exports.makeAuditSinkProvider = makeAuditSinkProvider;
|
|
111
112
|
const common_1 = require("@nestjs/common");
|
|
112
113
|
const node_crypto_1 = require("node:crypto");
|
|
113
114
|
const app_config_js_1 = require("../config/app-config.js");
|
|
@@ -136,13 +137,22 @@ const index_js_1 = require("../session/index.js");
|
|
|
136
137
|
const replay_outcome_js_1 = require("../session/replay-outcome.js");
|
|
137
138
|
const persistence_module_js_1 = require("./persistence.module.js");
|
|
138
139
|
const auth_controller_js_1 = require("./auth.controller.js");
|
|
140
|
+
const logout_proof_js_1 = require("./logout-proof.js");
|
|
139
141
|
const account_controller_js_1 = require("./account.controller.js");
|
|
140
142
|
const confirm_email_controller_js_1 = require("./confirm-email.controller.js");
|
|
141
143
|
const pending_mfa_store_js_1 = require("./pending-mfa-store.js");
|
|
142
144
|
const mfa_step_up_js_1 = require("./mfa-step-up.js");
|
|
143
145
|
const tokens_js_1 = require("./tokens.js");
|
|
146
|
+
const admin_signin_controls_js_1 = require("./admin-signin-controls.js");
|
|
147
|
+
const captcha_gate_js_1 = require("./captcha-gate.js");
|
|
148
|
+
const sign_in_with_js_1 = require("../authentication/sign-in-with.js");
|
|
149
|
+
const captcha_providers_js_1 = require("../captcha/captcha.providers.js");
|
|
150
|
+
const login_name_count_boot_js_1 = require("./login-name-count-boot.js");
|
|
151
|
+
const framework_schema_names_js_1 = require("../config/framework-schema-names.js");
|
|
144
152
|
const permission_version_cache_js_1 = require("../authz/permission-version-cache.js");
|
|
145
153
|
const session_restriction_store_js_1 = require("../session/session-restriction-store.js");
|
|
154
|
+
const mariadb_mfa_requirement_source_js_1 = require("../authentication/mariadb-mfa-requirement-source.js");
|
|
155
|
+
const mfa_requirement_service_js_1 = require("../session/mfa-requirement-service.js");
|
|
146
156
|
const attempt_limiter_js_1 = require("./rate-limit/attempt-limiter.js");
|
|
147
157
|
const trust_proxy_check_js_1 = require("./rate-limit/trust-proxy-check.js");
|
|
148
158
|
const email_delivery_js_1 = require("../messaging/email-delivery.js");
|
|
@@ -256,8 +266,11 @@ function makeCredentialResolverProvider(override) {
|
|
|
256
266
|
provide: tokens_js_1.SHIELD_CREDENTIAL_RESOLVER,
|
|
257
267
|
// #7: the default resolver folds the principal's CONFIRMED MFA devices into a
|
|
258
268
|
// `totp` required factor, so enrolled MFA is enforced at every password login.
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
// R1.8: `signInWith` decides whether a hint without `@` may resolve by login name.
|
|
270
|
+
useFactory: (pool, devices, config, signInWith) => new mariadb_credential_resolver_js_1.MariaDbCredentialResolver(pool, devices, undefined, (0, app_config_js_1.frameworkSchemasOf)(config), {
|
|
271
|
+
signInWith,
|
|
272
|
+
}),
|
|
273
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, tokens_js_1.SHIELD_MFA_DEVICE_STORE, config_module_js_1.APP_CONFIG, tokens_js_1.SHIELD_SIGN_IN_WITH],
|
|
261
274
|
};
|
|
262
275
|
}
|
|
263
276
|
/**
|
|
@@ -303,6 +316,88 @@ const sessionRestrictionStoreProvider = {
|
|
|
303
316
|
useFactory: (pool, config) => new session_restriction_store_js_1.MariaDbSessionRestrictionStore(pool, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
304
317
|
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
305
318
|
};
|
|
319
|
+
/**
|
|
320
|
+
* The guard's MariaDB {@link MfaRequirementSource} (auth capabilities B-1) over the runtime pool:
|
|
321
|
+
* policies, scope chain, confirmed devices, the per-user grace clock. Reads nothing until asked.
|
|
322
|
+
*/
|
|
323
|
+
const mfaRequirementSourceProvider = {
|
|
324
|
+
provide: tokens_js_1.SHIELD_MFA_REQUIREMENT_SOURCE,
|
|
325
|
+
useFactory: (pool, config) => new mariadb_mfa_requirement_source_js_1.MariaDbMfaRequirementSource(pool, (0, app_config_js_1.frameworkSchemasOf)(config)),
|
|
326
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
327
|
+
};
|
|
328
|
+
/**
|
|
329
|
+
* Mandatory 2FA (R2.3–R2.5, R2.7): the service the login, the request path, device confirm and
|
|
330
|
+
* device removal use — bound ONLY when `@astram/identity` signals its security-policy feature
|
|
331
|
+
* ({@link SHIELD_MFA_POLICY_FEATURE}); otherwise `null` and the guard behaves exactly as before (no
|
|
332
|
+
* evaluation, no extra read, no new claim). Grants come from the session-facts projector (the
|
|
333
|
+
* decision authority's own `loadCoarseGrants`); the self-authenticating routes read the version
|
|
334
|
+
* from Redis (miss ⇒ one DB fill, Redis error ⇒ deny), as gate 5 does.
|
|
335
|
+
*/
|
|
336
|
+
exports.mfaRequirementProvider = {
|
|
337
|
+
provide: tokens_js_1.SHIELD_MFA_REQUIREMENT,
|
|
338
|
+
useFactory: (feature, pool, config, projector, versionCache, permissionFacts, binder, restrictions) => {
|
|
339
|
+
if (feature !== true)
|
|
340
|
+
return null;
|
|
341
|
+
const source = new mariadb_mfa_requirement_source_js_1.MariaDbMfaRequirementSource(pool, (0, app_config_js_1.frameworkSchemasOf)(config));
|
|
342
|
+
return new mfa_requirement_service_js_1.MfaRequirementService({
|
|
343
|
+
source,
|
|
344
|
+
// R11.3: the admin users list's batched page reads.
|
|
345
|
+
batch: source,
|
|
346
|
+
loadGrants: async (principalId, tenantId) => {
|
|
347
|
+
if (projector === null || projector === undefined)
|
|
348
|
+
return null;
|
|
349
|
+
if (typeof projector.isActive === 'function' && projector.isActive() !== true)
|
|
350
|
+
return null;
|
|
351
|
+
return projector.project(principalId, tenantId);
|
|
352
|
+
},
|
|
353
|
+
currentVersion: (0, mfa_requirement_service_js_1.currentVersionReader)(versionCache, (tenantId) => permissionFacts.currentVersionFor('', tenantId)),
|
|
354
|
+
binder,
|
|
355
|
+
restrictions,
|
|
356
|
+
});
|
|
357
|
+
},
|
|
358
|
+
inject: [
|
|
359
|
+
{ token: tokens_js_1.SHIELD_MFA_POLICY_FEATURE, optional: true },
|
|
360
|
+
tokens_js_1.SHIELD_DB_POOL,
|
|
361
|
+
config_module_js_1.APP_CONFIG,
|
|
362
|
+
tokens_js_1.SHIELD_SESSION_FACTS_PROJECTOR,
|
|
363
|
+
tokens_js_1.SHIELD_PERMISSION_VERSION_CACHE,
|
|
364
|
+
tokens_js_1.SHIELD_PERMISSION_FACTS,
|
|
365
|
+
tokens_js_2.SHIELD_SESSION_TOKEN_BINDER,
|
|
366
|
+
tokens_js_1.SHIELD_SESSION_RESTRICTIONS,
|
|
367
|
+
],
|
|
368
|
+
};
|
|
369
|
+
/**
|
|
370
|
+
* Admin sign-in controls (auth capabilities R11.2): the admin's own TOTP step-up, over the device
|
|
371
|
+
* store, the replay-guarded login verifier and the `mfa:pid` limiter (the same three the code-gated
|
|
372
|
+
* `/account` routes use). For `@astram/identity`'s `/identity/users/:uuid/*` controls.
|
|
373
|
+
*/
|
|
374
|
+
exports.adminStepUpProvider = {
|
|
375
|
+
provide: tokens_js_1.SHIELD_ADMIN_STEP_UP,
|
|
376
|
+
useFactory: (devices, verifier, limiter) => new admin_signin_controls_js_1.TotpAdminStepUp({
|
|
377
|
+
devices: devices ?? null,
|
|
378
|
+
verifier: verifier ?? null,
|
|
379
|
+
limiter: limiter ?? null,
|
|
380
|
+
}),
|
|
381
|
+
inject: [
|
|
382
|
+
{ token: tokens_js_1.SHIELD_MFA_DEVICE_STORE, optional: true },
|
|
383
|
+
{ token: tokens_js_1.SHIELD_LOGIN_TOTP_VERIFIER, optional: true },
|
|
384
|
+
{ token: tokens_js_1.SHIELD_MFA_LIMITER, optional: true },
|
|
385
|
+
],
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Admin sign-in controls (R11.1 unlock): clears one principal's `login:pid`, `mfa:pid`,
|
|
389
|
+
* `recovery:` and CAPTCHA account counters on the guard's one Redis client (fails closed).
|
|
390
|
+
*/
|
|
391
|
+
exports.accountUnlockerProvider = {
|
|
392
|
+
provide: tokens_js_1.SHIELD_ACCOUNT_UNLOCKER,
|
|
393
|
+
useFactory: (redis, login, mfa, recovery) => new admin_signin_controls_js_1.RedisAccountUnlocker({
|
|
394
|
+
login,
|
|
395
|
+
mfa,
|
|
396
|
+
recovery,
|
|
397
|
+
captcha: new captcha_gate_js_1.RedisCaptchaCounterStore(redis),
|
|
398
|
+
}),
|
|
399
|
+
inject: [tokens_js_1.SHIELD_REDIS, tokens_js_1.SHIELD_LOGIN_LIMITER, tokens_js_1.SHIELD_MFA_LIMITER, tokens_js_1.SHIELD_RECOVERY_LIMITER],
|
|
400
|
+
};
|
|
306
401
|
/** Hot session store (Redis adapter, injected with the live client). */
|
|
307
402
|
const hotSessionStoreProvider = {
|
|
308
403
|
provide: index_js_1.SHIELD_HOT_SESSION_STORE,
|
|
@@ -680,6 +775,17 @@ const totpVerifierProvider = {
|
|
|
680
775
|
return createTotpFactorVerifier({ hmacSha1: exports.hmacSha1 });
|
|
681
776
|
},
|
|
682
777
|
};
|
|
778
|
+
/** DI token for the R1.9 boot count of users with a login name. */
|
|
779
|
+
const SHIELD_LOGIN_NAME_COUNT_BOOT = Symbol('SHIELD_LOGIN_NAME_COUNT_BOOT');
|
|
780
|
+
/**
|
|
781
|
+
* Auth capabilities R1.9: with `signInWith` including `'username'`, log once at boot how many
|
|
782
|
+
* active users have a login name (count only) through the runtime pool. A no-op otherwise.
|
|
783
|
+
*/
|
|
784
|
+
const loginNameCountBootProvider = {
|
|
785
|
+
provide: SHIELD_LOGIN_NAME_COUNT_BOOT,
|
|
786
|
+
useFactory: (pool, config, signInWith) => new login_name_count_boot_js_1.LoginNameCountBoot(async (sql) => (await pool.query(sql)), (0, framework_schema_names_js_1.qualifiedTableName)((0, app_config_js_1.frameworkSchemasOf)(config).app, 'users'), signInWith),
|
|
787
|
+
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG, tokens_js_1.SHIELD_SIGN_IN_WITH],
|
|
788
|
+
};
|
|
683
789
|
/**
|
|
684
790
|
* Bind the current-user profile resolver backing `GET /auth/me`.
|
|
685
791
|
*
|
|
@@ -895,8 +1001,19 @@ function makeMfaDeviceStoreProvider(override) {
|
|
|
895
1001
|
inject: [tokens_js_1.SHIELD_DB_POOL, config_module_js_1.APP_CONFIG],
|
|
896
1002
|
};
|
|
897
1003
|
}
|
|
1004
|
+
/**
|
|
1005
|
+
* The auth audit sink (R12.1, B-3): the app-supplied `auditSink` wins; else the framework default
|
|
1006
|
+
* on {@link SHIELD_DEFAULT_AUTH_AUDIT_SINK} (bound globally by `@astram/identity`), injected
|
|
1007
|
+
* optionally; else `null` (un-audited, as before).
|
|
1008
|
+
*/
|
|
898
1009
|
function makeAuditSinkProvider(override) {
|
|
899
|
-
return
|
|
1010
|
+
return override
|
|
1011
|
+
? { provide: tokens_js_1.SHIELD_AUDIT_SINK, useValue: override }
|
|
1012
|
+
: {
|
|
1013
|
+
provide: tokens_js_1.SHIELD_AUDIT_SINK,
|
|
1014
|
+
useFactory: (defaultSink) => defaultSink ?? null,
|
|
1015
|
+
inject: [{ token: tokens_js_1.SHIELD_DEFAULT_AUTH_AUDIT_SINK, optional: true }],
|
|
1016
|
+
};
|
|
900
1017
|
}
|
|
901
1018
|
/**
|
|
902
1019
|
* Bind the OPTIONAL eager session-facts projector (ADR-0011). Same value-provider
|
|
@@ -973,6 +1090,10 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
973
1090
|
// `resolveDefaultEmailSender` (that clearer error is kept; in development/test the rule is off).
|
|
974
1091
|
// G-010: `'env'` is a real sender unless `EMAIL_PROVIDER=disabled` (read after resolveBootSecrets).
|
|
975
1092
|
const mailDisabled = (0, email_delivery_js_1.isMailDisabled)(options.emailSender, process.env);
|
|
1093
|
+
// R1.8: validated here so a bad value fails the boot with a clear message.
|
|
1094
|
+
const signInWith = (0, sign_in_with_js_1.resolveSignInWith)(options.signInWith);
|
|
1095
|
+
// R7: validated here too, so a bad value fails the boot with a clear message.
|
|
1096
|
+
const captcha = (0, captcha_providers_js_1.captchaProviders)(options.captcha);
|
|
976
1097
|
return {
|
|
977
1098
|
module: AuthModule_1,
|
|
978
1099
|
imports: [persistence_module_js_1.PersistenceModule.forRoot()],
|
|
@@ -986,6 +1107,11 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
986
1107
|
controllers: [auth_controller_js_1.AuthController, confirm_email_controller_js_1.ConfirmEmailController, account_controller_js_1.AccountController, auth_facts_controller_js_1.AuthFactsController],
|
|
987
1108
|
providers: [
|
|
988
1109
|
passwordHasherProvider,
|
|
1110
|
+
{ provide: tokens_js_1.SHIELD_SIGN_IN_WITH, useValue: signInWith },
|
|
1111
|
+
// R1.9: boot count of active users with a login name (only with `username`).
|
|
1112
|
+
loginNameCountBootProvider,
|
|
1113
|
+
// R7: the CAPTCHA config, verifier and gate (`null` gate when the option is absent).
|
|
1114
|
+
...captcha,
|
|
989
1115
|
makeCredentialResolverProvider(options.credentialResolver),
|
|
990
1116
|
// The current-user profile seam backing `GET /auth/me` (null when absent).
|
|
991
1117
|
makeProfileResolverProvider(options.profileResolver),
|
|
@@ -1024,6 +1150,9 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
1024
1150
|
// fails closed, denying every switch — cannot verify the target binding). Consumed by
|
|
1025
1151
|
// AuthController's scopeSwitch handler.
|
|
1026
1152
|
makeMembershipCheckerProvider(options.membershipChecker),
|
|
1153
|
+
// R15.1: the logout proof check + the `logoutRequiresProof` option (default false).
|
|
1154
|
+
logout_proof_js_1.logoutProofVerifierProvider,
|
|
1155
|
+
(0, logout_proof_js_1.makeLogoutRequiresProofProvider)(options.logoutRequiresProof),
|
|
1027
1156
|
// The framework-DEFAULT permission-facts adapter backing AuthFactsController
|
|
1028
1157
|
// (`/identity/auth-facts` + `/identity/permissions-version`). Reads role grants +
|
|
1029
1158
|
// per-tenant version from the pool; expands `identity:*` wildcards against the
|
|
@@ -1045,6 +1174,13 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
1045
1174
|
permissionVersionCacheProvider,
|
|
1046
1175
|
// Phase 3B review P1: the durable re-enroll marker + account status for the rebuild.
|
|
1047
1176
|
sessionRestrictionStoreProvider,
|
|
1177
|
+
// Auth capabilities R2: the MariaDB requirement source and the mandatory-2FA service
|
|
1178
|
+
// (`null` unless identity signals the security-policy feature).
|
|
1179
|
+
mfaRequirementSourceProvider,
|
|
1180
|
+
exports.mfaRequirementProvider,
|
|
1181
|
+
// R11: identity's admin sign-in controls (step-up and unlock).
|
|
1182
|
+
exports.adminStepUpProvider,
|
|
1183
|
+
exports.accountUnlockerProvider,
|
|
1048
1184
|
hotSessionStoreProvider,
|
|
1049
1185
|
tokenGeneratorProvider,
|
|
1050
1186
|
refreshHasherProvider,
|
|
@@ -1132,6 +1268,15 @@ let AuthModule = AuthModule_1 = class AuthModule {
|
|
|
1132
1268
|
// reads it (gate 5) and `@astram/identity`'s bumper publishes to it after commit.
|
|
1133
1269
|
tokens_js_1.SHIELD_PERMISSION_VERSION_CACHE,
|
|
1134
1270
|
tokens_js_1.SHIELD_SESSION_RESTRICTIONS,
|
|
1271
|
+
// Auth capabilities R2: the enforcement guard injects the service (gate-5 recompute).
|
|
1272
|
+
tokens_js_1.SHIELD_MFA_REQUIREMENT,
|
|
1273
|
+
tokens_js_1.SHIELD_MFA_REQUIREMENT_SOURCE,
|
|
1274
|
+
tokens_js_1.SHIELD_SIGN_IN_WITH,
|
|
1275
|
+
// R7: exported for inspection and for later endpoints (OTP request, R7.2).
|
|
1276
|
+
tokens_js_1.SHIELD_CAPTCHA_GATE,
|
|
1277
|
+
// R11: identity's admin sign-in controls inject these (through @astram/guard/internal).
|
|
1278
|
+
tokens_js_1.SHIELD_ADMIN_STEP_UP,
|
|
1279
|
+
tokens_js_1.SHIELD_ACCOUNT_UNLOCKER,
|
|
1135
1280
|
],
|
|
1136
1281
|
};
|
|
1137
1282
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type Redis from 'ioredis';
|
|
2
|
+
import { type CaptchaProvider, type CaptchaVerifier } from '@astram/core';
|
|
3
|
+
import type { CaptchaConfig, CaptchaEndpoint, CaptchaMode } from '../config/captcha-config.js';
|
|
4
|
+
import type { AuditSink } from './ports/audit-sink.js';
|
|
5
|
+
/** Fixed counter window (ms). */
|
|
6
|
+
export declare const CAPTCHA_WINDOW_MS: number;
|
|
7
|
+
export declare const AUTH_CAPTCHA_FAILED = "auth.captcha.failed";
|
|
8
|
+
export declare const AUTH_CAPTCHA_FAIL_OPEN = "auth.captcha.fail_open";
|
|
9
|
+
/**
|
|
10
|
+
* Bump every key and arm the window on the first hit (or a key left without a TTL). Returns the
|
|
11
|
+
* new counts, in key order. KEYS = the counter keys; ARGV[1] = window ms.
|
|
12
|
+
*/
|
|
13
|
+
export declare const CAPTCHA_BUMP_SCRIPT = "local out = {}\nfor i, k in ipairs(KEYS) do\n local n = redis.call('INCR', k)\n if n == 1 or redis.call('PTTL', k) == -1 then\n redis.call('PEXPIRE', k, ARGV[1])\n end\n out[i] = n\nend\nreturn out";
|
|
14
|
+
/** The counters behind the adaptive decision. */
|
|
15
|
+
export interface CaptchaCounterStore {
|
|
16
|
+
/** Current counts (missing = 0). REJECTS on a store error. */
|
|
17
|
+
counts(keys: readonly string[]): Promise<readonly number[]>;
|
|
18
|
+
/** Increment each key (fixed window); returns the new counts. REJECTS on a store error. */
|
|
19
|
+
bump(keys: readonly string[]): Promise<readonly number[]>;
|
|
20
|
+
/** Remove keys. Best-effort. */
|
|
21
|
+
clear(keys: readonly string[]): Promise<void>;
|
|
22
|
+
/** `true` the first time `key` is seen in a window (audit bounding). Best-effort: error ⇒ false. */
|
|
23
|
+
firstInWindow(key: string): Promise<boolean>;
|
|
24
|
+
}
|
|
25
|
+
/** {@link CaptchaCounterStore} over the guard's bounded ioredis client. */
|
|
26
|
+
export declare class RedisCaptchaCounterStore implements CaptchaCounterStore {
|
|
27
|
+
private readonly redis;
|
|
28
|
+
private readonly windowMs;
|
|
29
|
+
constructor(redis: Pick<Redis, 'mget' | 'eval' | 'del' | 'set'>, windowMs?: number);
|
|
30
|
+
private k;
|
|
31
|
+
counts(keys: readonly string[]): Promise<readonly number[]>;
|
|
32
|
+
bump(keys: readonly string[]): Promise<readonly number[]>;
|
|
33
|
+
clear(keys: readonly string[]): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Remove keys and REJECT on a store error (auth capabilities R11.1: an admin unlock clears the
|
|
36
|
+
* account counters and must not report a success it did not achieve). Not on the port: only the
|
|
37
|
+
* unlocker uses it.
|
|
38
|
+
*/
|
|
39
|
+
clearStrict(keys: readonly string[]): Promise<void>;
|
|
40
|
+
firstInWindow(key: string): Promise<boolean>;
|
|
41
|
+
}
|
|
42
|
+
/** Who/what an attempt is about. `ip` is set only when per-IP limiting is on. */
|
|
43
|
+
export interface CaptchaSubject {
|
|
44
|
+
readonly accountId?: string | null;
|
|
45
|
+
readonly tenantId?: string | null;
|
|
46
|
+
readonly typedText?: string | null;
|
|
47
|
+
readonly ip?: string | null;
|
|
48
|
+
}
|
|
49
|
+
/** The gate's verdict for one request. */
|
|
50
|
+
export type CaptchaVerdict = {
|
|
51
|
+
readonly kind: 'not_required';
|
|
52
|
+
} | {
|
|
53
|
+
readonly kind: 'passed';
|
|
54
|
+
} | {
|
|
55
|
+
readonly kind: 'fail_open';
|
|
56
|
+
} | {
|
|
57
|
+
readonly kind: 'failed';
|
|
58
|
+
};
|
|
59
|
+
/** What `GET /auth/login-options` publishes (never the secret). */
|
|
60
|
+
export interface CaptchaPublicOptions {
|
|
61
|
+
readonly provider: CaptchaProvider;
|
|
62
|
+
readonly siteKey: string;
|
|
63
|
+
readonly mode: CaptchaMode;
|
|
64
|
+
}
|
|
65
|
+
export interface CaptchaGateDeps {
|
|
66
|
+
readonly config: CaptchaConfig;
|
|
67
|
+
readonly verifier: CaptchaVerifier;
|
|
68
|
+
readonly counters: CaptchaCounterStore;
|
|
69
|
+
readonly auditSink?: AuditSink | null;
|
|
70
|
+
readonly logger?: {
|
|
71
|
+
log(message: unknown): void;
|
|
72
|
+
warn(message: string): void;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export declare class CaptchaGate {
|
|
76
|
+
private readonly deps;
|
|
77
|
+
private readonly logger;
|
|
78
|
+
constructor(deps: CaptchaGateDeps);
|
|
79
|
+
/** The public part of the config (provider, site key, mode). */
|
|
80
|
+
get publicOptions(): CaptchaPublicOptions;
|
|
81
|
+
/** True when this endpoint is protected (`CAPTCHA_ENDPOINTS`). */
|
|
82
|
+
covers(endpoint: CaptchaEndpoint): boolean;
|
|
83
|
+
/** True when the mode is `always` (every attempt is challenged). */
|
|
84
|
+
get always(): boolean;
|
|
85
|
+
private keys;
|
|
86
|
+
private overThreshold;
|
|
87
|
+
/** Is a challenge required now? A store error ⇒ `true` (fail closed). */
|
|
88
|
+
required(endpoint: CaptchaEndpoint, subject: CaptchaSubject): Promise<boolean>;
|
|
89
|
+
/**
|
|
90
|
+
* Decide and, when required, verify `token`. Call BEFORE any hash / code check. Never throws.
|
|
91
|
+
*/
|
|
92
|
+
check(endpoint: CaptchaEndpoint, subject: CaptchaSubject, token: unknown, remoteIp?: string): Promise<CaptchaVerdict>;
|
|
93
|
+
/**
|
|
94
|
+
* Count one failure (login: wrong password; forgot: every request; reset: bad token). Returns
|
|
95
|
+
* whether the NEXT attempt needs a challenge (the failure body's `captcha: 'required'` flag). A
|
|
96
|
+
* store error ⇒ `true` (fail closed, consistent with {@link required}).
|
|
97
|
+
*/
|
|
98
|
+
recordFailure(endpoint: CaptchaEndpoint, subject: CaptchaSubject): Promise<boolean>;
|
|
99
|
+
/** A success clears the account and typed-text counters (never the IP one). Best-effort. */
|
|
100
|
+
recordSuccess(endpoint: CaptchaEndpoint, subject: CaptchaSubject): Promise<void>;
|
|
101
|
+
private count;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=captcha-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captcha-gate.d.ts","sourceRoot":"","sources":["../../src/auth/captcha-gate.ts"],"names":[],"mappings":"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"}
|