@strapi/core 5.24.0 → 5.24.2

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 (31) hide show
  1. package/dist/Strapi.d.ts.map +1 -1
  2. package/dist/Strapi.js +16 -14
  3. package/dist/Strapi.js.map +1 -1
  4. package/dist/Strapi.mjs +16 -14
  5. package/dist/Strapi.mjs.map +1 -1
  6. package/dist/package.json.js +11 -11
  7. package/dist/package.json.mjs +11 -11
  8. package/dist/providers/index.js +1 -1
  9. package/dist/providers/index.js.map +1 -1
  10. package/dist/providers/index.mjs +1 -1
  11. package/dist/providers/index.mjs.map +1 -1
  12. package/dist/providers/{sessionManager.d.ts → session-manager.d.ts} +1 -1
  13. package/dist/providers/session-manager.d.ts.map +1 -0
  14. package/dist/providers/{sessionManager.js → session-manager.js} +6 -4
  15. package/dist/providers/session-manager.js.map +1 -0
  16. package/dist/providers/{sessionManager.mjs → session-manager.mjs} +6 -4
  17. package/dist/providers/session-manager.mjs.map +1 -0
  18. package/dist/services/session-manager.d.ts +8 -1
  19. package/dist/services/session-manager.d.ts.map +1 -1
  20. package/dist/services/session-manager.js +74 -21
  21. package/dist/services/session-manager.js.map +1 -1
  22. package/dist/services/session-manager.mjs +74 -21
  23. package/dist/services/session-manager.mjs.map +1 -1
  24. package/package.json +11 -11
  25. package/dist/providers/sessionManager.d.ts.map +0 -1
  26. package/dist/providers/sessionManager.js.map +0 -1
  27. package/dist/providers/sessionManager.mjs.map +0 -1
  28. package/dist/services/document-service/utils/clean-component-join-table.js +0 -138
  29. package/dist/services/document-service/utils/clean-component-join-table.js.map +0 -1
  30. package/dist/services/document-service/utils/clean-component-join-table.mjs +0 -136
  31. package/dist/services/document-service/utils/clean-component-join-table.mjs.map +0 -1
@@ -5,17 +5,19 @@ var sessionManager$1 = require('../services/session-manager.js');
5
5
 
6
6
  var sessionManager = provider.defineProvider({
7
7
  init (strapi) {
8
+ strapi.add('sessionManager', ()=>sessionManager$1.createSessionManager({
9
+ db: strapi.db
10
+ }));
11
+ },
12
+ async register (strapi) {
8
13
  // Get JWT secret from admin auth settings (same as admin token service)
9
14
  const adminAuth = strapi.config.get('admin.auth', {});
10
15
  const jwtSecret = adminAuth.secret;
11
16
  if (!jwtSecret) {
12
17
  throw new Error('Missing admin.auth.secret configuration. The SessionManager requires a JWT secret');
13
18
  }
14
- strapi.add('sessionManager', ()=>sessionManager$1.createSessionManager({
15
- db: strapi.db
16
- }));
17
19
  }
18
20
  });
19
21
 
20
22
  module.exports = sessionManager;
21
- //# sourceMappingURL=sessionManager.js.map
23
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sources":["../../src/providers/session-manager.ts"],"sourcesContent":["import type { Algorithm } from 'jsonwebtoken';\nimport { defineProvider } from './provider';\nimport { createSessionManager } from '../services/session-manager';\n\ninterface AdminAuthConfig {\n secret?: string;\n options?: {\n algorithm?: Algorithm;\n [key: string]: unknown;\n };\n}\n\nexport default defineProvider({\n init(strapi) {\n strapi.add('sessionManager', () =>\n createSessionManager({\n db: strapi.db,\n })\n );\n },\n\n async register(strapi) {\n // Get JWT secret from admin auth settings (same as admin token service)\n const adminAuth = strapi.config.get<AdminAuthConfig>('admin.auth', {});\n const jwtSecret = adminAuth.secret;\n\n if (!jwtSecret) {\n throw new Error(\n 'Missing admin.auth.secret configuration. The SessionManager requires a JWT secret'\n );\n }\n },\n});\n"],"names":["defineProvider","init","strapi","add","createSessionManager","db","register","adminAuth","config","get","jwtSecret","secret","Error"],"mappings":";;;;;AAYA,qBAAeA,uBAAe,CAAA;AAC5BC,IAAAA,IAAAA,CAAAA,CAAKC,MAAM,EAAA;AACTA,QAAAA,MAAAA,CAAOC,GAAG,CAAC,gBAAkB,EAAA,IAC3BC,qCAAqB,CAAA;AACnBC,gBAAAA,EAAAA,EAAIH,OAAOG;AACb,aAAA,CAAA,CAAA;AAEJ,KAAA;AAEA,IAAA,MAAMC,UAASJ,MAAM,EAAA;;AAEnB,QAAA,MAAMK,YAAYL,MAAOM,CAAAA,MAAM,CAACC,GAAG,CAAkB,cAAc,EAAC,CAAA;QACpE,MAAMC,SAAAA,GAAYH,UAAUI,MAAM;AAElC,QAAA,IAAI,CAACD,SAAW,EAAA;AACd,YAAA,MAAM,IAAIE,KACR,CAAA,mFAAA,CAAA;AAEJ;AACF;AACF,CAAG,CAAA;;;;"}
@@ -3,17 +3,19 @@ import { createSessionManager } from '../services/session-manager.mjs';
3
3
 
4
4
  var sessionManager = defineProvider({
5
5
  init (strapi) {
6
+ strapi.add('sessionManager', ()=>createSessionManager({
7
+ db: strapi.db
8
+ }));
9
+ },
10
+ async register (strapi) {
6
11
  // Get JWT secret from admin auth settings (same as admin token service)
7
12
  const adminAuth = strapi.config.get('admin.auth', {});
8
13
  const jwtSecret = adminAuth.secret;
9
14
  if (!jwtSecret) {
10
15
  throw new Error('Missing admin.auth.secret configuration. The SessionManager requires a JWT secret');
11
16
  }
12
- strapi.add('sessionManager', ()=>createSessionManager({
13
- db: strapi.db
14
- }));
15
17
  }
16
18
  });
17
19
 
18
20
  export { sessionManager as default };
19
- //# sourceMappingURL=sessionManager.mjs.map
21
+ //# sourceMappingURL=session-manager.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.mjs","sources":["../../src/providers/session-manager.ts"],"sourcesContent":["import type { Algorithm } from 'jsonwebtoken';\nimport { defineProvider } from './provider';\nimport { createSessionManager } from '../services/session-manager';\n\ninterface AdminAuthConfig {\n secret?: string;\n options?: {\n algorithm?: Algorithm;\n [key: string]: unknown;\n };\n}\n\nexport default defineProvider({\n init(strapi) {\n strapi.add('sessionManager', () =>\n createSessionManager({\n db: strapi.db,\n })\n );\n },\n\n async register(strapi) {\n // Get JWT secret from admin auth settings (same as admin token service)\n const adminAuth = strapi.config.get<AdminAuthConfig>('admin.auth', {});\n const jwtSecret = adminAuth.secret;\n\n if (!jwtSecret) {\n throw new Error(\n 'Missing admin.auth.secret configuration. The SessionManager requires a JWT secret'\n );\n }\n },\n});\n"],"names":["defineProvider","init","strapi","add","createSessionManager","db","register","adminAuth","config","get","jwtSecret","secret","Error"],"mappings":";;;AAYA,qBAAeA,cAAe,CAAA;AAC5BC,IAAAA,IAAAA,CAAAA,CAAKC,MAAM,EAAA;AACTA,QAAAA,MAAAA,CAAOC,GAAG,CAAC,gBAAkB,EAAA,IAC3BC,oBAAqB,CAAA;AACnBC,gBAAAA,EAAAA,EAAIH,OAAOG;AACb,aAAA,CAAA,CAAA;AAEJ,KAAA;AAEA,IAAA,MAAMC,UAASJ,MAAM,EAAA;;AAEnB,QAAA,MAAMK,YAAYL,MAAOM,CAAAA,MAAM,CAACC,GAAG,CAAkB,cAAc,EAAC,CAAA;QACpE,MAAMC,SAAAA,GAAYH,UAAUI,MAAM;AAElC,QAAA,IAAI,CAACD,SAAW,EAAA;AACd,YAAA,MAAM,IAAIE,KACR,CAAA,mFAAA,CAAA;AAEJ;AACF;AACF,CAAG,CAAA;;;;"}
@@ -1,3 +1,4 @@
1
+ import type { Algorithm } from 'jsonwebtoken';
1
2
  import type { Database } from '@strapi/database';
2
3
  export interface SessionProvider {
3
4
  create(session: SessionData): Promise<SessionData>;
@@ -47,12 +48,14 @@ export interface ValidateRefreshTokenResult {
47
48
  error?: 'invalid_token' | 'token_expired' | 'session_not_found' | 'session_expired' | 'wrong_token_type';
48
49
  }
49
50
  export interface SessionManagerConfig {
50
- jwtSecret: string;
51
+ jwtSecret?: string;
51
52
  accessTokenLifespan: number;
52
53
  maxRefreshTokenLifespan: number;
53
54
  idleRefreshTokenLifespan: number;
54
55
  maxSessionLifespan: number;
55
56
  idleSessionLifespan: number;
57
+ algorithm?: Algorithm;
58
+ jwtOptions?: Record<string, unknown>;
56
59
  }
57
60
  declare class OriginSessionManager {
58
61
  private sessionManager;
@@ -111,6 +114,10 @@ declare class SessionManager {
111
114
  * Get configuration for a specific origin, throw error if not defined
112
115
  */
113
116
  private getConfigForOrigin;
117
+ /**
118
+ * Get the appropriate JWT key based on the algorithm
119
+ */
120
+ private getJwtKey;
114
121
  generateSessionId(): string;
115
122
  private maybeCleanupExpired;
116
123
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/services/session-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/services/session-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGjD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAChE,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5F;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,IAAI,CAAC;IAChB,iBAAiB,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EACF,eAAe,GACf,eAAe,GACf,mBAAmB,GACnB,iBAAiB,GACjB,kBAAkB,CAAC;CACxB;AAqDD,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,uBAAuB,EAAE,MAAM,CAAC;IAChC,wBAAwB,EAAE,MAAM,CAAC;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,cAAM,oBAAoB;IAEtB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,MAAM;gBADN,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM;IAGlB,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;KAAE,GACzC,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE,CAAC;IAIrE,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAIzF,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CACnD;QACE,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;KAC7B,GACD;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CACpB;IAID,mBAAmB,CACjB,KAAK,EAAE,MAAM,GACZ;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,kBAAkB,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,IAAI,CAAA;KAAE;IAI/E,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAIxE,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E;;;OAGG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG3D;AAED,cAAM,cAAc;IAClB,OAAO,CAAC,QAAQ,CAAkB;IAGlC,OAAO,CAAC,aAAa,CAAgD;IAGrE,OAAO,CAAC,wBAAwB,CAAa;IAE7C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAc;gBAEpC,QAAQ,EAAE,eAAe;IAIrC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAIhE;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIlC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAU1B;;OAEG;IACH,OAAO,CAAC,SAAS;IAqCjB,iBAAiB,IAAI,MAAM;YAIb,mBAAmB;IASjC;;OAEG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAEK,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;KAAE,GACzC,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAE,CAAC;IAiE3E,mBAAmB,CACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,OAAO,EAAE,kBAAkB,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,IAAI,CAAA;KAAE;IA2B/E,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IA4DxF,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxF,mBAAmB,CACvB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAmC3C,kBAAkB,CACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CACN;QACE,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;KAC7B,GACD;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CACpB;IAmJD;;;OAGG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAmB3E;AAED,QAAA,MAAM,sBAAsB,OAAQ,QAAQ,eAAe,MAAM,KAAG,eAEnE,CAAC;AAEF,QAAA,MAAM,oBAAoB,YAEvB;IACD,EAAE,EAAE,QAAQ,CAAC;CACd,KAAG,cAAc,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,KAAK,oBAAoB,CA8B7D,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,CAAC"}
@@ -113,6 +113,32 @@ class SessionManager {
113
113
  }
114
114
  throw new Error(`SessionManager: Origin '${origin}' is not defined. Please define it using defineOrigin('${origin}', config).`);
115
115
  }
116
+ /**
117
+ * Get the appropriate JWT key based on the algorithm
118
+ */ getJwtKey(config, algorithm, operation) {
119
+ const isAsymmetric = algorithm.startsWith('RS') || algorithm.startsWith('ES') || algorithm.startsWith('PS');
120
+ if (isAsymmetric) {
121
+ // For asymmetric algorithms, check if user has provided proper key configuration
122
+ if (operation === 'sign') {
123
+ const privateKey = config.jwtOptions?.privateKey;
124
+ if (privateKey) {
125
+ return privateKey;
126
+ }
127
+ throw new Error(`SessionManager: Private key is required for asymmetric algorithm ${algorithm}. Please configure admin.auth.options.privateKey.`);
128
+ } else {
129
+ const publicKey = config.jwtOptions?.publicKey;
130
+ if (publicKey) {
131
+ return publicKey;
132
+ }
133
+ throw new Error(`SessionManager: Public key is required for asymmetric algorithm ${algorithm}. Please configure admin.auth.options.publicKey.`);
134
+ }
135
+ } else {
136
+ if (!config.jwtSecret) {
137
+ throw new Error(`SessionManager: Secret key is required for symmetric algorithm ${algorithm}`);
138
+ }
139
+ return config.jwtSecret;
140
+ }
141
+ }
116
142
  generateSessionId() {
117
143
  return crypto.randomBytes(16).toString('hex');
118
144
  }
@@ -134,6 +160,8 @@ class SessionManager {
134
160
  }
135
161
  await this.maybeCleanupExpired();
136
162
  const config = this.getConfigForOrigin(origin);
163
+ const algorithm = config.algorithm || constants.DEFAULT_ALGORITHM;
164
+ const jwtKey = this.getJwtKey(config, algorithm, 'sign');
137
165
  const sessionId = this.generateSessionId();
138
166
  const tokenType = options?.type ?? 'refresh';
139
167
  const isRefresh = tokenType === 'refresh';
@@ -165,9 +193,13 @@ class SessionManager {
165
193
  iat: issuedAtSeconds,
166
194
  exp: expiresAtSeconds
167
195
  };
168
- const token = jwt.sign(payload, config.jwtSecret, {
169
- algorithm: constants.DEFAULT_ALGORITHM,
170
- noTimestamp: true
196
+ // Filter out conflicting options that are already handled by the payload or used for key selection
197
+ const jwtOptions = config.jwtOptions || {};
198
+ const { expiresIn, privateKey, publicKey, ...jwtSignOptions } = jwtOptions;
199
+ const token = jwt.sign(payload, jwtKey, {
200
+ algorithm,
201
+ noTimestamp: true,
202
+ ...jwtSignOptions
171
203
  });
172
204
  return {
173
205
  token,
@@ -181,10 +213,13 @@ class SessionManager {
181
213
  }
182
214
  try {
183
215
  const config = this.getConfigForOrigin(origin);
184
- const payload = jwt.verify(token, config.jwtSecret, {
216
+ const algorithm = config.algorithm || constants.DEFAULT_ALGORITHM;
217
+ const jwtKey = this.getJwtKey(config, algorithm, 'verify');
218
+ const payload = jwt.verify(token, jwtKey, {
185
219
  algorithms: [
186
- constants.DEFAULT_ALGORITHM
187
- ]
220
+ algorithm
221
+ ],
222
+ ...config.jwtOptions
188
223
  });
189
224
  // Ensure this is an access token
190
225
  if (!payload || payload.type !== 'access') {
@@ -210,12 +245,15 @@ class SessionManager {
210
245
  }
211
246
  try {
212
247
  const config = this.getConfigForOrigin(origin);
248
+ const algorithm = config.algorithm || constants.DEFAULT_ALGORITHM;
249
+ const jwtKey = this.getJwtKey(config, algorithm, 'verify');
213
250
  const verifyOptions = {
214
251
  algorithms: [
215
- constants.DEFAULT_ALGORITHM
216
- ]
252
+ algorithm
253
+ ],
254
+ ...config.jwtOptions
217
255
  };
218
- const payload = jwt.verify(token, config.jwtSecret, verifyOptions);
256
+ const payload = jwt.verify(token, jwtKey, verifyOptions);
219
257
  if (payload.type !== 'refresh') {
220
258
  return {
221
259
  isValid: false
@@ -287,9 +325,15 @@ class SessionManager {
287
325
  type: 'access'
288
326
  };
289
327
  const config = this.getConfigForOrigin(origin);
290
- const token = jwt.sign(payload, config.jwtSecret, {
291
- algorithm: constants.DEFAULT_ALGORITHM,
292
- expiresIn: config.accessTokenLifespan
328
+ const algorithm = config.algorithm || constants.DEFAULT_ALGORITHM;
329
+ const jwtKey = this.getJwtKey(config, algorithm, 'sign');
330
+ // Filter out conflicting options that are already handled by the payload or used for key selection
331
+ const jwtOptions = config.jwtOptions || {};
332
+ const { expiresIn, privateKey, publicKey, ...jwtSignOptions } = jwtOptions;
333
+ const token = jwt.sign(payload, jwtKey, {
334
+ algorithm,
335
+ expiresIn: config.accessTokenLifespan,
336
+ ...jwtSignOptions
293
337
  });
294
338
  return {
295
339
  token
@@ -301,10 +345,13 @@ class SessionManager {
301
345
  }
302
346
  try {
303
347
  const config = this.getConfigForOrigin(origin);
304
- const payload = jwt.verify(refreshToken, config.jwtSecret, {
348
+ const algorithm = config.algorithm || constants.DEFAULT_ALGORITHM;
349
+ const jwtKey = this.getJwtKey(config, algorithm, 'verify');
350
+ const payload = jwt.verify(refreshToken, jwtKey, {
305
351
  algorithms: [
306
- constants.DEFAULT_ALGORITHM
307
- ]
352
+ algorithm
353
+ ],
354
+ ...config.jwtOptions
308
355
  });
309
356
  if (!payload || payload.type !== 'refresh') {
310
357
  return {
@@ -330,9 +377,12 @@ class SessionManager {
330
377
  iat: childIat,
331
378
  exp: childExp
332
379
  };
333
- const childToken = jwt.sign(childPayload, config.jwtSecret, {
334
- algorithm: constants.DEFAULT_ALGORITHM,
335
- noTimestamp: true
380
+ // Filter out conflicting options that are already handled by the payload
381
+ const { expiresIn, ...jwtSignOptions } = config.jwtOptions || {};
382
+ const childToken = jwt.sign(childPayload, jwtKey, {
383
+ algorithm,
384
+ noTimestamp: true,
385
+ ...jwtSignOptions
336
386
  });
337
387
  let absoluteExpiresAt;
338
388
  if (child.absoluteExpiresAt) {
@@ -389,9 +439,12 @@ class SessionManager {
389
439
  iat: childIat,
390
440
  exp: childExp
391
441
  };
392
- const childToken = jwt.sign(payloadOut, config.jwtSecret, {
393
- algorithm: constants.DEFAULT_ALGORITHM,
394
- noTimestamp: true
442
+ // Filter out conflicting options that are already handled by the payload
443
+ const { expiresIn, ...jwtSignOptions } = config.jwtOptions || {};
444
+ const childToken = jwt.sign(payloadOut, jwtKey, {
445
+ algorithm,
446
+ noTimestamp: true,
447
+ ...jwtSignOptions
395
448
  });
396
449
  await this.provider.updateBySessionId(current.sessionId, {
397
450
  status: 'rotated',
@@ -1 +1 @@
1
- {"version":3,"file":"session-manager.js","sources":["../../src/services/session-manager.ts"],"sourcesContent":["import crypto from 'crypto';\nimport jwt from 'jsonwebtoken';\nimport type { VerifyOptions } from 'jsonwebtoken';\nimport type { Database } from '@strapi/database';\nimport { DEFAULT_ALGORITHM } from '../constants';\n\nexport interface SessionProvider {\n create(session: SessionData): Promise<SessionData>;\n findBySessionId(sessionId: string): Promise<SessionData | null>;\n updateBySessionId(sessionId: string, data: Partial<SessionData>): Promise<void>;\n deleteBySessionId(sessionId: string): Promise<void>;\n deleteExpired(): Promise<void>;\n deleteBy(criteria: { userId?: string; origin?: string; deviceId?: string }): Promise<void>;\n}\n\nexport interface SessionData {\n id?: string;\n userId: string; // User ID stored as string (key-value store)\n sessionId: string;\n deviceId?: string; // Optional for origins that don't need device tracking\n origin: string;\n childId?: string | null;\n\n type?: 'refresh' | 'session';\n status?: 'active' | 'rotated' | 'revoked';\n expiresAt: Date;\n absoluteExpiresAt?: Date | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nexport interface RefreshTokenPayload {\n userId: string;\n sessionId: string;\n type: 'refresh';\n exp: number;\n iat: number;\n}\n\nexport interface AccessTokenPayload {\n userId: string;\n sessionId: string;\n type: 'access';\n exp: number;\n iat: number;\n}\n\nexport type TokenPayload = RefreshTokenPayload | AccessTokenPayload;\n\nexport interface ValidateRefreshTokenResult {\n isValid: boolean;\n userId?: string;\n sessionId?: string;\n error?:\n | 'invalid_token'\n | 'token_expired'\n | 'session_not_found'\n | 'session_expired'\n | 'wrong_token_type';\n}\n\nclass DatabaseSessionProvider implements SessionProvider {\n private db: Database;\n\n private contentType: string;\n\n constructor(db: Database, contentType: string) {\n this.db = db;\n this.contentType = contentType;\n }\n\n async create(session: SessionData): Promise<SessionData> {\n const result = await this.db.query(this.contentType).create({\n data: session,\n });\n return result as SessionData;\n }\n\n async findBySessionId(sessionId: string): Promise<SessionData | null> {\n const result = await this.db.query(this.contentType).findOne({\n where: { sessionId },\n });\n return result as SessionData | null;\n }\n\n async updateBySessionId(sessionId: string, data: Partial<SessionData>): Promise<void> {\n await this.db.query(this.contentType).update({ where: { sessionId }, data });\n }\n\n async deleteBySessionId(sessionId: string): Promise<void> {\n await this.db.query(this.contentType).delete({\n where: { sessionId },\n });\n }\n\n async deleteExpired(): Promise<void> {\n await this.db.query(this.contentType).deleteMany({\n where: { absoluteExpiresAt: { $lt: new Date() } },\n });\n }\n\n async deleteBy(criteria: { userId?: string; origin?: string; deviceId?: string }): Promise<void> {\n await this.db.query(this.contentType).deleteMany({\n where: {\n ...(criteria.userId ? { userId: criteria.userId } : {}),\n ...(criteria.origin ? { origin: criteria.origin } : {}),\n ...(criteria.deviceId ? { deviceId: criteria.deviceId } : {}),\n },\n });\n }\n}\n\nexport interface SessionManagerConfig {\n jwtSecret: string;\n accessTokenLifespan: number;\n maxRefreshTokenLifespan: number;\n idleRefreshTokenLifespan: number;\n maxSessionLifespan: number;\n idleSessionLifespan: number;\n}\n\nclass OriginSessionManager {\n constructor(\n private sessionManager: SessionManager,\n private origin: string\n ) {}\n\n async generateRefreshToken(\n userId: string,\n deviceId: string | undefined,\n options?: { type?: 'refresh' | 'session' }\n ): Promise<{ token: string; sessionId: string; absoluteExpiresAt: string }> {\n return this.sessionManager.generateRefreshToken(userId, deviceId, this.origin, options);\n }\n\n async generateAccessToken(refreshToken: string): Promise<{ token: string } | { error: string }> {\n return this.sessionManager.generateAccessToken(refreshToken, this.origin);\n }\n\n async rotateRefreshToken(refreshToken: string): Promise<\n | {\n token: string;\n sessionId: string;\n absoluteExpiresAt: string;\n type: 'refresh' | 'session';\n }\n | { error: string }\n > {\n return this.sessionManager.rotateRefreshToken(refreshToken, this.origin);\n }\n\n validateAccessToken(\n token: string\n ): { isValid: true; payload: AccessTokenPayload } | { isValid: false; payload: null } {\n return this.sessionManager.validateAccessToken(token, this.origin);\n }\n\n async validateRefreshToken(token: string): Promise<ValidateRefreshTokenResult> {\n return this.sessionManager.validateRefreshToken(token, this.origin);\n }\n\n async invalidateRefreshToken(userId: string, deviceId?: string): Promise<void> {\n return this.sessionManager.invalidateRefreshToken(this.origin, userId, deviceId);\n }\n\n /**\n * Returns true when a session exists and is not expired for this origin.\n * If the session exists but is expired, it will be deleted as part of this check.\n */\n async isSessionActive(sessionId: string): Promise<boolean> {\n return this.sessionManager.isSessionActive(sessionId, this.origin);\n }\n}\n\nclass SessionManager {\n private provider: SessionProvider;\n\n // Store origin-specific configurations\n private originConfigs: Map<string, SessionManagerConfig> = new Map();\n\n // Run expired cleanup only every N calls to avoid extra queries\n private cleanupInvocationCounter: number = 0;\n\n private readonly cleanupEveryCalls: number = 50;\n\n constructor(provider: SessionProvider) {\n this.provider = provider;\n }\n\n /**\n * Define configuration for a specific origin\n */\n defineOrigin(origin: string, config: SessionManagerConfig): void {\n this.originConfigs.set(origin, config);\n }\n\n /**\n * Check if an origin is defined\n */\n hasOrigin(origin: string): boolean {\n return this.originConfigs.has(origin);\n }\n\n /**\n * Get configuration for a specific origin, throw error if not defined\n */\n private getConfigForOrigin(origin: string): SessionManagerConfig {\n const originConfig = this.originConfigs.get(origin);\n if (originConfig) {\n return originConfig;\n }\n throw new Error(\n `SessionManager: Origin '${origin}' is not defined. Please define it using defineOrigin('${origin}', config).`\n );\n }\n\n generateSessionId(): string {\n return crypto.randomBytes(16).toString('hex');\n }\n\n private async maybeCleanupExpired(): Promise<void> {\n this.cleanupInvocationCounter += 1;\n if (this.cleanupInvocationCounter >= this.cleanupEveryCalls) {\n this.cleanupInvocationCounter = 0;\n\n await this.provider.deleteExpired();\n }\n }\n\n /**\n * Get the cleanup every calls threshold\n */\n get cleanupThreshold(): number {\n return this.cleanupEveryCalls;\n }\n\n async generateRefreshToken(\n userId: string,\n deviceId: string | undefined,\n origin: string,\n options?: { type?: 'refresh' | 'session' }\n ): Promise<{ token: string; sessionId: string; absoluteExpiresAt: string }> {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n await this.maybeCleanupExpired();\n\n const config = this.getConfigForOrigin(origin);\n const sessionId = this.generateSessionId();\n const tokenType = options?.type ?? 'refresh';\n const isRefresh = tokenType === 'refresh';\n\n const idleLifespan = isRefresh ? config.idleRefreshTokenLifespan : config.idleSessionLifespan;\n\n const maxLifespan = isRefresh ? config.maxRefreshTokenLifespan : config.maxSessionLifespan;\n\n const now = Date.now();\n const expiresAt = new Date(now + idleLifespan * 1000);\n const absoluteExpiresAt = new Date(now + maxLifespan * 1000);\n\n // Create the root record first so createdAt can be used for signing.\n const record = await this.provider.create({\n userId,\n sessionId,\n ...(deviceId && { deviceId }),\n origin,\n childId: null,\n type: tokenType,\n status: 'active',\n expiresAt,\n absoluteExpiresAt,\n });\n\n const issuedAtSeconds = Math.floor(new Date(record.createdAt ?? new Date()).getTime() / 1000);\n const expiresAtSeconds = Math.floor(new Date(record.expiresAt).getTime() / 1000);\n\n const payload: RefreshTokenPayload = {\n userId,\n sessionId,\n type: 'refresh',\n iat: issuedAtSeconds,\n exp: expiresAtSeconds,\n };\n\n const token = jwt.sign(payload, config.jwtSecret, {\n algorithm: DEFAULT_ALGORITHM,\n noTimestamp: true,\n });\n\n return {\n token,\n sessionId,\n absoluteExpiresAt: absoluteExpiresAt.toISOString(),\n };\n }\n\n validateAccessToken(\n token: string,\n origin: string\n ): { isValid: true; payload: AccessTokenPayload } | { isValid: false; payload: null } {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n try {\n const config = this.getConfigForOrigin(origin);\n const payload = jwt.verify(token, config.jwtSecret, {\n algorithms: [DEFAULT_ALGORITHM],\n }) as TokenPayload;\n\n // Ensure this is an access token\n if (!payload || payload.type !== 'access') {\n return { isValid: false, payload: null };\n }\n\n return { isValid: true, payload };\n } catch (err) {\n return { isValid: false, payload: null };\n }\n }\n\n async validateRefreshToken(token: string, origin: string): Promise<ValidateRefreshTokenResult> {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n try {\n const config = this.getConfigForOrigin(origin);\n const verifyOptions: VerifyOptions = {\n algorithms: [DEFAULT_ALGORITHM],\n };\n\n const payload = jwt.verify(token, config.jwtSecret, verifyOptions) as RefreshTokenPayload;\n\n if (payload.type !== 'refresh') {\n return { isValid: false };\n }\n\n const session = await this.provider.findBySessionId(payload.sessionId);\n if (!session) {\n return { isValid: false };\n }\n\n const now = new Date();\n if (new Date(session.expiresAt) <= now) {\n return { isValid: false };\n }\n\n // Absolute family expiry check\n if (session.absoluteExpiresAt && new Date(session.absoluteExpiresAt) <= now) {\n return { isValid: false };\n }\n\n // Only 'active' sessions are eligible to create access tokens.\n if (session.status !== 'active') {\n return { isValid: false };\n }\n\n if (session.userId !== payload.userId) {\n return { isValid: false };\n }\n\n return {\n isValid: true,\n userId: payload.userId,\n sessionId: payload.sessionId,\n };\n } catch (error: any) {\n if (error instanceof jwt.JsonWebTokenError) {\n return { isValid: false };\n }\n\n throw error;\n }\n }\n\n async invalidateRefreshToken(origin: string, userId: string, deviceId?: string): Promise<void> {\n await this.provider.deleteBy({ userId, origin, deviceId });\n }\n\n async generateAccessToken(\n refreshToken: string,\n origin: string\n ): Promise<{ token: string } | { error: string }> {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n const validation = await this.validateRefreshToken(refreshToken, origin);\n\n if (!validation.isValid) {\n return { error: 'invalid_refresh_token' };\n }\n\n const payload: Omit<AccessTokenPayload, 'iat' | 'exp'> = {\n userId: String(validation.userId!),\n sessionId: validation.sessionId!,\n type: 'access',\n };\n\n const config = this.getConfigForOrigin(origin);\n const token = jwt.sign(payload, config.jwtSecret, {\n algorithm: DEFAULT_ALGORITHM,\n expiresIn: config.accessTokenLifespan,\n });\n\n return { token };\n }\n\n async rotateRefreshToken(\n refreshToken: string,\n origin: string\n ): Promise<\n | {\n token: string;\n sessionId: string;\n absoluteExpiresAt: string;\n type: 'refresh' | 'session';\n }\n | { error: string }\n > {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n try {\n const config = this.getConfigForOrigin(origin);\n const payload = jwt.verify(refreshToken, config.jwtSecret, {\n algorithms: [DEFAULT_ALGORITHM],\n }) as RefreshTokenPayload;\n\n if (!payload || payload.type !== 'refresh') {\n return { error: 'invalid_refresh_token' };\n }\n\n const current = await this.provider.findBySessionId(payload.sessionId);\n if (!current) {\n return { error: 'invalid_refresh_token' };\n }\n\n // If parent already has a child, return the same child token\n if (current.childId) {\n const child = await this.provider.findBySessionId(current.childId);\n\n if (child) {\n const childIat = Math.floor(new Date(child.createdAt ?? new Date()).getTime() / 1000);\n const childExp = Math.floor(new Date(child.expiresAt).getTime() / 1000);\n\n const childPayload: RefreshTokenPayload = {\n userId: child.userId,\n sessionId: child.sessionId,\n type: 'refresh',\n iat: childIat,\n exp: childExp,\n };\n\n const childToken = jwt.sign(childPayload, config.jwtSecret, {\n algorithm: DEFAULT_ALGORITHM,\n noTimestamp: true,\n });\n\n let absoluteExpiresAt;\n if (child.absoluteExpiresAt) {\n absoluteExpiresAt =\n typeof child.absoluteExpiresAt === 'string'\n ? child.absoluteExpiresAt\n : child.absoluteExpiresAt.toISOString();\n } else {\n absoluteExpiresAt = new Date(0).toISOString();\n }\n\n return {\n token: childToken,\n sessionId: child.sessionId,\n absoluteExpiresAt,\n type: child.type ?? 'refresh',\n };\n }\n }\n\n const now = Date.now();\n const tokenType = current.type ?? 'refresh';\n const idleLifespan =\n tokenType === 'refresh' ? config.idleRefreshTokenLifespan : config.idleSessionLifespan;\n\n // Enforce idle window since creation of the current token\n if (current.createdAt && now - new Date(current.createdAt).getTime() > idleLifespan * 1000) {\n return { error: 'idle_window_elapsed' };\n }\n\n // Enforce max family window using absoluteExpiresAt\n const absolute = current.absoluteExpiresAt\n ? new Date(current.absoluteExpiresAt).getTime()\n : now;\n if (absolute <= now) {\n return { error: 'max_window_elapsed' };\n }\n\n // Create child token\n const childSessionId = this.generateSessionId();\n const childExpiresAt = new Date(now + idleLifespan * 1000);\n\n const childRecord = await this.provider.create({\n userId: current.userId,\n sessionId: childSessionId,\n ...(current.deviceId && { deviceId: current.deviceId }),\n origin: current.origin,\n childId: null,\n type: tokenType,\n status: 'active',\n expiresAt: childExpiresAt,\n absoluteExpiresAt: current.absoluteExpiresAt ?? new Date(absolute),\n });\n\n const childIat = Math.floor(new Date(childRecord.createdAt ?? new Date()).getTime() / 1000);\n const childExp = Math.floor(new Date(childRecord.expiresAt).getTime() / 1000);\n const payloadOut: RefreshTokenPayload = {\n userId: current.userId,\n sessionId: childSessionId,\n type: 'refresh',\n iat: childIat,\n exp: childExp,\n };\n const childToken = jwt.sign(payloadOut, config.jwtSecret, {\n algorithm: DEFAULT_ALGORITHM,\n noTimestamp: true,\n });\n\n await this.provider.updateBySessionId(current.sessionId, {\n status: 'rotated',\n childId: childSessionId,\n });\n\n let absoluteExpiresAt;\n if (childRecord.absoluteExpiresAt) {\n absoluteExpiresAt =\n typeof childRecord.absoluteExpiresAt === 'string'\n ? childRecord.absoluteExpiresAt\n : childRecord.absoluteExpiresAt.toISOString();\n } else {\n absoluteExpiresAt = new Date(absolute).toISOString();\n }\n\n return {\n token: childToken,\n sessionId: childSessionId,\n absoluteExpiresAt,\n type: tokenType,\n };\n } catch {\n return { error: 'invalid_refresh_token' };\n }\n }\n\n /**\n * Returns true when a session exists and is not expired.\n * If the session exists but is expired, it will be deleted as part of this check.\n */\n async isSessionActive(sessionId: string, origin: string): Promise<boolean> {\n const session = await this.provider.findBySessionId(sessionId);\n if (!session) {\n return false;\n }\n\n if (session.origin !== origin) {\n return false;\n }\n\n if (new Date(session.expiresAt) <= new Date()) {\n // Clean up expired session eagerly\n await this.provider.deleteBySessionId(sessionId);\n\n return false;\n }\n\n return true;\n }\n}\n\nconst createDatabaseProvider = (db: Database, contentType: string): SessionProvider => {\n return new DatabaseSessionProvider(db, contentType);\n};\n\nconst createSessionManager = ({\n db,\n}: {\n db: Database;\n}): SessionManager & ((origin: string) => OriginSessionManager) => {\n const provider = createDatabaseProvider(db, 'admin::session');\n const sessionManager = new SessionManager(provider);\n\n // Add callable functionality\n const fluentApi = (origin: string): OriginSessionManager => {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n return new OriginSessionManager(sessionManager, origin);\n };\n\n // Attach only the public SessionManagerService API to the callable\n const api = fluentApi as unknown as any;\n api.generateSessionId = sessionManager.generateSessionId.bind(sessionManager);\n api.defineOrigin = sessionManager.defineOrigin.bind(sessionManager);\n api.hasOrigin = sessionManager.hasOrigin.bind(sessionManager);\n // Note: isSessionActive is origin-scoped and exposed on OriginSessionManager only\n\n // Forward the cleanupThreshold getter (used in tests)\n Object.defineProperty(api, 'cleanupThreshold', {\n get() {\n return sessionManager.cleanupThreshold;\n },\n enumerable: true,\n });\n\n return api as SessionManager & ((origin: string) => OriginSessionManager);\n};\n\nexport { createSessionManager, createDatabaseProvider };\n"],"names":["DatabaseSessionProvider","create","session","result","db","query","contentType","data","findBySessionId","sessionId","findOne","where","updateBySessionId","update","deleteBySessionId","delete","deleteExpired","deleteMany","absoluteExpiresAt","$lt","Date","deleteBy","criteria","userId","origin","deviceId","constructor","OriginSessionManager","generateRefreshToken","options","sessionManager","generateAccessToken","refreshToken","rotateRefreshToken","validateAccessToken","token","validateRefreshToken","invalidateRefreshToken","isSessionActive","SessionManager","defineOrigin","config","originConfigs","set","hasOrigin","has","getConfigForOrigin","originConfig","get","Error","generateSessionId","crypto","randomBytes","toString","maybeCleanupExpired","cleanupInvocationCounter","cleanupEveryCalls","provider","cleanupThreshold","tokenType","type","isRefresh","idleLifespan","idleRefreshTokenLifespan","idleSessionLifespan","maxLifespan","maxRefreshTokenLifespan","maxSessionLifespan","now","expiresAt","record","childId","status","issuedAtSeconds","Math","floor","createdAt","getTime","expiresAtSeconds","payload","iat","exp","jwt","sign","jwtSecret","algorithm","DEFAULT_ALGORITHM","noTimestamp","toISOString","verify","algorithms","isValid","err","verifyOptions","error","JsonWebTokenError","validation","String","expiresIn","accessTokenLifespan","current","child","childIat","childExp","childPayload","childToken","absolute","childSessionId","childExpiresAt","childRecord","payloadOut","Map","createDatabaseProvider","createSessionManager","fluentApi","api","bind","Object","defineProperty","enumerable"],"mappings":"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"}
1
+ {"version":3,"file":"session-manager.js","sources":["../../src/services/session-manager.ts"],"sourcesContent":["import crypto from 'crypto';\nimport jwt from 'jsonwebtoken';\nimport type { VerifyOptions, Algorithm } from 'jsonwebtoken';\nimport type { Database } from '@strapi/database';\nimport { DEFAULT_ALGORITHM } from '../constants';\n\nexport interface SessionProvider {\n create(session: SessionData): Promise<SessionData>;\n findBySessionId(sessionId: string): Promise<SessionData | null>;\n updateBySessionId(sessionId: string, data: Partial<SessionData>): Promise<void>;\n deleteBySessionId(sessionId: string): Promise<void>;\n deleteExpired(): Promise<void>;\n deleteBy(criteria: { userId?: string; origin?: string; deviceId?: string }): Promise<void>;\n}\n\nexport interface SessionData {\n id?: string;\n userId: string; // User ID stored as string (key-value store)\n sessionId: string;\n deviceId?: string; // Optional for origins that don't need device tracking\n origin: string;\n childId?: string | null;\n\n type?: 'refresh' | 'session';\n status?: 'active' | 'rotated' | 'revoked';\n expiresAt: Date;\n absoluteExpiresAt?: Date | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nexport interface RefreshTokenPayload {\n userId: string;\n sessionId: string;\n type: 'refresh';\n exp: number;\n iat: number;\n}\n\nexport interface AccessTokenPayload {\n userId: string;\n sessionId: string;\n type: 'access';\n exp: number;\n iat: number;\n}\n\nexport type TokenPayload = RefreshTokenPayload | AccessTokenPayload;\n\nexport interface ValidateRefreshTokenResult {\n isValid: boolean;\n userId?: string;\n sessionId?: string;\n error?:\n | 'invalid_token'\n | 'token_expired'\n | 'session_not_found'\n | 'session_expired'\n | 'wrong_token_type';\n}\n\nclass DatabaseSessionProvider implements SessionProvider {\n private db: Database;\n\n private contentType: string;\n\n constructor(db: Database, contentType: string) {\n this.db = db;\n this.contentType = contentType;\n }\n\n async create(session: SessionData): Promise<SessionData> {\n const result = await this.db.query(this.contentType).create({\n data: session,\n });\n return result as SessionData;\n }\n\n async findBySessionId(sessionId: string): Promise<SessionData | null> {\n const result = await this.db.query(this.contentType).findOne({\n where: { sessionId },\n });\n return result as SessionData | null;\n }\n\n async updateBySessionId(sessionId: string, data: Partial<SessionData>): Promise<void> {\n await this.db.query(this.contentType).update({ where: { sessionId }, data });\n }\n\n async deleteBySessionId(sessionId: string): Promise<void> {\n await this.db.query(this.contentType).delete({\n where: { sessionId },\n });\n }\n\n async deleteExpired(): Promise<void> {\n await this.db.query(this.contentType).deleteMany({\n where: { absoluteExpiresAt: { $lt: new Date() } },\n });\n }\n\n async deleteBy(criteria: { userId?: string; origin?: string; deviceId?: string }): Promise<void> {\n await this.db.query(this.contentType).deleteMany({\n where: {\n ...(criteria.userId ? { userId: criteria.userId } : {}),\n ...(criteria.origin ? { origin: criteria.origin } : {}),\n ...(criteria.deviceId ? { deviceId: criteria.deviceId } : {}),\n },\n });\n }\n}\n\nexport interface SessionManagerConfig {\n jwtSecret?: string;\n accessTokenLifespan: number;\n maxRefreshTokenLifespan: number;\n idleRefreshTokenLifespan: number;\n maxSessionLifespan: number;\n idleSessionLifespan: number;\n algorithm?: Algorithm;\n jwtOptions?: Record<string, unknown>;\n}\n\nclass OriginSessionManager {\n constructor(\n private sessionManager: SessionManager,\n private origin: string\n ) {}\n\n async generateRefreshToken(\n userId: string,\n deviceId: string | undefined,\n options?: { type?: 'refresh' | 'session' }\n ): Promise<{ token: string; sessionId: string; absoluteExpiresAt: string }> {\n return this.sessionManager.generateRefreshToken(userId, deviceId, this.origin, options);\n }\n\n async generateAccessToken(refreshToken: string): Promise<{ token: string } | { error: string }> {\n return this.sessionManager.generateAccessToken(refreshToken, this.origin);\n }\n\n async rotateRefreshToken(refreshToken: string): Promise<\n | {\n token: string;\n sessionId: string;\n absoluteExpiresAt: string;\n type: 'refresh' | 'session';\n }\n | { error: string }\n > {\n return this.sessionManager.rotateRefreshToken(refreshToken, this.origin);\n }\n\n validateAccessToken(\n token: string\n ): { isValid: true; payload: AccessTokenPayload } | { isValid: false; payload: null } {\n return this.sessionManager.validateAccessToken(token, this.origin);\n }\n\n async validateRefreshToken(token: string): Promise<ValidateRefreshTokenResult> {\n return this.sessionManager.validateRefreshToken(token, this.origin);\n }\n\n async invalidateRefreshToken(userId: string, deviceId?: string): Promise<void> {\n return this.sessionManager.invalidateRefreshToken(this.origin, userId, deviceId);\n }\n\n /**\n * Returns true when a session exists and is not expired for this origin.\n * If the session exists but is expired, it will be deleted as part of this check.\n */\n async isSessionActive(sessionId: string): Promise<boolean> {\n return this.sessionManager.isSessionActive(sessionId, this.origin);\n }\n}\n\nclass SessionManager {\n private provider: SessionProvider;\n\n // Store origin-specific configurations\n private originConfigs: Map<string, SessionManagerConfig> = new Map();\n\n // Run expired cleanup only every N calls to avoid extra queries\n private cleanupInvocationCounter: number = 0;\n\n private readonly cleanupEveryCalls: number = 50;\n\n constructor(provider: SessionProvider) {\n this.provider = provider;\n }\n\n /**\n * Define configuration for a specific origin\n */\n defineOrigin(origin: string, config: SessionManagerConfig): void {\n this.originConfigs.set(origin, config);\n }\n\n /**\n * Check if an origin is defined\n */\n hasOrigin(origin: string): boolean {\n return this.originConfigs.has(origin);\n }\n\n /**\n * Get configuration for a specific origin, throw error if not defined\n */\n private getConfigForOrigin(origin: string): SessionManagerConfig {\n const originConfig = this.originConfigs.get(origin);\n if (originConfig) {\n return originConfig;\n }\n throw new Error(\n `SessionManager: Origin '${origin}' is not defined. Please define it using defineOrigin('${origin}', config).`\n );\n }\n\n /**\n * Get the appropriate JWT key based on the algorithm\n */\n private getJwtKey(\n config: SessionManagerConfig,\n algorithm: Algorithm,\n operation: 'sign' | 'verify'\n ): string {\n const isAsymmetric =\n algorithm.startsWith('RS') || algorithm.startsWith('ES') || algorithm.startsWith('PS');\n\n if (isAsymmetric) {\n // For asymmetric algorithms, check if user has provided proper key configuration\n if (operation === 'sign') {\n const privateKey = config.jwtOptions?.privateKey as string;\n if (privateKey) {\n return privateKey;\n }\n throw new Error(\n `SessionManager: Private key is required for asymmetric algorithm ${algorithm}. Please configure admin.auth.options.privateKey.`\n );\n } else {\n const publicKey = config.jwtOptions?.publicKey as string;\n if (publicKey) {\n return publicKey;\n }\n throw new Error(\n `SessionManager: Public key is required for asymmetric algorithm ${algorithm}. Please configure admin.auth.options.publicKey.`\n );\n }\n } else {\n if (!config.jwtSecret) {\n throw new Error(\n `SessionManager: Secret key is required for symmetric algorithm ${algorithm}`\n );\n }\n return config.jwtSecret;\n }\n }\n\n generateSessionId(): string {\n return crypto.randomBytes(16).toString('hex');\n }\n\n private async maybeCleanupExpired(): Promise<void> {\n this.cleanupInvocationCounter += 1;\n if (this.cleanupInvocationCounter >= this.cleanupEveryCalls) {\n this.cleanupInvocationCounter = 0;\n\n await this.provider.deleteExpired();\n }\n }\n\n /**\n * Get the cleanup every calls threshold\n */\n get cleanupThreshold(): number {\n return this.cleanupEveryCalls;\n }\n\n async generateRefreshToken(\n userId: string,\n deviceId: string | undefined,\n origin: string,\n options?: { type?: 'refresh' | 'session' }\n ): Promise<{ token: string; sessionId: string; absoluteExpiresAt: string }> {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n await this.maybeCleanupExpired();\n\n const config = this.getConfigForOrigin(origin);\n const algorithm = config.algorithm || DEFAULT_ALGORITHM;\n const jwtKey = this.getJwtKey(config, algorithm, 'sign');\n const sessionId = this.generateSessionId();\n const tokenType = options?.type ?? 'refresh';\n const isRefresh = tokenType === 'refresh';\n\n const idleLifespan = isRefresh ? config.idleRefreshTokenLifespan : config.idleSessionLifespan;\n\n const maxLifespan = isRefresh ? config.maxRefreshTokenLifespan : config.maxSessionLifespan;\n\n const now = Date.now();\n const expiresAt = new Date(now + idleLifespan * 1000);\n const absoluteExpiresAt = new Date(now + maxLifespan * 1000);\n\n // Create the root record first so createdAt can be used for signing.\n const record = await this.provider.create({\n userId,\n sessionId,\n ...(deviceId && { deviceId }),\n origin,\n childId: null,\n type: tokenType,\n status: 'active',\n expiresAt,\n absoluteExpiresAt,\n });\n\n const issuedAtSeconds = Math.floor(new Date(record.createdAt ?? new Date()).getTime() / 1000);\n const expiresAtSeconds = Math.floor(new Date(record.expiresAt).getTime() / 1000);\n\n const payload: RefreshTokenPayload = {\n userId,\n sessionId,\n type: 'refresh',\n iat: issuedAtSeconds,\n exp: expiresAtSeconds,\n };\n\n // Filter out conflicting options that are already handled by the payload or used for key selection\n const jwtOptions = config.jwtOptions || {};\n const { expiresIn, privateKey, publicKey, ...jwtSignOptions } = jwtOptions;\n\n const token = jwt.sign(payload, jwtKey, {\n algorithm,\n noTimestamp: true,\n ...jwtSignOptions,\n });\n\n return {\n token,\n sessionId,\n absoluteExpiresAt: absoluteExpiresAt.toISOString(),\n };\n }\n\n validateAccessToken(\n token: string,\n origin: string\n ): { isValid: true; payload: AccessTokenPayload } | { isValid: false; payload: null } {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n try {\n const config = this.getConfigForOrigin(origin);\n const algorithm = config.algorithm || DEFAULT_ALGORITHM;\n const jwtKey = this.getJwtKey(config, algorithm, 'verify');\n const payload = jwt.verify(token, jwtKey, {\n algorithms: [algorithm],\n ...config.jwtOptions,\n }) as TokenPayload;\n\n // Ensure this is an access token\n if (!payload || payload.type !== 'access') {\n return { isValid: false, payload: null };\n }\n\n return { isValid: true, payload };\n } catch (err) {\n return { isValid: false, payload: null };\n }\n }\n\n async validateRefreshToken(token: string, origin: string): Promise<ValidateRefreshTokenResult> {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n try {\n const config = this.getConfigForOrigin(origin);\n const algorithm = config.algorithm || DEFAULT_ALGORITHM;\n const jwtKey = this.getJwtKey(config, algorithm, 'verify');\n const verifyOptions: VerifyOptions = {\n algorithms: [algorithm],\n ...config.jwtOptions,\n };\n\n const payload = jwt.verify(token, jwtKey, verifyOptions) as RefreshTokenPayload;\n\n if (payload.type !== 'refresh') {\n return { isValid: false };\n }\n\n const session = await this.provider.findBySessionId(payload.sessionId);\n if (!session) {\n return { isValid: false };\n }\n\n const now = new Date();\n if (new Date(session.expiresAt) <= now) {\n return { isValid: false };\n }\n\n // Absolute family expiry check\n if (session.absoluteExpiresAt && new Date(session.absoluteExpiresAt) <= now) {\n return { isValid: false };\n }\n\n // Only 'active' sessions are eligible to create access tokens.\n if (session.status !== 'active') {\n return { isValid: false };\n }\n\n if (session.userId !== payload.userId) {\n return { isValid: false };\n }\n\n return {\n isValid: true,\n userId: payload.userId,\n sessionId: payload.sessionId,\n };\n } catch (error: any) {\n if (error instanceof jwt.JsonWebTokenError) {\n return { isValid: false };\n }\n\n throw error;\n }\n }\n\n async invalidateRefreshToken(origin: string, userId: string, deviceId?: string): Promise<void> {\n await this.provider.deleteBy({ userId, origin, deviceId });\n }\n\n async generateAccessToken(\n refreshToken: string,\n origin: string\n ): Promise<{ token: string } | { error: string }> {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n const validation = await this.validateRefreshToken(refreshToken, origin);\n\n if (!validation.isValid) {\n return { error: 'invalid_refresh_token' };\n }\n\n const payload: Omit<AccessTokenPayload, 'iat' | 'exp'> = {\n userId: String(validation.userId!),\n sessionId: validation.sessionId!,\n type: 'access',\n };\n\n const config = this.getConfigForOrigin(origin);\n const algorithm = config.algorithm || DEFAULT_ALGORITHM;\n const jwtKey = this.getJwtKey(config, algorithm, 'sign');\n // Filter out conflicting options that are already handled by the payload or used for key selection\n const jwtOptions = config.jwtOptions || {};\n const { expiresIn, privateKey, publicKey, ...jwtSignOptions } = jwtOptions;\n\n const token = jwt.sign(payload, jwtKey, {\n algorithm,\n expiresIn: config.accessTokenLifespan,\n ...jwtSignOptions,\n });\n\n return { token };\n }\n\n async rotateRefreshToken(\n refreshToken: string,\n origin: string\n ): Promise<\n | {\n token: string;\n sessionId: string;\n absoluteExpiresAt: string;\n type: 'refresh' | 'session';\n }\n | { error: string }\n > {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n\n try {\n const config = this.getConfigForOrigin(origin);\n const algorithm = config.algorithm || DEFAULT_ALGORITHM;\n const jwtKey = this.getJwtKey(config, algorithm, 'verify');\n const payload = jwt.verify(refreshToken, jwtKey, {\n algorithms: [algorithm],\n ...config.jwtOptions,\n }) as RefreshTokenPayload;\n\n if (!payload || payload.type !== 'refresh') {\n return { error: 'invalid_refresh_token' };\n }\n\n const current = await this.provider.findBySessionId(payload.sessionId);\n if (!current) {\n return { error: 'invalid_refresh_token' };\n }\n\n // If parent already has a child, return the same child token\n if (current.childId) {\n const child = await this.provider.findBySessionId(current.childId);\n\n if (child) {\n const childIat = Math.floor(new Date(child.createdAt ?? new Date()).getTime() / 1000);\n const childExp = Math.floor(new Date(child.expiresAt).getTime() / 1000);\n\n const childPayload: RefreshTokenPayload = {\n userId: child.userId,\n sessionId: child.sessionId,\n type: 'refresh',\n iat: childIat,\n exp: childExp,\n };\n\n // Filter out conflicting options that are already handled by the payload\n const { expiresIn, ...jwtSignOptions } = config.jwtOptions || {};\n\n const childToken = jwt.sign(childPayload, jwtKey, {\n algorithm,\n noTimestamp: true,\n ...jwtSignOptions,\n });\n\n let absoluteExpiresAt;\n if (child.absoluteExpiresAt) {\n absoluteExpiresAt =\n typeof child.absoluteExpiresAt === 'string'\n ? child.absoluteExpiresAt\n : child.absoluteExpiresAt.toISOString();\n } else {\n absoluteExpiresAt = new Date(0).toISOString();\n }\n\n return {\n token: childToken,\n sessionId: child.sessionId,\n absoluteExpiresAt,\n type: child.type ?? 'refresh',\n };\n }\n }\n\n const now = Date.now();\n const tokenType = current.type ?? 'refresh';\n const idleLifespan =\n tokenType === 'refresh' ? config.idleRefreshTokenLifespan : config.idleSessionLifespan;\n\n // Enforce idle window since creation of the current token\n if (current.createdAt && now - new Date(current.createdAt).getTime() > idleLifespan * 1000) {\n return { error: 'idle_window_elapsed' };\n }\n\n // Enforce max family window using absoluteExpiresAt\n const absolute = current.absoluteExpiresAt\n ? new Date(current.absoluteExpiresAt).getTime()\n : now;\n if (absolute <= now) {\n return { error: 'max_window_elapsed' };\n }\n\n // Create child token\n const childSessionId = this.generateSessionId();\n const childExpiresAt = new Date(now + idleLifespan * 1000);\n\n const childRecord = await this.provider.create({\n userId: current.userId,\n sessionId: childSessionId,\n ...(current.deviceId && { deviceId: current.deviceId }),\n origin: current.origin,\n childId: null,\n type: tokenType,\n status: 'active',\n expiresAt: childExpiresAt,\n absoluteExpiresAt: current.absoluteExpiresAt ?? new Date(absolute),\n });\n\n const childIat = Math.floor(new Date(childRecord.createdAt ?? new Date()).getTime() / 1000);\n const childExp = Math.floor(new Date(childRecord.expiresAt).getTime() / 1000);\n const payloadOut: RefreshTokenPayload = {\n userId: current.userId,\n sessionId: childSessionId,\n type: 'refresh',\n iat: childIat,\n exp: childExp,\n };\n // Filter out conflicting options that are already handled by the payload\n const { expiresIn, ...jwtSignOptions } = config.jwtOptions || {};\n\n const childToken = jwt.sign(payloadOut, jwtKey, {\n algorithm,\n noTimestamp: true,\n ...jwtSignOptions,\n });\n\n await this.provider.updateBySessionId(current.sessionId, {\n status: 'rotated',\n childId: childSessionId,\n });\n\n let absoluteExpiresAt;\n if (childRecord.absoluteExpiresAt) {\n absoluteExpiresAt =\n typeof childRecord.absoluteExpiresAt === 'string'\n ? childRecord.absoluteExpiresAt\n : childRecord.absoluteExpiresAt.toISOString();\n } else {\n absoluteExpiresAt = new Date(absolute).toISOString();\n }\n\n return {\n token: childToken,\n sessionId: childSessionId,\n absoluteExpiresAt,\n type: tokenType,\n };\n } catch {\n return { error: 'invalid_refresh_token' };\n }\n }\n\n /**\n * Returns true when a session exists and is not expired.\n * If the session exists but is expired, it will be deleted as part of this check.\n */\n async isSessionActive(sessionId: string, origin: string): Promise<boolean> {\n const session = await this.provider.findBySessionId(sessionId);\n if (!session) {\n return false;\n }\n\n if (session.origin !== origin) {\n return false;\n }\n\n if (new Date(session.expiresAt) <= new Date()) {\n // Clean up expired session eagerly\n await this.provider.deleteBySessionId(sessionId);\n\n return false;\n }\n\n return true;\n }\n}\n\nconst createDatabaseProvider = (db: Database, contentType: string): SessionProvider => {\n return new DatabaseSessionProvider(db, contentType);\n};\n\nconst createSessionManager = ({\n db,\n}: {\n db: Database;\n}): SessionManager & ((origin: string) => OriginSessionManager) => {\n const provider = createDatabaseProvider(db, 'admin::session');\n const sessionManager = new SessionManager(provider);\n\n // Add callable functionality\n const fluentApi = (origin: string): OriginSessionManager => {\n if (!origin || typeof origin !== 'string') {\n throw new Error(\n 'SessionManager: Origin parameter is required and must be a non-empty string'\n );\n }\n return new OriginSessionManager(sessionManager, origin);\n };\n\n // Attach only the public SessionManagerService API to the callable\n const api = fluentApi as unknown as any;\n api.generateSessionId = sessionManager.generateSessionId.bind(sessionManager);\n api.defineOrigin = sessionManager.defineOrigin.bind(sessionManager);\n api.hasOrigin = sessionManager.hasOrigin.bind(sessionManager);\n // Note: isSessionActive is origin-scoped and exposed on OriginSessionManager only\n\n // Forward the cleanupThreshold getter (used in tests)\n Object.defineProperty(api, 'cleanupThreshold', {\n get() {\n return sessionManager.cleanupThreshold;\n },\n enumerable: true,\n });\n\n return api as SessionManager & ((origin: string) => OriginSessionManager);\n};\n\nexport { createSessionManager, createDatabaseProvider };\n"],"names":["DatabaseSessionProvider","create","session","result","db","query","contentType","data","findBySessionId","sessionId","findOne","where","updateBySessionId","update","deleteBySessionId","delete","deleteExpired","deleteMany","absoluteExpiresAt","$lt","Date","deleteBy","criteria","userId","origin","deviceId","constructor","OriginSessionManager","generateRefreshToken","options","sessionManager","generateAccessToken","refreshToken","rotateRefreshToken","validateAccessToken","token","validateRefreshToken","invalidateRefreshToken","isSessionActive","SessionManager","defineOrigin","config","originConfigs","set","hasOrigin","has","getConfigForOrigin","originConfig","get","Error","algorithm","operation","isAsymmetric","startsWith","privateKey","jwtOptions","publicKey","jwtSecret","generateSessionId","crypto","randomBytes","toString","maybeCleanupExpired","cleanupInvocationCounter","cleanupEveryCalls","provider","cleanupThreshold","DEFAULT_ALGORITHM","jwtKey","getJwtKey","tokenType","type","isRefresh","idleLifespan","idleRefreshTokenLifespan","idleSessionLifespan","maxLifespan","maxRefreshTokenLifespan","maxSessionLifespan","now","expiresAt","record","childId","status","issuedAtSeconds","Math","floor","createdAt","getTime","expiresAtSeconds","payload","iat","exp","expiresIn","jwtSignOptions","jwt","sign","noTimestamp","toISOString","verify","algorithms","isValid","err","verifyOptions","error","JsonWebTokenError","validation","String","accessTokenLifespan","current","child","childIat","childExp","childPayload","childToken","absolute","childSessionId","childExpiresAt","childRecord","payloadOut","Map","createDatabaseProvider","createSessionManager","fluentApi","api","bind","Object","defineProperty","enumerable"],"mappings":";;;;;;AA6DA,MAAMA,uBAAAA,CAAAA;IAUJ,MAAMC,MAAAA,CAAOC,OAAoB,EAAwB;AACvD,QAAA,MAAMC,MAAS,GAAA,MAAM,IAAI,CAACC,EAAE,CAACC,KAAK,CAAC,IAAI,CAACC,WAAW,CAAA,CAAEL,MAAM,CAAC;YAC1DM,IAAML,EAAAA;AACR,SAAA,CAAA;QACA,OAAOC,MAAAA;AACT;IAEA,MAAMK,eAAAA,CAAgBC,SAAiB,EAA+B;AACpE,QAAA,MAAMN,MAAS,GAAA,MAAM,IAAI,CAACC,EAAE,CAACC,KAAK,CAAC,IAAI,CAACC,WAAW,CAAA,CAAEI,OAAO,CAAC;YAC3DC,KAAO,EAAA;AAAEF,gBAAAA;AAAU;AACrB,SAAA,CAAA;QACA,OAAON,MAAAA;AACT;AAEA,IAAA,MAAMS,iBAAkBH,CAAAA,SAAiB,EAAEF,IAA0B,EAAiB;QACpF,MAAM,IAAI,CAACH,EAAE,CAACC,KAAK,CAAC,IAAI,CAACC,WAAW,CAAEO,CAAAA,MAAM,CAAC;YAAEF,KAAO,EAAA;AAAEF,gBAAAA;AAAU,aAAA;AAAGF,YAAAA;AAAK,SAAA,CAAA;AAC5E;IAEA,MAAMO,iBAAAA,CAAkBL,SAAiB,EAAiB;QACxD,MAAM,IAAI,CAACL,EAAE,CAACC,KAAK,CAAC,IAAI,CAACC,WAAW,CAAES,CAAAA,MAAM,CAAC;YAC3CJ,KAAO,EAAA;AAAEF,gBAAAA;AAAU;AACrB,SAAA,CAAA;AACF;AAEA,IAAA,MAAMO,aAA+B,GAAA;QACnC,MAAM,IAAI,CAACZ,EAAE,CAACC,KAAK,CAAC,IAAI,CAACC,WAAW,CAAEW,CAAAA,UAAU,CAAC;YAC/CN,KAAO,EAAA;gBAAEO,iBAAmB,EAAA;AAAEC,oBAAAA,GAAAA,EAAK,IAAIC,IAAAA;AAAO;AAAE;AAClD,SAAA,CAAA;AACF;IAEA,MAAMC,QAAAA,CAASC,QAAiE,EAAiB;QAC/F,MAAM,IAAI,CAAClB,EAAE,CAACC,KAAK,CAAC,IAAI,CAACC,WAAW,CAAEW,CAAAA,UAAU,CAAC;YAC/CN,KAAO,EAAA;gBACL,GAAIW,QAAAA,CAASC,MAAM,GAAG;AAAEA,oBAAAA,MAAAA,EAAQD,SAASC;AAAO,iBAAA,GAAI,EAAE;gBACtD,GAAID,QAAAA,CAASE,MAAM,GAAG;AAAEA,oBAAAA,MAAAA,EAAQF,SAASE;AAAO,iBAAA,GAAI,EAAE;gBACtD,GAAIF,QAAAA,CAASG,QAAQ,GAAG;AAAEA,oBAAAA,QAAAA,EAAUH,SAASG;AAAS,iBAAA,GAAI;AAC5D;AACF,SAAA,CAAA;AACF;IA3CAC,WAAYtB,CAAAA,EAAY,EAAEE,WAAmB,CAAE;QAC7C,IAAI,CAACF,EAAE,GAAGA,EAAAA;QACV,IAAI,CAACE,WAAW,GAAGA,WAAAA;AACrB;AAyCF;AAaA,MAAMqB,oBAAAA,CAAAA;AAMJ,IAAA,MAAMC,qBACJL,MAAc,EACdE,QAA4B,EAC5BI,OAA0C,EACgC;QAC1E,OAAO,IAAI,CAACC,cAAc,CAACF,oBAAoB,CAACL,MAAAA,EAAQE,QAAU,EAAA,IAAI,CAACD,MAAM,EAAEK,OAAAA,CAAAA;AACjF;IAEA,MAAME,mBAAAA,CAAoBC,YAAoB,EAAkD;QAC9F,OAAO,IAAI,CAACF,cAAc,CAACC,mBAAmB,CAACC,YAAAA,EAAc,IAAI,CAACR,MAAM,CAAA;AAC1E;IAEA,MAAMS,kBAAAA,CAAmBD,YAAoB,EAQ3C;QACA,OAAO,IAAI,CAACF,cAAc,CAACG,kBAAkB,CAACD,YAAAA,EAAc,IAAI,CAACR,MAAM,CAAA;AACzE;AAEAU,IAAAA,mBAAAA,CACEC,KAAa,EACuE;QACpF,OAAO,IAAI,CAACL,cAAc,CAACI,mBAAmB,CAACC,KAAAA,EAAO,IAAI,CAACX,MAAM,CAAA;AACnE;IAEA,MAAMY,oBAAAA,CAAqBD,KAAa,EAAuC;QAC7E,OAAO,IAAI,CAACL,cAAc,CAACM,oBAAoB,CAACD,KAAAA,EAAO,IAAI,CAACX,MAAM,CAAA;AACpE;AAEA,IAAA,MAAMa,sBAAuBd,CAAAA,MAAc,EAAEE,QAAiB,EAAiB;QAC7E,OAAO,IAAI,CAACK,cAAc,CAACO,sBAAsB,CAAC,IAAI,CAACb,MAAM,EAAED,MAAQE,EAAAA,QAAAA,CAAAA;AACzE;AAEA;;;MAIA,MAAMa,eAAgB7B,CAAAA,SAAiB,EAAoB;QACzD,OAAO,IAAI,CAACqB,cAAc,CAACQ,eAAe,CAAC7B,SAAAA,EAAW,IAAI,CAACe,MAAM,CAAA;AACnE;AAjDAE,IAAAA,WAAAA,CACE,cAAsC,EAC9BF,MAAc,CACtB;aAFQM,cAAAA,GAAAA,cAAAA;aACAN,MAAAA,GAAAA,MAAAA;AACP;AA+CL;AAEA,MAAMe,cAAAA,CAAAA;AAeJ;;AAEC,MACDC,YAAahB,CAAAA,MAAc,EAAEiB,MAA4B,EAAQ;AAC/D,QAAA,IAAI,CAACC,aAAa,CAACC,GAAG,CAACnB,MAAQiB,EAAAA,MAAAA,CAAAA;AACjC;AAEA;;MAGAG,SAAAA,CAAUpB,MAAc,EAAW;AACjC,QAAA,OAAO,IAAI,CAACkB,aAAa,CAACG,GAAG,CAACrB,MAAAA,CAAAA;AAChC;AAEA;;MAGQsB,kBAAmBtB,CAAAA,MAAc,EAAwB;AAC/D,QAAA,MAAMuB,eAAe,IAAI,CAACL,aAAa,CAACM,GAAG,CAACxB,MAAAA,CAAAA;AAC5C,QAAA,IAAIuB,YAAc,EAAA;YAChB,OAAOA,YAAAA;AACT;QACA,MAAM,IAAIE,KACR,CAAA,CAAC,wBAAwB,EAAEzB,OAAO,uDAAuD,EAAEA,MAAO,CAAA,WAAW,CAAC,CAAA;AAElH;AAEA;;AAEC,MACD,SACEiB,CAAAA,MAA4B,EAC5BS,SAAoB,EACpBC,SAA4B,EACpB;QACR,MAAMC,YAAAA,GACJF,SAAUG,CAAAA,UAAU,CAAC,IAAA,CAAA,IAASH,SAAUG,CAAAA,UAAU,CAAC,IAAA,CAAA,IAASH,SAAUG,CAAAA,UAAU,CAAC,IAAA,CAAA;AAEnF,QAAA,IAAID,YAAc,EAAA;;AAEhB,YAAA,IAAID,cAAc,MAAQ,EAAA;gBACxB,MAAMG,UAAAA,GAAab,MAAOc,CAAAA,UAAU,EAAED,UAAAA;AACtC,gBAAA,IAAIA,UAAY,EAAA;oBACd,OAAOA,UAAAA;AACT;AACA,gBAAA,MAAM,IAAIL,KACR,CAAA,CAAC,iEAAiE,EAAEC,SAAAA,CAAU,iDAAiD,CAAC,CAAA;aAE7H,MAAA;gBACL,MAAMM,SAAAA,GAAYf,MAAOc,CAAAA,UAAU,EAAEC,SAAAA;AACrC,gBAAA,IAAIA,SAAW,EAAA;oBACb,OAAOA,SAAAA;AACT;AACA,gBAAA,MAAM,IAAIP,KACR,CAAA,CAAC,gEAAgE,EAAEC,SAAAA,CAAU,gDAAgD,CAAC,CAAA;AAElI;SACK,MAAA;YACL,IAAI,CAACT,MAAOgB,CAAAA,SAAS,EAAE;AACrB,gBAAA,MAAM,IAAIR,KACR,CAAA,CAAC,+DAA+D,EAAEC,UAAU,CAAC,CAAA;AAEjF;AACA,YAAA,OAAOT,OAAOgB,SAAS;AACzB;AACF;IAEAC,iBAA4B,GAAA;AAC1B,QAAA,OAAOC,MAAOC,CAAAA,WAAW,CAAC,EAAA,CAAA,CAAIC,QAAQ,CAAC,KAAA,CAAA;AACzC;AAEA,IAAA,MAAcC,mBAAqC,GAAA;QACjD,IAAI,CAACC,wBAAwB,IAAI,CAAA;AACjC,QAAA,IAAI,IAAI,CAACA,wBAAwB,IAAI,IAAI,CAACC,iBAAiB,EAAE;YAC3D,IAAI,CAACD,wBAAwB,GAAG,CAAA;AAEhC,YAAA,MAAM,IAAI,CAACE,QAAQ,CAACjD,aAAa,EAAA;AACnC;AACF;AAEA;;AAEC,MACD,IAAIkD,gBAA2B,GAAA;QAC7B,OAAO,IAAI,CAACF,iBAAiB;AAC/B;IAEA,MAAMpC,oBAAAA,CACJL,MAAc,EACdE,QAA4B,EAC5BD,MAAc,EACdK,OAA0C,EACgC;AAC1E,QAAA,IAAI,CAACL,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAU,EAAA;AACzC,YAAA,MAAM,IAAIyB,KACR,CAAA,6EAAA,CAAA;AAEJ;QAEA,MAAM,IAAI,CAACa,mBAAmB,EAAA;AAE9B,QAAA,MAAMrB,MAAS,GAAA,IAAI,CAACK,kBAAkB,CAACtB,MAAAA,CAAAA;QACvC,MAAM0B,SAAAA,GAAYT,MAAOS,CAAAA,SAAS,IAAIiB,2BAAAA;AACtC,QAAA,MAAMC,SAAS,IAAI,CAACC,SAAS,CAAC5B,QAAQS,SAAW,EAAA,MAAA,CAAA;QACjD,MAAMzC,SAAAA,GAAY,IAAI,CAACiD,iBAAiB,EAAA;QACxC,MAAMY,SAAAA,GAAYzC,SAAS0C,IAAQ,IAAA,SAAA;AACnC,QAAA,MAAMC,YAAYF,SAAc,KAAA,SAAA;AAEhC,QAAA,MAAMG,eAAeD,SAAY/B,GAAAA,MAAAA,CAAOiC,wBAAwB,GAAGjC,OAAOkC,mBAAmB;AAE7F,QAAA,MAAMC,cAAcJ,SAAY/B,GAAAA,MAAAA,CAAOoC,uBAAuB,GAAGpC,OAAOqC,kBAAkB;QAE1F,MAAMC,GAAAA,GAAM3D,KAAK2D,GAAG,EAAA;AACpB,QAAA,MAAMC,SAAY,GAAA,IAAI5D,IAAK2D,CAAAA,GAAAA,GAAMN,YAAe,GAAA,IAAA,CAAA;AAChD,QAAA,MAAMvD,iBAAoB,GAAA,IAAIE,IAAK2D,CAAAA,GAAAA,GAAMH,WAAc,GAAA,IAAA,CAAA;;AAGvD,QAAA,MAAMK,SAAS,MAAM,IAAI,CAAChB,QAAQ,CAAChE,MAAM,CAAC;AACxCsB,YAAAA,MAAAA;AACAd,YAAAA,SAAAA;AACA,YAAA,GAAIgB,QAAY,IAAA;AAAEA,gBAAAA;aAAU;AAC5BD,YAAAA,MAAAA;YACA0D,OAAS,EAAA,IAAA;YACTX,IAAMD,EAAAA,SAAAA;YACNa,MAAQ,EAAA,QAAA;AACRH,YAAAA,SAAAA;AACA9D,YAAAA;AACF,SAAA,CAAA;AAEA,QAAA,MAAMkE,eAAkBC,GAAAA,IAAAA,CAAKC,KAAK,CAAC,IAAIlE,IAAAA,CAAK6D,MAAOM,CAAAA,SAAS,IAAI,IAAInE,IAAQoE,EAAAA,CAAAA,CAAAA,OAAO,EAAK,GAAA,IAAA,CAAA;QACxF,MAAMC,gBAAAA,GAAmBJ,IAAKC,CAAAA,KAAK,CAAC,IAAIlE,KAAK6D,MAAOD,CAAAA,SAAS,CAAEQ,CAAAA,OAAO,EAAK,GAAA,IAAA,CAAA;AAE3E,QAAA,MAAME,OAA+B,GAAA;AACnCnE,YAAAA,MAAAA;AACAd,YAAAA,SAAAA;YACA8D,IAAM,EAAA,SAAA;YACNoB,GAAKP,EAAAA,eAAAA;YACLQ,GAAKH,EAAAA;AACP,SAAA;;AAGA,QAAA,MAAMlC,UAAad,GAAAA,MAAAA,CAAOc,UAAU,IAAI,EAAC;QACzC,MAAM,EAAEsC,SAAS,EAAEvC,UAAU,EAAEE,SAAS,EAAE,GAAGsC,cAAAA,EAAgB,GAAGvC,UAAAA;AAEhE,QAAA,MAAMpB,KAAQ4D,GAAAA,GAAAA,CAAIC,IAAI,CAACN,SAAStB,MAAQ,EAAA;AACtClB,YAAAA,SAAAA;YACA+C,WAAa,EAAA,IAAA;AACb,YAAA,GAAGH;AACL,SAAA,CAAA;QAEA,OAAO;AACL3D,YAAAA,KAAAA;AACA1B,YAAAA,SAAAA;AACAS,YAAAA,iBAAAA,EAAmBA,kBAAkBgF,WAAW;AAClD,SAAA;AACF;IAEAhE,mBACEC,CAAAA,KAAa,EACbX,MAAc,EACsE;AACpF,QAAA,IAAI,CAACA,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAU,EAAA;AACzC,YAAA,MAAM,IAAIyB,KACR,CAAA,6EAAA,CAAA;AAEJ;QAEA,IAAI;AACF,YAAA,MAAMR,MAAS,GAAA,IAAI,CAACK,kBAAkB,CAACtB,MAAAA,CAAAA;YACvC,MAAM0B,SAAAA,GAAYT,MAAOS,CAAAA,SAAS,IAAIiB,2BAAAA;AACtC,YAAA,MAAMC,SAAS,IAAI,CAACC,SAAS,CAAC5B,QAAQS,SAAW,EAAA,QAAA,CAAA;AACjD,YAAA,MAAMwC,OAAUK,GAAAA,GAAAA,CAAII,MAAM,CAAChE,OAAOiC,MAAQ,EAAA;gBACxCgC,UAAY,EAAA;AAAClD,oBAAAA;AAAU,iBAAA;AACvB,gBAAA,GAAGT,OAAOc;AACZ,aAAA,CAAA;;AAGA,YAAA,IAAI,CAACmC,OAAAA,IAAWA,OAAQnB,CAAAA,IAAI,KAAK,QAAU,EAAA;gBACzC,OAAO;oBAAE8B,OAAS,EAAA,KAAA;oBAAOX,OAAS,EAAA;AAAK,iBAAA;AACzC;YAEA,OAAO;gBAAEW,OAAS,EAAA,IAAA;AAAMX,gBAAAA;AAAQ,aAAA;AAClC,SAAA,CAAE,OAAOY,GAAK,EAAA;YACZ,OAAO;gBAAED,OAAS,EAAA,KAAA;gBAAOX,OAAS,EAAA;AAAK,aAAA;AACzC;AACF;AAEA,IAAA,MAAMtD,oBAAqBD,CAAAA,KAAa,EAAEX,MAAc,EAAuC;AAC7F,QAAA,IAAI,CAACA,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAU,EAAA;AACzC,YAAA,MAAM,IAAIyB,KACR,CAAA,6EAAA,CAAA;AAEJ;QAEA,IAAI;AACF,YAAA,MAAMR,MAAS,GAAA,IAAI,CAACK,kBAAkB,CAACtB,MAAAA,CAAAA;YACvC,MAAM0B,SAAAA,GAAYT,MAAOS,CAAAA,SAAS,IAAIiB,2BAAAA;AACtC,YAAA,MAAMC,SAAS,IAAI,CAACC,SAAS,CAAC5B,QAAQS,SAAW,EAAA,QAAA,CAAA;AACjD,YAAA,MAAMqD,aAA+B,GAAA;gBACnCH,UAAY,EAAA;AAAClD,oBAAAA;AAAU,iBAAA;AACvB,gBAAA,GAAGT,OAAOc;AACZ,aAAA;AAEA,YAAA,MAAMmC,OAAUK,GAAAA,GAAAA,CAAII,MAAM,CAAChE,OAAOiC,MAAQmC,EAAAA,aAAAA,CAAAA;YAE1C,IAAIb,OAAAA,CAAQnB,IAAI,KAAK,SAAW,EAAA;gBAC9B,OAAO;oBAAE8B,OAAS,EAAA;AAAM,iBAAA;AAC1B;YAEA,MAAMnG,OAAAA,GAAU,MAAM,IAAI,CAAC+D,QAAQ,CAACzD,eAAe,CAACkF,OAAAA,CAAQjF,SAAS,CAAA;AACrE,YAAA,IAAI,CAACP,OAAS,EAAA;gBACZ,OAAO;oBAAEmG,OAAS,EAAA;AAAM,iBAAA;AAC1B;AAEA,YAAA,MAAMtB,MAAM,IAAI3D,IAAAA,EAAAA;AAChB,YAAA,IAAI,IAAIA,IAAAA,CAAKlB,OAAQ8E,CAAAA,SAAS,KAAKD,GAAK,EAAA;gBACtC,OAAO;oBAAEsB,OAAS,EAAA;AAAM,iBAAA;AAC1B;;YAGA,IAAInG,OAAAA,CAAQgB,iBAAiB,IAAI,IAAIE,KAAKlB,OAAQgB,CAAAA,iBAAiB,KAAK6D,GAAK,EAAA;gBAC3E,OAAO;oBAAEsB,OAAS,EAAA;AAAM,iBAAA;AAC1B;;YAGA,IAAInG,OAAAA,CAAQiF,MAAM,KAAK,QAAU,EAAA;gBAC/B,OAAO;oBAAEkB,OAAS,EAAA;AAAM,iBAAA;AAC1B;AAEA,YAAA,IAAInG,OAAQqB,CAAAA,MAAM,KAAKmE,OAAAA,CAAQnE,MAAM,EAAE;gBACrC,OAAO;oBAAE8E,OAAS,EAAA;AAAM,iBAAA;AAC1B;YAEA,OAAO;gBACLA,OAAS,EAAA,IAAA;AACT9E,gBAAAA,MAAAA,EAAQmE,QAAQnE,MAAM;AACtBd,gBAAAA,SAAAA,EAAWiF,QAAQjF;AACrB,aAAA;AACF,SAAA,CAAE,OAAO+F,KAAY,EAAA;YACnB,IAAIA,KAAAA,YAAiBT,GAAIU,CAAAA,iBAAiB,EAAE;gBAC1C,OAAO;oBAAEJ,OAAS,EAAA;AAAM,iBAAA;AAC1B;YAEA,MAAMG,KAAAA;AACR;AACF;AAEA,IAAA,MAAMnE,uBAAuBb,MAAc,EAAED,MAAc,EAAEE,QAAiB,EAAiB;AAC7F,QAAA,MAAM,IAAI,CAACwC,QAAQ,CAAC5C,QAAQ,CAAC;AAAEE,YAAAA,MAAAA;AAAQC,YAAAA,MAAAA;AAAQC,YAAAA;AAAS,SAAA,CAAA;AAC1D;AAEA,IAAA,MAAMM,mBACJC,CAAAA,YAAoB,EACpBR,MAAc,EACkC;AAChD,QAAA,IAAI,CAACA,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAU,EAAA;AACzC,YAAA,MAAM,IAAIyB,KACR,CAAA,6EAAA,CAAA;AAEJ;AAEA,QAAA,MAAMyD,aAAa,MAAM,IAAI,CAACtE,oBAAoB,CAACJ,YAAcR,EAAAA,MAAAA,CAAAA;QAEjE,IAAI,CAACkF,UAAWL,CAAAA,OAAO,EAAE;YACvB,OAAO;gBAAEG,KAAO,EAAA;AAAwB,aAAA;AAC1C;AAEA,QAAA,MAAMd,OAAmD,GAAA;YACvDnE,MAAQoF,EAAAA,MAAAA,CAAOD,WAAWnF,MAAM,CAAA;AAChCd,YAAAA,SAAAA,EAAWiG,WAAWjG,SAAS;YAC/B8D,IAAM,EAAA;AACR,SAAA;AAEA,QAAA,MAAM9B,MAAS,GAAA,IAAI,CAACK,kBAAkB,CAACtB,MAAAA,CAAAA;QACvC,MAAM0B,SAAAA,GAAYT,MAAOS,CAAAA,SAAS,IAAIiB,2BAAAA;AACtC,QAAA,MAAMC,SAAS,IAAI,CAACC,SAAS,CAAC5B,QAAQS,SAAW,EAAA,MAAA,CAAA;;AAEjD,QAAA,MAAMK,UAAad,GAAAA,MAAAA,CAAOc,UAAU,IAAI,EAAC;QACzC,MAAM,EAAEsC,SAAS,EAAEvC,UAAU,EAAEE,SAAS,EAAE,GAAGsC,cAAAA,EAAgB,GAAGvC,UAAAA;AAEhE,QAAA,MAAMpB,KAAQ4D,GAAAA,GAAAA,CAAIC,IAAI,CAACN,SAAStB,MAAQ,EAAA;AACtClB,YAAAA,SAAAA;AACA2C,YAAAA,SAAAA,EAAWpD,OAAOmE,mBAAmB;AACrC,YAAA,GAAGd;AACL,SAAA,CAAA;QAEA,OAAO;AAAE3D,YAAAA;AAAM,SAAA;AACjB;AAEA,IAAA,MAAMF,kBACJD,CAAAA,YAAoB,EACpBR,MAAc,EASd;AACA,QAAA,IAAI,CAACA,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAU,EAAA;AACzC,YAAA,MAAM,IAAIyB,KACR,CAAA,6EAAA,CAAA;AAEJ;QAEA,IAAI;AACF,YAAA,MAAMR,MAAS,GAAA,IAAI,CAACK,kBAAkB,CAACtB,MAAAA,CAAAA;YACvC,MAAM0B,SAAAA,GAAYT,MAAOS,CAAAA,SAAS,IAAIiB,2BAAAA;AACtC,YAAA,MAAMC,SAAS,IAAI,CAACC,SAAS,CAAC5B,QAAQS,SAAW,EAAA,QAAA,CAAA;AACjD,YAAA,MAAMwC,OAAUK,GAAAA,GAAAA,CAAII,MAAM,CAACnE,cAAcoC,MAAQ,EAAA;gBAC/CgC,UAAY,EAAA;AAAClD,oBAAAA;AAAU,iBAAA;AACvB,gBAAA,GAAGT,OAAOc;AACZ,aAAA,CAAA;AAEA,YAAA,IAAI,CAACmC,OAAAA,IAAWA,OAAQnB,CAAAA,IAAI,KAAK,SAAW,EAAA;gBAC1C,OAAO;oBAAEiC,KAAO,EAAA;AAAwB,iBAAA;AAC1C;YAEA,MAAMK,OAAAA,GAAU,MAAM,IAAI,CAAC5C,QAAQ,CAACzD,eAAe,CAACkF,OAAAA,CAAQjF,SAAS,CAAA;AACrE,YAAA,IAAI,CAACoG,OAAS,EAAA;gBACZ,OAAO;oBAAEL,KAAO,EAAA;AAAwB,iBAAA;AAC1C;;YAGA,IAAIK,OAAAA,CAAQ3B,OAAO,EAAE;gBACnB,MAAM4B,KAAAA,GAAQ,MAAM,IAAI,CAAC7C,QAAQ,CAACzD,eAAe,CAACqG,OAAAA,CAAQ3B,OAAO,CAAA;AAEjE,gBAAA,IAAI4B,KAAO,EAAA;AACT,oBAAA,MAAMC,QAAW1B,GAAAA,IAAAA,CAAKC,KAAK,CAAC,IAAIlE,IAAAA,CAAK0F,KAAMvB,CAAAA,SAAS,IAAI,IAAInE,IAAQoE,EAAAA,CAAAA,CAAAA,OAAO,EAAK,GAAA,IAAA,CAAA;oBAChF,MAAMwB,QAAAA,GAAW3B,IAAKC,CAAAA,KAAK,CAAC,IAAIlE,KAAK0F,KAAM9B,CAAAA,SAAS,CAAEQ,CAAAA,OAAO,EAAK,GAAA,IAAA,CAAA;AAElE,oBAAA,MAAMyB,YAAoC,GAAA;AACxC1F,wBAAAA,MAAAA,EAAQuF,MAAMvF,MAAM;AACpBd,wBAAAA,SAAAA,EAAWqG,MAAMrG,SAAS;wBAC1B8D,IAAM,EAAA,SAAA;wBACNoB,GAAKoB,EAAAA,QAAAA;wBACLnB,GAAKoB,EAAAA;AACP,qBAAA;;oBAGA,MAAM,EAAEnB,SAAS,EAAE,GAAGC,gBAAgB,GAAGrD,MAAAA,CAAOc,UAAU,IAAI,EAAC;AAE/D,oBAAA,MAAM2D,UAAanB,GAAAA,GAAAA,CAAIC,IAAI,CAACiB,cAAc7C,MAAQ,EAAA;AAChDlB,wBAAAA,SAAAA;wBACA+C,WAAa,EAAA,IAAA;AACb,wBAAA,GAAGH;AACL,qBAAA,CAAA;oBAEA,IAAI5E,iBAAAA;oBACJ,IAAI4F,KAAAA,CAAM5F,iBAAiB,EAAE;wBAC3BA,iBACE,GAAA,OAAO4F,KAAM5F,CAAAA,iBAAiB,KAAK,QAAA,GAC/B4F,KAAM5F,CAAAA,iBAAiB,GACvB4F,KAAAA,CAAM5F,iBAAiB,CAACgF,WAAW,EAAA;qBACpC,MAAA;wBACLhF,iBAAoB,GAAA,IAAIE,IAAK,CAAA,CAAA,CAAA,CAAG8E,WAAW,EAAA;AAC7C;oBAEA,OAAO;wBACL/D,KAAO+E,EAAAA,UAAAA;AACPzG,wBAAAA,SAAAA,EAAWqG,MAAMrG,SAAS;AAC1BS,wBAAAA,iBAAAA;wBACAqD,IAAMuC,EAAAA,KAAAA,CAAMvC,IAAI,IAAI;AACtB,qBAAA;AACF;AACF;YAEA,MAAMQ,GAAAA,GAAM3D,KAAK2D,GAAG,EAAA;YACpB,MAAMT,SAAAA,GAAYuC,OAAQtC,CAAAA,IAAI,IAAI,SAAA;AAClC,YAAA,MAAME,eACJH,SAAc,KAAA,SAAA,GAAY7B,OAAOiC,wBAAwB,GAAGjC,OAAOkC,mBAAmB;;AAGxF,YAAA,IAAIkC,OAAQtB,CAAAA,SAAS,IAAIR,GAAAA,GAAM,IAAI3D,IAAAA,CAAKyF,OAAQtB,CAAAA,SAAS,CAAEC,CAAAA,OAAO,EAAKf,GAAAA,YAAAA,GAAe,IAAM,EAAA;gBAC1F,OAAO;oBAAE+B,KAAO,EAAA;AAAsB,iBAAA;AACxC;;YAGA,MAAMW,QAAAA,GAAWN,OAAQ3F,CAAAA,iBAAiB,GACtC,IAAIE,KAAKyF,OAAQ3F,CAAAA,iBAAiB,CAAEsE,CAAAA,OAAO,EAC3CT,GAAAA,GAAAA;AACJ,YAAA,IAAIoC,YAAYpC,GAAK,EAAA;gBACnB,OAAO;oBAAEyB,KAAO,EAAA;AAAqB,iBAAA;AACvC;;YAGA,MAAMY,cAAAA,GAAiB,IAAI,CAAC1D,iBAAiB,EAAA;AAC7C,YAAA,MAAM2D,cAAiB,GAAA,IAAIjG,IAAK2D,CAAAA,GAAAA,GAAMN,YAAe,GAAA,IAAA,CAAA;AAErD,YAAA,MAAM6C,cAAc,MAAM,IAAI,CAACrD,QAAQ,CAAChE,MAAM,CAAC;AAC7CsB,gBAAAA,MAAAA,EAAQsF,QAAQtF,MAAM;gBACtBd,SAAW2G,EAAAA,cAAAA;gBACX,GAAIP,OAAAA,CAAQpF,QAAQ,IAAI;AAAEA,oBAAAA,QAAAA,EAAUoF,QAAQpF;iBAAU;AACtDD,gBAAAA,MAAAA,EAAQqF,QAAQrF,MAAM;gBACtB0D,OAAS,EAAA,IAAA;gBACTX,IAAMD,EAAAA,SAAAA;gBACNa,MAAQ,EAAA,QAAA;gBACRH,SAAWqC,EAAAA,cAAAA;AACXnG,gBAAAA,iBAAAA,EAAmB2F,OAAQ3F,CAAAA,iBAAiB,IAAI,IAAIE,IAAK+F,CAAAA,QAAAA;AAC3D,aAAA,CAAA;AAEA,YAAA,MAAMJ,QAAW1B,GAAAA,IAAAA,CAAKC,KAAK,CAAC,IAAIlE,IAAAA,CAAKkG,WAAY/B,CAAAA,SAAS,IAAI,IAAInE,IAAQoE,EAAAA,CAAAA,CAAAA,OAAO,EAAK,GAAA,IAAA,CAAA;YACtF,MAAMwB,QAAAA,GAAW3B,IAAKC,CAAAA,KAAK,CAAC,IAAIlE,KAAKkG,WAAYtC,CAAAA,SAAS,CAAEQ,CAAAA,OAAO,EAAK,GAAA,IAAA,CAAA;AACxE,YAAA,MAAM+B,UAAkC,GAAA;AACtChG,gBAAAA,MAAAA,EAAQsF,QAAQtF,MAAM;gBACtBd,SAAW2G,EAAAA,cAAAA;gBACX7C,IAAM,EAAA,SAAA;gBACNoB,GAAKoB,EAAAA,QAAAA;gBACLnB,GAAKoB,EAAAA;AACP,aAAA;;YAEA,MAAM,EAAEnB,SAAS,EAAE,GAAGC,gBAAgB,GAAGrD,MAAAA,CAAOc,UAAU,IAAI,EAAC;AAE/D,YAAA,MAAM2D,UAAanB,GAAAA,GAAAA,CAAIC,IAAI,CAACuB,YAAYnD,MAAQ,EAAA;AAC9ClB,gBAAAA,SAAAA;gBACA+C,WAAa,EAAA,IAAA;AACb,gBAAA,GAAGH;AACL,aAAA,CAAA;YAEA,MAAM,IAAI,CAAC7B,QAAQ,CAACrD,iBAAiB,CAACiG,OAAAA,CAAQpG,SAAS,EAAE;gBACvD0E,MAAQ,EAAA,SAAA;gBACRD,OAASkC,EAAAA;AACX,aAAA,CAAA;YAEA,IAAIlG,iBAAAA;YACJ,IAAIoG,WAAAA,CAAYpG,iBAAiB,EAAE;gBACjCA,iBACE,GAAA,OAAOoG,WAAYpG,CAAAA,iBAAiB,KAAK,QAAA,GACrCoG,WAAYpG,CAAAA,iBAAiB,GAC7BoG,WAAAA,CAAYpG,iBAAiB,CAACgF,WAAW,EAAA;aAC1C,MAAA;gBACLhF,iBAAoB,GAAA,IAAIE,IAAK+F,CAAAA,QAAAA,CAAAA,CAAUjB,WAAW,EAAA;AACpD;YAEA,OAAO;gBACL/D,KAAO+E,EAAAA,UAAAA;gBACPzG,SAAW2G,EAAAA,cAAAA;AACXlG,gBAAAA,iBAAAA;gBACAqD,IAAMD,EAAAA;AACR,aAAA;AACF,SAAA,CAAE,OAAM;YACN,OAAO;gBAAEkC,KAAO,EAAA;AAAwB,aAAA;AAC1C;AACF;AAEA;;;AAGC,MACD,MAAMlE,eAAAA,CAAgB7B,SAAiB,EAAEe,MAAc,EAAoB;AACzE,QAAA,MAAMtB,UAAU,MAAM,IAAI,CAAC+D,QAAQ,CAACzD,eAAe,CAACC,SAAAA,CAAAA;AACpD,QAAA,IAAI,CAACP,OAAS,EAAA;YACZ,OAAO,KAAA;AACT;QAEA,IAAIA,OAAAA,CAAQsB,MAAM,KAAKA,MAAQ,EAAA;YAC7B,OAAO,KAAA;AACT;AAEA,QAAA,IAAI,IAAIJ,IAAKlB,CAAAA,OAAAA,CAAQ8E,SAAS,CAAA,IAAK,IAAI5D,IAAQ,EAAA,EAAA;;AAE7C,YAAA,MAAM,IAAI,CAAC6C,QAAQ,CAACnD,iBAAiB,CAACL,SAAAA,CAAAA;YAEtC,OAAO,KAAA;AACT;QAEA,OAAO,IAAA;AACT;AAzdAiB,IAAAA,WAAAA,CAAYuC,QAAyB,CAAE;;AAP/BvB,QAAAA,IAAAA,CAAAA,aAAAA,GAAmD,IAAI8E,GAAAA,EAAAA;;aAGvDzD,wBAAmC,GAAA,CAAA;aAE1BC,iBAA4B,GAAA,EAAA;QAG3C,IAAI,CAACC,QAAQ,GAAGA,QAAAA;AAClB;AAwdF;AAEMwD,MAAAA,sBAAAA,GAAyB,CAACrH,EAAcE,EAAAA,WAAAA,GAAAA;IAC5C,OAAO,IAAIN,wBAAwBI,EAAIE,EAAAA,WAAAA,CAAAA;AACzC;AAEA,MAAMoH,oBAAuB,GAAA,CAAC,EAC5BtH,EAAE,EAGH,GAAA;IACC,MAAM6D,QAAAA,GAAWwD,uBAAuBrH,EAAI,EAAA,gBAAA,CAAA;IAC5C,MAAM0B,cAAAA,GAAiB,IAAIS,cAAe0B,CAAAA,QAAAA,CAAAA;;AAG1C,IAAA,MAAM0D,YAAY,CAACnG,MAAAA,GAAAA;AACjB,QAAA,IAAI,CAACA,MAAAA,IAAU,OAAOA,MAAAA,KAAW,QAAU,EAAA;AACzC,YAAA,MAAM,IAAIyB,KACR,CAAA,6EAAA,CAAA;AAEJ;QACA,OAAO,IAAItB,qBAAqBG,cAAgBN,EAAAA,MAAAA,CAAAA;AAClD,KAAA;;AAGA,IAAA,MAAMoG,GAAMD,GAAAA,SAAAA;AACZC,IAAAA,GAAAA,CAAIlE,iBAAiB,GAAG5B,cAAAA,CAAe4B,iBAAiB,CAACmE,IAAI,CAAC/F,cAAAA,CAAAA;AAC9D8F,IAAAA,GAAAA,CAAIpF,YAAY,GAAGV,cAAAA,CAAeU,YAAY,CAACqF,IAAI,CAAC/F,cAAAA,CAAAA;AACpD8F,IAAAA,GAAAA,CAAIhF,SAAS,GAAGd,cAAAA,CAAec,SAAS,CAACiF,IAAI,CAAC/F,cAAAA,CAAAA;;;IAI9CgG,MAAOC,CAAAA,cAAc,CAACH,GAAAA,EAAK,kBAAoB,EAAA;AAC7C5E,QAAAA,GAAAA,CAAAA,GAAAA;AACE,YAAA,OAAOlB,eAAeoC,gBAAgB;AACxC,SAAA;QACA8D,UAAY,EAAA;AACd,KAAA,CAAA;IAEA,OAAOJ,GAAAA;AACT;;;;;"}
@@ -111,6 +111,32 @@ class SessionManager {
111
111
  }
112
112
  throw new Error(`SessionManager: Origin '${origin}' is not defined. Please define it using defineOrigin('${origin}', config).`);
113
113
  }
114
+ /**
115
+ * Get the appropriate JWT key based on the algorithm
116
+ */ getJwtKey(config, algorithm, operation) {
117
+ const isAsymmetric = algorithm.startsWith('RS') || algorithm.startsWith('ES') || algorithm.startsWith('PS');
118
+ if (isAsymmetric) {
119
+ // For asymmetric algorithms, check if user has provided proper key configuration
120
+ if (operation === 'sign') {
121
+ const privateKey = config.jwtOptions?.privateKey;
122
+ if (privateKey) {
123
+ return privateKey;
124
+ }
125
+ throw new Error(`SessionManager: Private key is required for asymmetric algorithm ${algorithm}. Please configure admin.auth.options.privateKey.`);
126
+ } else {
127
+ const publicKey = config.jwtOptions?.publicKey;
128
+ if (publicKey) {
129
+ return publicKey;
130
+ }
131
+ throw new Error(`SessionManager: Public key is required for asymmetric algorithm ${algorithm}. Please configure admin.auth.options.publicKey.`);
132
+ }
133
+ } else {
134
+ if (!config.jwtSecret) {
135
+ throw new Error(`SessionManager: Secret key is required for symmetric algorithm ${algorithm}`);
136
+ }
137
+ return config.jwtSecret;
138
+ }
139
+ }
114
140
  generateSessionId() {
115
141
  return crypto.randomBytes(16).toString('hex');
116
142
  }
@@ -132,6 +158,8 @@ class SessionManager {
132
158
  }
133
159
  await this.maybeCleanupExpired();
134
160
  const config = this.getConfigForOrigin(origin);
161
+ const algorithm = config.algorithm || DEFAULT_ALGORITHM;
162
+ const jwtKey = this.getJwtKey(config, algorithm, 'sign');
135
163
  const sessionId = this.generateSessionId();
136
164
  const tokenType = options?.type ?? 'refresh';
137
165
  const isRefresh = tokenType === 'refresh';
@@ -163,9 +191,13 @@ class SessionManager {
163
191
  iat: issuedAtSeconds,
164
192
  exp: expiresAtSeconds
165
193
  };
166
- const token = jwt.sign(payload, config.jwtSecret, {
167
- algorithm: DEFAULT_ALGORITHM,
168
- noTimestamp: true
194
+ // Filter out conflicting options that are already handled by the payload or used for key selection
195
+ const jwtOptions = config.jwtOptions || {};
196
+ const { expiresIn, privateKey, publicKey, ...jwtSignOptions } = jwtOptions;
197
+ const token = jwt.sign(payload, jwtKey, {
198
+ algorithm,
199
+ noTimestamp: true,
200
+ ...jwtSignOptions
169
201
  });
170
202
  return {
171
203
  token,
@@ -179,10 +211,13 @@ class SessionManager {
179
211
  }
180
212
  try {
181
213
  const config = this.getConfigForOrigin(origin);
182
- const payload = jwt.verify(token, config.jwtSecret, {
214
+ const algorithm = config.algorithm || DEFAULT_ALGORITHM;
215
+ const jwtKey = this.getJwtKey(config, algorithm, 'verify');
216
+ const payload = jwt.verify(token, jwtKey, {
183
217
  algorithms: [
184
- DEFAULT_ALGORITHM
185
- ]
218
+ algorithm
219
+ ],
220
+ ...config.jwtOptions
186
221
  });
187
222
  // Ensure this is an access token
188
223
  if (!payload || payload.type !== 'access') {
@@ -208,12 +243,15 @@ class SessionManager {
208
243
  }
209
244
  try {
210
245
  const config = this.getConfigForOrigin(origin);
246
+ const algorithm = config.algorithm || DEFAULT_ALGORITHM;
247
+ const jwtKey = this.getJwtKey(config, algorithm, 'verify');
211
248
  const verifyOptions = {
212
249
  algorithms: [
213
- DEFAULT_ALGORITHM
214
- ]
250
+ algorithm
251
+ ],
252
+ ...config.jwtOptions
215
253
  };
216
- const payload = jwt.verify(token, config.jwtSecret, verifyOptions);
254
+ const payload = jwt.verify(token, jwtKey, verifyOptions);
217
255
  if (payload.type !== 'refresh') {
218
256
  return {
219
257
  isValid: false
@@ -285,9 +323,15 @@ class SessionManager {
285
323
  type: 'access'
286
324
  };
287
325
  const config = this.getConfigForOrigin(origin);
288
- const token = jwt.sign(payload, config.jwtSecret, {
289
- algorithm: DEFAULT_ALGORITHM,
290
- expiresIn: config.accessTokenLifespan
326
+ const algorithm = config.algorithm || DEFAULT_ALGORITHM;
327
+ const jwtKey = this.getJwtKey(config, algorithm, 'sign');
328
+ // Filter out conflicting options that are already handled by the payload or used for key selection
329
+ const jwtOptions = config.jwtOptions || {};
330
+ const { expiresIn, privateKey, publicKey, ...jwtSignOptions } = jwtOptions;
331
+ const token = jwt.sign(payload, jwtKey, {
332
+ algorithm,
333
+ expiresIn: config.accessTokenLifespan,
334
+ ...jwtSignOptions
291
335
  });
292
336
  return {
293
337
  token
@@ -299,10 +343,13 @@ class SessionManager {
299
343
  }
300
344
  try {
301
345
  const config = this.getConfigForOrigin(origin);
302
- const payload = jwt.verify(refreshToken, config.jwtSecret, {
346
+ const algorithm = config.algorithm || DEFAULT_ALGORITHM;
347
+ const jwtKey = this.getJwtKey(config, algorithm, 'verify');
348
+ const payload = jwt.verify(refreshToken, jwtKey, {
303
349
  algorithms: [
304
- DEFAULT_ALGORITHM
305
- ]
350
+ algorithm
351
+ ],
352
+ ...config.jwtOptions
306
353
  });
307
354
  if (!payload || payload.type !== 'refresh') {
308
355
  return {
@@ -328,9 +375,12 @@ class SessionManager {
328
375
  iat: childIat,
329
376
  exp: childExp
330
377
  };
331
- const childToken = jwt.sign(childPayload, config.jwtSecret, {
332
- algorithm: DEFAULT_ALGORITHM,
333
- noTimestamp: true
378
+ // Filter out conflicting options that are already handled by the payload
379
+ const { expiresIn, ...jwtSignOptions } = config.jwtOptions || {};
380
+ const childToken = jwt.sign(childPayload, jwtKey, {
381
+ algorithm,
382
+ noTimestamp: true,
383
+ ...jwtSignOptions
334
384
  });
335
385
  let absoluteExpiresAt;
336
386
  if (child.absoluteExpiresAt) {
@@ -387,9 +437,12 @@ class SessionManager {
387
437
  iat: childIat,
388
438
  exp: childExp
389
439
  };
390
- const childToken = jwt.sign(payloadOut, config.jwtSecret, {
391
- algorithm: DEFAULT_ALGORITHM,
392
- noTimestamp: true
440
+ // Filter out conflicting options that are already handled by the payload
441
+ const { expiresIn, ...jwtSignOptions } = config.jwtOptions || {};
442
+ const childToken = jwt.sign(payloadOut, jwtKey, {
443
+ algorithm,
444
+ noTimestamp: true,
445
+ ...jwtSignOptions
393
446
  });
394
447
  await this.provider.updateBySessionId(current.sessionId, {
395
448
  status: 'rotated',