@c9up/warden 0.1.4 → 0.1.6

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.
Files changed (88) hide show
  1. package/README.md +58 -0
  2. package/dist/Guard.d.ts +9 -0
  3. package/dist/Guard.d.ts.map +1 -1
  4. package/dist/Guard.js +16 -0
  5. package/dist/Guard.js.map +1 -1
  6. package/dist/RedisBlacklistDriver.d.ts +32 -0
  7. package/dist/RedisBlacklistDriver.d.ts.map +1 -0
  8. package/dist/RedisBlacklistDriver.js +37 -0
  9. package/dist/RedisBlacklistDriver.js.map +1 -0
  10. package/dist/ResilientBlacklistDriver.d.ts +35 -0
  11. package/dist/ResilientBlacklistDriver.d.ts.map +1 -0
  12. package/dist/ResilientBlacklistDriver.js +61 -0
  13. package/dist/ResilientBlacklistDriver.js.map +1 -0
  14. package/dist/TokenBlacklist.d.ts +6 -2
  15. package/dist/TokenBlacklist.d.ts.map +1 -1
  16. package/dist/TokenBlacklist.js +2 -2
  17. package/dist/TokenBlacklist.js.map +1 -1
  18. package/dist/WardenProvider.d.ts.map +1 -1
  19. package/dist/WardenProvider.js +47 -6
  20. package/dist/WardenProvider.js.map +1 -1
  21. package/dist/config.d.ts +65 -1
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js.map +1 -1
  24. package/dist/index.d.ts +15 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +8 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/mfa/BackupCodesProvider.d.ts +39 -0
  29. package/dist/mfa/BackupCodesProvider.d.ts.map +1 -0
  30. package/dist/mfa/BackupCodesProvider.js +87 -0
  31. package/dist/mfa/BackupCodesProvider.js.map +1 -0
  32. package/dist/mfa/MfaManager.d.ts +107 -0
  33. package/dist/mfa/MfaManager.d.ts.map +1 -0
  34. package/dist/mfa/MfaManager.js +219 -0
  35. package/dist/mfa/MfaManager.js.map +1 -0
  36. package/dist/mfa/OtpProvider.d.ts +67 -0
  37. package/dist/mfa/OtpProvider.d.ts.map +1 -0
  38. package/dist/mfa/OtpProvider.js +104 -0
  39. package/dist/mfa/OtpProvider.js.map +1 -0
  40. package/dist/mfa/TotpProvider.d.ts +52 -0
  41. package/dist/mfa/TotpProvider.d.ts.map +1 -0
  42. package/dist/mfa/TotpProvider.js +103 -0
  43. package/dist/mfa/TotpProvider.js.map +1 -0
  44. package/dist/mfa/WebauthnProvider.d.ts +175 -0
  45. package/dist/mfa/WebauthnProvider.d.ts.map +1 -0
  46. package/dist/mfa/WebauthnProvider.js +239 -0
  47. package/dist/mfa/WebauthnProvider.js.map +1 -0
  48. package/dist/mfa/base32.d.ts +13 -0
  49. package/dist/mfa/base32.d.ts.map +1 -0
  50. package/dist/mfa/base32.js +52 -0
  51. package/dist/mfa/base32.js.map +1 -0
  52. package/dist/mfa/webauthn-codec.d.ts +58 -0
  53. package/dist/mfa/webauthn-codec.d.ts.map +1 -0
  54. package/dist/mfa/webauthn-codec.js +221 -0
  55. package/dist/mfa/webauthn-codec.js.map +1 -0
  56. package/dist/middleware.d.ts +31 -0
  57. package/dist/middleware.d.ts.map +1 -1
  58. package/dist/middleware.js +77 -4
  59. package/dist/middleware.js.map +1 -1
  60. package/dist/standalone.d.ts.map +1 -1
  61. package/dist/standalone.js +12 -0
  62. package/dist/standalone.js.map +1 -1
  63. package/dist/strategies/ApiKeyStrategy.d.ts.map +1 -1
  64. package/dist/strategies/ApiKeyStrategy.js +14 -1
  65. package/dist/strategies/ApiKeyStrategy.js.map +1 -1
  66. package/index.darwin-arm64.node +0 -0
  67. package/index.darwin-x64.node +0 -0
  68. package/index.linux-arm64-gnu.node +0 -0
  69. package/index.linux-x64-gnu.node +0 -0
  70. package/index.win32-x64-msvc.node +0 -0
  71. package/package.json +2 -2
  72. package/src/Guard.ts +21 -0
  73. package/src/RedisBlacklistDriver.ts +60 -0
  74. package/src/ResilientBlacklistDriver.ts +84 -0
  75. package/src/TokenBlacklist.ts +7 -3
  76. package/src/WardenProvider.ts +53 -7
  77. package/src/config.ts +60 -1
  78. package/src/index.ts +58 -0
  79. package/src/mfa/BackupCodesProvider.ts +125 -0
  80. package/src/mfa/MfaManager.ts +307 -0
  81. package/src/mfa/OtpProvider.ts +177 -0
  82. package/src/mfa/TotpProvider.ts +140 -0
  83. package/src/mfa/WebauthnProvider.ts +416 -0
  84. package/src/mfa/base32.ts +54 -0
  85. package/src/mfa/webauthn-codec.ts +264 -0
  86. package/src/middleware.ts +111 -2
  87. package/src/standalone.ts +14 -1
  88. package/src/strategies/ApiKeyStrategy.ts +14 -1
@@ -16,6 +16,11 @@
16
16
  * }
17
17
  */
18
18
  import { type AuthResult } from "./AuthManager.js";
19
+ import type { BasePolicy } from "./bouncer/BasePolicy.js";
20
+ import { Bouncer } from "./bouncer/Bouncer.js";
21
+ import type { Ability } from "./bouncer/types.js";
22
+ import type { ScopeRequestContext } from "./config.js";
23
+ import type { Scope } from "./rights/types.js";
19
24
  import type { SessionStore } from "./strategies/SessionStrategy.js";
20
25
  export interface WardenContext {
21
26
  request: {
@@ -34,6 +39,8 @@ export interface WardenContext {
34
39
  session?: SessionStore;
35
40
  /** Set by the middleware after successful auth. */
36
41
  auth?: AuthResult;
42
+ /** Set by `initializeBouncer` — the per-request authorization entry point. */
43
+ bouncer?: Bouncer;
37
44
  /** The route handler metadata (decorators). */
38
45
  route?: {
39
46
  controller?: object;
@@ -47,5 +54,29 @@ type WardenNext = () => Promise<void> | void;
47
54
  * and authenticates + authorizes the request.
48
55
  */
49
56
  export declare function wardenMiddleware(ctx: WardenContext, next: WardenNext): Promise<void>;
57
+ /**
58
+ * The abilities/policies/scope-resolver a per-request Bouncer is built from.
59
+ * Registered once by `WardenProvider` (from `config.auth`) under the container
60
+ * token `"bouncer:registry"`; read fresh by `initializeBouncer` per request.
61
+ */
62
+ export interface BouncerRegistry {
63
+ abilities: Record<string, Ability<never[]>>;
64
+ policies: Record<string, new () => BasePolicy>;
65
+ resolveScope?: (ctx: ScopeRequestContext) => Scope | Promise<Scope>;
66
+ }
67
+ /**
68
+ * Bouncer initializer (Epic 56.6) — a GLOBAL middleware (register it for every
69
+ * route, after `wardenMiddleware`). It builds the per-request {@link Bouncer}
70
+ * from the authenticated user (`ctx.auth?.user`, or `null` for a guest), the
71
+ * shared `RightsResolver`, and the registered abilities/policies, then attaches
72
+ * it as `ctx.bouncer`. Handlers authorize via `await ctx.bouncer.authorize(...)`
73
+ * (throws `WARDEN_AUTHORIZATION_FAILURE` carrying `status: 403`, which the host's
74
+ * ExceptionHandler maps to a 403 response) or branch on `ctx.bouncer.allows(...)`.
75
+ *
76
+ * Unlike `wardenMiddleware` (a per-route GUARD that short-circuits public
77
+ * routes), this runs on EVERY request so `ctx.bouncer` is always available —
78
+ * including for guests — matching AdonisJS's `initialize_bouncer_middleware`.
79
+ */
80
+ export declare function initializeBouncer(ctx: WardenContext, next: WardenNext): Promise<void>;
50
81
  export {};
51
82
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAEN,KAAK,UAAU,EAGf,MAAM,kBAAkB,CAAC;AAM1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAcpE,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC,CAAC;IACF,QAAQ,EAAE;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;KAC9B,CAAC;IACF,SAAS,EAAE;QACV,OAAO,EAAE,CACR,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,KAC/D,OAAO,CAAC;KACb,CAAC;IACF,4DAA4D;IAC5D,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,+CAA+C;IAC/C,KAAK,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KACzB,CAAC;CACF;AAED,KAAK,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE7C;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,iBAoG1E"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAEN,KAAK,UAAU,EAGf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQvD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAcpE,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC,CAAC;IACF,QAAQ,EAAE;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;KAC9B,CAAC;IACF,SAAS,EAAE;QACV,OAAO,EAAE,CACR,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,KAC/D,OAAO,CAAC;KACb,CAAC;IACF,4DAA4D;IAC5D,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,mDAAmD;IACnD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+CAA+C;IAC/C,KAAK,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KACzB,CAAC;CACF;AAED,KAAK,UAAU,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE7C;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,iBAwH1E;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,UAAU,CAAC,CAAC;IAC/C,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;CACpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU,iBAmB3E"}
@@ -16,7 +16,9 @@
16
16
  * }
17
17
  */
18
18
  import { AuthManager, sanitizePayload, } from "./AuthManager.js";
19
- import { getGuardMetadata, getPermissionMetadata, getRoleMetadata, } from "./Guard.js";
19
+ import { Bouncer } from "./bouncer/Bouncer.js";
20
+ import { getGuardMetadata, getPermissionMetadata, getRequireMfaMetadata, getRoleMetadata, } from "./Guard.js";
21
+ import { RightsResolver } from "./rights/RightsResolver.js";
20
22
  function hasVerifyWithContext(strategy) {
21
23
  return (typeof strategy.verifyWithContext === "function");
22
24
  }
@@ -101,17 +103,88 @@ export async function wardenMiddleware(ctx, next) {
101
103
  // bypass permission checks. This is the strictest model — callers who want
102
104
  // role-OR-permission semantics should use a custom guard instead.
103
105
  if (controller && action) {
104
- const denied = await checkAuthorization(auth, user, controller, action);
106
+ const scope = await resolveRequestScope(ctx);
107
+ const denied = await checkAuthorization(auth, user, controller, action, scope);
105
108
  if (denied) {
106
109
  ctx.response.status(403);
107
110
  ctx.response.json({ error: { code: "FORBIDDEN", message: denied } });
108
111
  return;
109
112
  }
113
+ // @RequireMfa gate: the user must carry a truthy `mfa` claim, set by the
114
+ // app's step-up flow once MfaManager.verify() succeeds.
115
+ if (getRequireMfaMetadata(controller, action) && user.mfa !== true) {
116
+ ctx.response.status(403);
117
+ ctx.response.json({
118
+ error: {
119
+ code: "MFA_REQUIRED",
120
+ message: "Multi-factor authentication is required for this action.",
121
+ },
122
+ });
123
+ return;
124
+ }
110
125
  }
111
126
  // Auth successful — attach to context and continue.
112
127
  ctx.auth = result;
113
128
  await next();
114
129
  }
130
+ /**
131
+ * Bouncer initializer (Epic 56.6) — a GLOBAL middleware (register it for every
132
+ * route, after `wardenMiddleware`). It builds the per-request {@link Bouncer}
133
+ * from the authenticated user (`ctx.auth?.user`, or `null` for a guest), the
134
+ * shared `RightsResolver`, and the registered abilities/policies, then attaches
135
+ * it as `ctx.bouncer`. Handlers authorize via `await ctx.bouncer.authorize(...)`
136
+ * (throws `WARDEN_AUTHORIZATION_FAILURE` carrying `status: 403`, which the host's
137
+ * ExceptionHandler maps to a 403 response) or branch on `ctx.bouncer.allows(...)`.
138
+ *
139
+ * Unlike `wardenMiddleware` (a per-route GUARD that short-circuits public
140
+ * routes), this runs on EVERY request so `ctx.bouncer` is always available —
141
+ * including for guests — matching AdonisJS's `initialize_bouncer_middleware`.
142
+ */
143
+ export async function initializeBouncer(ctx, next) {
144
+ // Both dependencies are registered by WardenProvider. Resolve defensively:
145
+ // a host that wired the middleware but not the provider gets an empty Bouncer
146
+ // (no abilities/resolver) rather than a crash on every request.
147
+ const resolved = tryResolve(ctx, RightsResolver);
148
+ const resolver = resolved instanceof RightsResolver ? resolved : undefined;
149
+ const candidate = tryResolve(ctx, "bouncer:registry");
150
+ const registry = isBouncerRegistry(candidate) ? candidate : undefined;
151
+ const user = ctx.auth?.user ?? null;
152
+ const scope = registry?.resolveScope
153
+ ? await registry.resolveScope(ctx)
154
+ : "global";
155
+ ctx.bouncer = new Bouncer(user, registry?.abilities, registry?.policies, {
156
+ scope,
157
+ resolver,
158
+ });
159
+ await next();
160
+ }
161
+ /** Resolve a container token, returning undefined instead of throwing when absent. */
162
+ function tryResolve(ctx, token) {
163
+ try {
164
+ return ctx.container.resolve(token);
165
+ }
166
+ catch {
167
+ return undefined;
168
+ }
169
+ }
170
+ /** Structural guard — the registry is a plain object carrying ability/policy tables. */
171
+ function isBouncerRegistry(value) {
172
+ return (typeof value === "object" &&
173
+ value !== null &&
174
+ "abilities" in value &&
175
+ "policies" in value);
176
+ }
177
+ /**
178
+ * Resolve the request's authorization scope from the registry's `resolveScope`
179
+ * hook (default `"global"`). Shared so the @Role/@Permission decorator gate and
180
+ * the Bouncer path evaluate in the SAME scope — without this the decorator path
181
+ * hardcoded "global" and tenant-scoped roles/grants never satisfied @Role/@Permission.
182
+ */
183
+ async function resolveRequestScope(ctx) {
184
+ const candidate = tryResolve(ctx, "bouncer:registry");
185
+ const registry = isBouncerRegistry(candidate) ? candidate : undefined;
186
+ return registry?.resolveScope ? await registry.resolveScope(ctx) : "global";
187
+ }
115
188
  /**
116
189
  * Try each declared strategy in order — session strategies via
117
190
  * `verifyWithContext()`, others via `verify(token)` with native-first credential
@@ -179,13 +252,13 @@ async function tryAuthenticate(auth, strategies, creds) {
179
252
  * EffectivePermissions set (Epic 56, D7). Returns the FORBIDDEN message, or null
180
253
  * when authorised (and zero-cost when neither decorator is present).
181
254
  */
182
- async function checkAuthorization(auth, user, controller, action) {
255
+ async function checkAuthorization(auth, user, controller, action, scope) {
183
256
  const requiredPermissions = getPermissionMetadata(controller, action);
184
257
  const requiredRoles = getRoleMetadata(controller, action);
185
258
  if (requiredPermissions.length === 0 && requiredRoles.length === 0) {
186
259
  return null;
187
260
  }
188
- const effective = await auth.resolvePermissions(user, "global");
261
+ const effective = await auth.resolvePermissions(user, scope);
189
262
  if (requiredPermissions.length > 0) {
190
263
  const missing = requiredPermissions.filter((p) => !effective.has(p));
191
264
  if (missing.length > 0)
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../src/standalone.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACN,WAAW,EACX,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,WAAW,MAAM;IACtB,oEAAoE;IACpE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9D,wDAAwD;IACxD,YAAY,CACX,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,qDAAqD;IACrD,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,mDAAmD;IACnD,OAAO,EAAE,WAAW,CAAC;IACrB,iFAAiF;IACjF,iBAAiB,IAAI,CACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,IAAI,EAAE,MAAM,IAAI,KACZ,IAAI,CAAC;CACV;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CA6EzD"}
1
+ {"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../src/standalone.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACN,WAAW,EACX,KAAK,UAAU,EAEf,KAAK,WAAW,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKhD,MAAM,WAAW,MAAM;IACtB,oEAAoE;IACpE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9D,wDAAwD;IACxD,YAAY,CACX,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAAC;IACvB,qDAAqD;IACrD,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,mDAAmD;IACnD,OAAO,EAAE,WAAW,CAAC;IACrB,iFAAiF;IACjF,iBAAiB,IAAI,CACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,IAAI,EAAE,MAAM,IAAI,KACZ,IAAI,CAAC;CACV;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAuFzD"}
@@ -17,15 +17,27 @@
17
17
  * if (!result.authenticated) return res.status(401).json(result)
18
18
  */
19
19
  import { AuthManager, } from "./AuthManager.js";
20
+ import { ApiKeyStrategy } from "./strategies/ApiKeyStrategy.js";
20
21
  import { JwtStrategy } from "./strategies/JwtStrategy.js";
22
+ import { SessionStrategy } from "./strategies/SessionStrategy.js";
21
23
  /**
22
24
  * Create a standalone Warden instance — no Ream container needed.
23
25
  */
24
26
  export function createWarden(config) {
27
+ // Mirror WardenProvider: build EVERY configured strategy, not just jwt —
28
+ // otherwise config.session / config.apiKey were silently dropped and a
29
+ // jwt-less config (e.g. { defaultStrategy: 'api-key', apiKey }) threw
30
+ // INVALID_CONFIG at boot (audit 2026-06-13). Keys match the @Guard names.
25
31
  const strategies = {};
26
32
  if (config.jwt) {
27
33
  strategies.jwt = new JwtStrategy(config.jwt);
28
34
  }
35
+ if (config.session) {
36
+ strategies.session = new SessionStrategy(config.session);
37
+ }
38
+ if (config.apiKey) {
39
+ strategies["api-key"] = new ApiKeyStrategy(config.apiKey);
40
+ }
29
41
  const manager = new AuthManager({
30
42
  defaultStrategy: config.defaultStrategy ?? "jwt",
31
43
  strategies,
@@ -1 +1 @@
1
- {"version":3,"file":"standalone.js","sourceRoot":"","sources":["../src/standalone.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACN,WAAW,GAGX,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAsB1D;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAoB;IAChD,MAAM,UAAU,GAAgC,EAAE,CAAC;IAEnD,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;QAChB,UAAU,CAAC,GAAG,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC;QAC/B,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,KAAK;QAChD,UAAU;KACV,CAAC,CAAC;IAEH,OAAO;QACN,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC;QAC5D,YAAY,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,CACvC,OAAO,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC;QAE5C,KAAK,CAAC,aAAa,CAAC,IAAiB;YACpC,MAAM,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAgB,CAAC;YACtD,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO;QAEP,iBAAiB;YAChB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;gBACzB,MAAM,OAAO,GAAG,GAAG,CAAC,OAA6C,CAAC;gBAClE,MAAM,UAAU,GAAG,OAAO,EAAE,aAAa,IAAI,EAAE,CAAC;gBAChD,MAAM,KAAK,GACV,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;oBACjE,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;oBACrB,CAAC,CAAC,EAAE,CAAC;gBAEP,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,GAAiE;yBAChE,MAAM,CAAC,GAAG,CAAC;yBACX,IAAI,CAAC;wBACL,KAAK,EAAE;4BACN,IAAI,EAAE,cAAc;4BACpB,OAAO,EAAE,8BAA8B;yBACvC;qBACD,CAAC,CAAC;oBACJ,OAAO;gBACR,CAAC;gBAED,OAAO;qBACL,MAAM,CAAC,KAAK,CAAC;qBACb,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;oBAChB,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;wBAC1C,GAAiE;6BAChE,MAAM,CAAC,GAAG,CAAC;6BACX,IAAI,CAAC;4BACL,KAAK,EAAE;gCACN,IAAI,EAAE,cAAc;gCACpB,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,uBAAuB;6BAChD;yBACD,CAAC,CAAC;wBACJ,OAAO;oBACR,CAAC;oBACD,iEAAiE;oBACjE,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC;oBAClB,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;oBACvB,IAAI,EAAE,CAAC;gBACR,CAAC,CAAC;qBACD,KAAK,CAAC,GAAG,EAAE;oBACV,GAAiE;yBAChE,MAAM,CAAC,GAAG,CAAC;yBACX,IAAI,CAAC;wBACL,KAAK,EAAE;4BACN,IAAI,EAAE,YAAY;4BAClB,OAAO,EAAE,+BAA+B;yBACxC;qBACD,CAAC,CAAC;gBACL,CAAC,CAAC,CAAC;YACL,CAAC,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"standalone.js","sourceRoot":"","sources":["../src/standalone.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ApiKeyStrategy.d.ts","sourceRoot":"","sources":["../../src/strategies/ApiKeyStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,CACV,GAAG,EAAE,MAAM,KACP,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC9D;AAED,qBAAa,cAAe,YAAW,YAAY;;IAClD,IAAI,SAAa;gBAIL,MAAM,EAAE,YAAY;IAKhC,wDAAwD;IACxD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAEK,YAAY,CAAC,YAAY,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,UAAU,CAAC;IAMjB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAYhD"}
1
+ {"version":3,"file":"ApiKeyStrategy.d.ts","sourceRoot":"","sources":["../../src/strategies/ApiKeyStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,CACV,GAAG,EAAE,MAAM,KACP,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC9D;AAED,qBAAa,cAAe,YAAW,YAAY;;IAClD,IAAI,SAAa;gBAIL,MAAM,EAAE,YAAY;IAKhC,wDAAwD;IACxD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAEK,YAAY,CAAC,YAAY,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,UAAU,CAAC;IAMjB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAyBhD"}
@@ -26,7 +26,20 @@ export class ApiKeyStrategy {
26
26
  return { authenticated: false, error: "Invalid API key" };
27
27
  const user = { ...result.user };
28
28
  if (result.scopes && result.scopes.length > 0) {
29
- // Merge scopes into permissions without mutating source object.
29
+ // Expose the API key's scopes on `user.permissions` (without mutating
30
+ // the source object) so APP code can read them via
31
+ // `ctx.auth.user.permissions`.
32
+ //
33
+ // IMPORTANT — these scopes are a SEPARATE axis from the `@Permission`
34
+ // route gate, by design (Adonis Bouncer parity): the gate flows through
35
+ // RightsResolver, which resolves grants from the rights STORE and
36
+ // deliberately ignores payload-carried permissions (see RightsResolver
37
+ // D1). This mirrors AdonisJS, where token abilities are checked via
38
+ // `currentAccessToken.allows(scope)` and are NOT consulted by Bouncer
39
+ // ability/policy checks. So an API key carrying `orders.create` is NOT
40
+ // auto-granted by `@Permission('orders.create')` — that's intentional,
41
+ // not a bug. Gate API-key routes on scopes with an explicit app-level
42
+ // check against `ctx.auth.user.permissions`.
30
43
  const merged = new Set([...(user.permissions ?? []), ...result.scopes]);
31
44
  user.permissions = [...merged];
32
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ApiKeyStrategy.js","sourceRoot":"","sources":["../../src/strategies/ApiKeyStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,MAAM,OAAO,cAAc;IAC1B,IAAI,GAAG,SAAS,CAAC;IACjB,OAAO,CAAe;IACtB,WAAW,CAAS;IAEpB,YAAY,MAAoB;QAC/B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,IAAI,WAAW,CAAC;IACrD,CAAC;IAED,wDAAwD;IACxD,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,YAGlB;QACA,MAAM,IAAI,KAAK,CACd,uFAAuF,CACvF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;QAEvE,MAAM,IAAI,GAAgB,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC7C,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,gEAAgE;YAChE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YACxE,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;CACD"}
1
+ {"version":3,"file":"ApiKeyStrategy.js","sourceRoot":"","sources":["../../src/strategies/ApiKeyStrategy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,MAAM,OAAO,cAAc;IAC1B,IAAI,GAAG,SAAS,CAAC;IACjB,OAAO,CAAe;IACtB,WAAW,CAAS;IAEpB,YAAY,MAAoB;QAC/B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,UAAU,IAAI,WAAW,CAAC;IACrD,CAAC;IAED,wDAAwD;IACxD,IAAI,UAAU;QACb,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,YAGlB;QACA,MAAM,IAAI,KAAK,CACd,uFAAuF,CACvF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;QAEvE,MAAM,IAAI,GAAgB,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC7C,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,sEAAsE;YACtE,mDAAmD;YACnD,+BAA+B;YAC/B,EAAE;YACF,sEAAsE;YACtE,wEAAwE;YACxE,kEAAkE;YAClE,uEAAuE;YACvE,oEAAoE;YACpE,sEAAsE;YACtE,uEAAuE;YACvE,uEAAuE;YACvE,sEAAsE;YACtE,6CAA6C;YAC7C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YACxE,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;CACD"}
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@c9up/warden",
3
- "version": "0.1.4",
4
- "description": "Warden — Authentication for the Ream framework",
3
+ "version": "0.1.6",
4
+ "description": "Warden — Authentication & authorization for the Ream framework",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
package/src/Guard.ts CHANGED
@@ -13,6 +13,7 @@ import "reflect-metadata";
13
13
  const GUARD_KEY = Symbol.for("warden:guard");
14
14
  const PERMISSION_KEY = Symbol.for("warden:permission");
15
15
  const ROLE_KEY = Symbol.for("warden:role");
16
+ const MFA_KEY = Symbol.for("warden:mfa");
16
17
 
17
18
  /**
18
19
  * @Guard('jwt') — require authentication via the named strategy.
@@ -66,3 +67,23 @@ export function getRoleMetadata(
66
67
  ): string[] {
67
68
  return Reflect.getOwnMetadata(ROLE_KEY, target, propertyKey) ?? [];
68
69
  }
70
+
71
+ /**
72
+ * @RequireMfa() — require the authenticated user to have completed multi-factor
73
+ * authentication. The auth middleware rejects with 403 `MFA_REQUIRED` when the
74
+ * user payload lacks a truthy `mfa` claim (set by your MFA step-up flow once
75
+ * `MfaManager.verify()` succeeds).
76
+ */
77
+ export function RequireMfa(): MethodDecorator {
78
+ return (target, propertyKey) => {
79
+ Reflect.defineMetadata(MFA_KEY, true, target, propertyKey);
80
+ };
81
+ }
82
+
83
+ /** Whether the route requires completed MFA. */
84
+ export function getRequireMfaMetadata(
85
+ target: object,
86
+ propertyKey: string | symbol,
87
+ ): boolean {
88
+ return Reflect.getOwnMetadata(MFA_KEY, target, propertyKey) ?? false;
89
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * RedisBlacklistDriver — a persistent JWT blacklist backed by Redis / KeyDB,
3
+ * so logout revocation survives a process restart (unlike MemoryBlacklistDriver).
4
+ *
5
+ * Agnostic by construction: it depends on no Redis package. The caller injects
6
+ * any ioredis-compatible client (KeyDB, Redis, a mock…) that exposes `set` with
7
+ * an `"EX"` ttl and `exists`. Native key expiry does the housekeeping, so
8
+ * `cleanup()` is a no-op.
9
+ */
10
+
11
+ import type { BlacklistDriver } from "./TokenBlacklist.js";
12
+
13
+ /** The minimal ioredis-shaped surface this driver needs. */
14
+ export interface RedisLikeClient {
15
+ set(
16
+ key: string,
17
+ value: string,
18
+ mode: "EX",
19
+ ttlSeconds: number,
20
+ ): Promise<unknown>;
21
+ exists(key: string): Promise<number>;
22
+ }
23
+
24
+ export interface RedisBlacklistConfig {
25
+ /** Key prefix for blacklist entries. Default `warden:blacklist:`. */
26
+ prefix?: string;
27
+ }
28
+
29
+ export class RedisBlacklistDriver implements BlacklistDriver {
30
+ readonly #client: RedisLikeClient;
31
+ readonly #prefix: string;
32
+
33
+ constructor(client: RedisLikeClient, config: RedisBlacklistConfig = {}) {
34
+ this.#client = client;
35
+ this.#prefix = config.prefix ?? "warden:blacklist:";
36
+ }
37
+
38
+ /**
39
+ * Blacklist a JTI until its natural expiry. Tokens already past `expiresAt`
40
+ * are skipped — there is nothing left to revoke.
41
+ */
42
+ async add(jti: string, expiresAt: number): Promise<void> {
43
+ const ttlSeconds = Math.ceil((expiresAt - Date.now()) / 1000);
44
+ if (ttlSeconds <= 0) {
45
+ return;
46
+ }
47
+ await this.#client.set(this.#key(jti), "1", "EX", ttlSeconds);
48
+ }
49
+
50
+ async has(jti: string): Promise<boolean> {
51
+ return (await this.#client.exists(this.#key(jti))) > 0;
52
+ }
53
+
54
+ /** No-op: Redis/KeyDB evicts expired keys on its own. */
55
+ async cleanup(): Promise<void> {}
56
+
57
+ #key(jti: string): string {
58
+ return `${this.#prefix}${jti}`;
59
+ }
60
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * ResilientBlacklistDriver — wraps a primary blacklist (e.g. KeyDB-backed
3
+ * `RedisBlacklistDriver`) with an in-memory fallback so a cache outage never
4
+ * takes the whole app down.
5
+ *
6
+ * Policy (fail-open on reads):
7
+ * - `add()` — if the primary throws, the revocation is recorded in the
8
+ * fallback so logout stays effective on this instance.
9
+ * - `has()` — if the primary throws, consult the fallback: a token revoked
10
+ * during the outage is still caught here; anything else is
11
+ * allowed through (fail-open). Access tokens are short-lived, so
12
+ * the window a missed revocation survives is bounded by the token
13
+ * TTL — the blacklist is defense-in-depth above expiry, not the
14
+ * primary boundary.
15
+ *
16
+ * Every degradation invokes `onDegrade` (defaults to a stderr warning) so the
17
+ * outage is observable.
18
+ */
19
+
20
+ import {
21
+ type BlacklistDriver,
22
+ MemoryBlacklistDriver,
23
+ } from "./TokenBlacklist.js";
24
+
25
+ export interface BlacklistDegradeEvent {
26
+ op: "add" | "has" | "cleanup";
27
+ error: unknown;
28
+ }
29
+
30
+ export interface ResilientBlacklistConfig {
31
+ /** Invoked whenever the primary driver fails and the fallback is used. */
32
+ onDegrade?: (event: BlacklistDegradeEvent) => void;
33
+ }
34
+
35
+ function defaultOnDegrade({ op, error }: BlacklistDegradeEvent): void {
36
+ console.warn(
37
+ `[warden] blacklist primary failed on ${op}; using in-memory fallback:`,
38
+ error,
39
+ );
40
+ }
41
+
42
+ export class ResilientBlacklistDriver implements BlacklistDriver {
43
+ readonly #primary: BlacklistDriver;
44
+ readonly #fallback: BlacklistDriver;
45
+ readonly #onDegrade: (event: BlacklistDegradeEvent) => void;
46
+
47
+ constructor(
48
+ primary: BlacklistDriver,
49
+ fallback: BlacklistDriver = new MemoryBlacklistDriver(),
50
+ config: ResilientBlacklistConfig = {},
51
+ ) {
52
+ this.#primary = primary;
53
+ this.#fallback = fallback;
54
+ this.#onDegrade = config.onDegrade ?? defaultOnDegrade;
55
+ }
56
+
57
+ async add(jti: string, expiresAt: number): Promise<void> {
58
+ try {
59
+ await this.#primary.add(jti, expiresAt);
60
+ } catch (error) {
61
+ this.#onDegrade({ op: "add", error });
62
+ await this.#fallback.add(jti, expiresAt);
63
+ }
64
+ }
65
+
66
+ async has(jti: string): Promise<boolean> {
67
+ try {
68
+ return await this.#primary.has(jti);
69
+ } catch (error) {
70
+ this.#onDegrade({ op: "has", error });
71
+ // Fail-open: honour in-outage revocations on this instance, allow rest.
72
+ return this.#fallback.has(jti);
73
+ }
74
+ }
75
+
76
+ async cleanup(): Promise<void> {
77
+ try {
78
+ await this.#primary.cleanup?.();
79
+ } catch (error) {
80
+ this.#onDegrade({ op: "cleanup", error });
81
+ }
82
+ await this.#fallback.cleanup?.();
83
+ }
84
+ }
@@ -9,7 +9,11 @@
9
9
  export interface BlacklistDriver {
10
10
  add(jti: string, expiresAt: number): Promise<void>;
11
11
  has(jti: string): Promise<boolean>;
12
- cleanup(): Promise<void>;
12
+ /**
13
+ * Reap expired entries. Optional: TTL-backed stores (Redis/KeyDB) expire keys
14
+ * themselves and have nothing to sweep, so they may omit this.
15
+ */
16
+ cleanup?(): Promise<void>;
13
17
  }
14
18
 
15
19
  /** In-memory blacklist for development. */
@@ -51,8 +55,8 @@ export class TokenBlacklist {
51
55
  return this.driver.has(jti);
52
56
  }
53
57
 
54
- /** Remove expired entries. */
58
+ /** Remove expired entries (no-op when the driver self-expires via TTL). */
55
59
  async cleanup(): Promise<void> {
56
- return this.driver.cleanup();
60
+ await this.driver.cleanup?.();
57
61
  }
58
62
  }
@@ -1,10 +1,14 @@
1
- import { AuthManager } from "./AuthManager.js";
1
+ import { AuthManager, type AuthStrategy } from "./AuthManager.js";
2
2
  import type { WardenConfig } from "./config.js";
3
3
  import { WardenError } from "./errors.js";
4
+ import { MfaManager } from "./mfa/MfaManager.js";
5
+ import type { BouncerRegistry } from "./middleware.js";
4
6
  import { MemoryRightsStore } from "./rights/MemoryRightsStore.js";
5
7
  import { RightsResolver } from "./rights/RightsResolver.js";
6
8
  import { setAuth } from "./services/main.js";
9
+ import { ApiKeyStrategy } from "./strategies/ApiKeyStrategy.js";
7
10
  import { JwtStrategy } from "./strategies/JwtStrategy.js";
11
+ import { SessionStrategy } from "./strategies/SessionStrategy.js";
8
12
 
9
13
  interface WardenContainer {
10
14
  singleton(token: unknown, factory: () => unknown): void;
@@ -35,15 +39,34 @@ export default class WardenProvider {
35
39
  // AuthManager with `strategies: {}` and `defaultStrategy: 'jwt'`,
36
40
  // passing the (then-permissive) constructor and erroring deep in the
37
41
  // middleware loop.
38
- if (!config?.jwt) {
42
+ if (!config?.jwt && !config?.session && !config?.apiKey) {
39
43
  throw new WardenError(
40
44
  "WARDEN_NO_AUTH_CONFIG",
41
- `@c9up/warden: no authentication strategies configured. Set config.warden.auth.jwt (or another strategy) in your reamrc.ts before registering WardenProvider.`,
45
+ `@c9up/warden: no authentication strategies configured. Set at least one of config.warden.auth.jwt / .session / .apiKey in your reamrc.ts before registering WardenProvider.`,
42
46
  );
43
47
  }
44
48
 
45
- const jwt = new JwtStrategy(config.jwt);
46
- this.app.container.singleton(JwtStrategy, () => jwt);
49
+ // Build the strategy table from whatever the app configured. Each strategy
50
+ // is also exposed by its class token (mirrors the jwt convention) so apps
51
+ // can resolve a specific one. The `revoke()` blacklist flows through
52
+ // `config.jwt.blacklist` into JwtStrategy.
53
+ const strategies: Record<string, AuthStrategy> = {};
54
+
55
+ if (config.jwt) {
56
+ const jwt = new JwtStrategy(config.jwt);
57
+ this.app.container.singleton(JwtStrategy, () => jwt);
58
+ strategies.jwt = jwt;
59
+ }
60
+ if (config.session) {
61
+ const session = new SessionStrategy(config.session);
62
+ this.app.container.singleton(SessionStrategy, () => session);
63
+ strategies.session = session;
64
+ }
65
+ if (config.apiKey) {
66
+ const apiKey = new ApiKeyStrategy(config.apiKey);
67
+ this.app.container.singleton(ApiKeyStrategy, () => apiKey);
68
+ strategies["api-key"] = apiKey;
69
+ }
47
70
 
48
71
  // Rights layer (Epic 56): one resolver singleton backs BOTH the coarse
49
72
  // RBAC helpers (injected into AuthManager below) and — once 56.6 lands —
@@ -59,10 +82,23 @@ export default class WardenProvider {
59
82
  this.app.container.singleton(MemoryRightsStore, () => rightsStore);
60
83
  }
61
84
 
85
+ // Bouncer registry (Epic 56.6): the abilities/policies/scope-resolver the
86
+ // per-request `initializeBouncer` middleware builds each `ctx.bouncer`
87
+ // from. Registered (even when empty) under a string token so the agnostic
88
+ // middleware resolves it by name, mirroring the "auth" alias above.
89
+ const bouncerRegistry: BouncerRegistry = {
90
+ abilities: config.abilities ?? {},
91
+ policies: config.policies ?? {},
92
+ resolveScope: config.resolveScope,
93
+ };
94
+ this.app.container.singleton("bouncer:registry", () => bouncerRegistry);
95
+
96
+ // Default to the configured strategy, else the first one registered.
97
+ const defaultStrategy =
98
+ config.defaultStrategy ?? Object.keys(strategies)[0];
62
99
  this.app.container.singleton(AuthManager, () => {
63
- const strategies: Record<string, JwtStrategy> = { jwt };
64
100
  return new AuthManager({
65
- defaultStrategy: config.defaultStrategy ?? "jwt",
101
+ defaultStrategy,
66
102
  strategies,
67
103
  rights: rightsResolver,
68
104
  });
@@ -76,6 +112,16 @@ export default class WardenProvider {
76
112
  this.app.container.singleton("auth", () =>
77
113
  this.app.container.resolve(AuthManager),
78
114
  );
115
+
116
+ // MFA (optional): the app builds an MfaManager with its persistent stores
117
+ // + providers and passes it via config.mfa. Registered by class and under
118
+ // the "mfa" string alias (same convention as "auth") so controllers and
119
+ // agnostic consumers can resolve it.
120
+ const mfa = config.mfa?.manager;
121
+ if (mfa) {
122
+ this.app.container.singleton(MfaManager, () => mfa);
123
+ this.app.container.singleton("mfa", () => mfa);
124
+ }
79
125
  }
80
126
 
81
127
  async boot() {