@igxjs/node-components 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/http-handlers.js +6 -0
- package/components/jwt.js +89 -45
- package/components/session.js +36 -18
- package/index.d.ts +62 -38
- package/package.json +10 -3
- package/.github/workflows/node.js.yml +0 -31
- package/.github/workflows/npm-publish.yml +0 -33
- package/docs/README.md +0 -54
- package/docs/flex-router.md +0 -167
- package/docs/http-handlers.md +0 -302
- package/docs/jwt-manager.md +0 -124
- package/docs/redis-manager.md +0 -210
- package/docs/session-manager.md +0 -160
- package/tests/http-handlers.test.js +0 -21
- package/tests/jwt.test.js +0 -345
- package/tests/redis.test.js +0 -50
- package/tests/router.test.js +0 -50
- package/tests/session.test.js +0 -116
|
@@ -141,6 +141,12 @@ const _getErrorMessage = (error, defaultMessage) => {
|
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
export const httpHelper = {
|
|
144
|
+
/**
|
|
145
|
+
* Format a string with placeholders
|
|
146
|
+
* @param {string} str String with {0}, {1}, etc. placeholders
|
|
147
|
+
* @param {...string} args Values to replace placeholders
|
|
148
|
+
* @returns {string} Formatted string
|
|
149
|
+
*/
|
|
144
150
|
format (str, ...args) {
|
|
145
151
|
const matched = str.match(/{\d}/ig);
|
|
146
152
|
matched.forEach((element, index) => {
|
package/components/jwt.js
CHANGED
|
@@ -1,51 +1,89 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
|
|
1
3
|
import { jwtDecrypt, EncryptJWT } from 'jose';
|
|
2
4
|
|
|
5
|
+
/**
|
|
6
|
+
* JwtManager configuration options
|
|
7
|
+
* Uses strict UPPERCASE naming convention with JWT_ prefix for all property names.
|
|
8
|
+
*/
|
|
3
9
|
export class JwtManager {
|
|
10
|
+
/** @type {string} JWE algorithm */
|
|
11
|
+
algorithm;
|
|
12
|
+
|
|
13
|
+
/** @type {string} Encryption method */
|
|
14
|
+
encryption;
|
|
15
|
+
|
|
16
|
+
/** @type {string} Token expiration time */
|
|
17
|
+
expirationTime;
|
|
18
|
+
|
|
19
|
+
/** @type {number} Clock tolerance in seconds */
|
|
20
|
+
clockTolerance;
|
|
21
|
+
|
|
22
|
+
/** @type {string} Hash algorithm for secret derivation */
|
|
23
|
+
secretHashAlgorithm;
|
|
24
|
+
|
|
25
|
+
/** @type {string|null} Optional JWT issuer claim */
|
|
26
|
+
issuer;
|
|
27
|
+
|
|
28
|
+
/** @type {string|null} Optional JWT audience claim */
|
|
29
|
+
audience;
|
|
30
|
+
|
|
31
|
+
/** @type {string|null} Optional JWT subject claim */
|
|
32
|
+
subject;
|
|
4
33
|
/**
|
|
5
34
|
* Create a new JwtManager instance with configurable defaults
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
10
|
-
* @
|
|
11
|
-
* @
|
|
12
|
-
* @
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
35
|
+
* Constructor options use UPPERCASE naming convention with JWT_ prefix (e.g., JWT_ALGORITHM).
|
|
36
|
+
*
|
|
37
|
+
* @typedef {Object} JwtManagerOptions JwtManager configuration options
|
|
38
|
+
* @property {string} [JWT_ALGORITHM='dir'] JWE algorithm (default: 'dir')
|
|
39
|
+
* @property {string} [JWT_ENCRYPTION='A256GCM'] Encryption method (default: 'A256GCM')
|
|
40
|
+
* @property {string} [JWT_EXPIRATION_TIME='10m'] Token expiration time (default: '10m')
|
|
41
|
+
* @property {string} [JWT_SECRET_HASH_ALGORITHM='SHA-256'] Hash algorithm (default: 'SHA-256')
|
|
42
|
+
* @property {string?} [JWT_ISSUER] Optional JWT issuer claim
|
|
43
|
+
* @property {string?} [JWT_AUDIENCE] Optional JWT audience claim
|
|
44
|
+
* @property {string?} [JWT_SUBJECT] Optional JWT subject claim
|
|
45
|
+
* @property {number} [JWT_CLOCK_TOLERANCE=30] Clock tolerance in seconds (default: 30)
|
|
46
|
+
* @param {JwtManagerOptions} options Configuration options
|
|
15
47
|
*/
|
|
16
48
|
constructor(options = {}) {
|
|
17
|
-
this.algorithm = options.
|
|
18
|
-
this.encryption = options.
|
|
19
|
-
this.expirationTime = options.
|
|
20
|
-
this.
|
|
21
|
-
this.
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
49
|
+
this.algorithm = options.JWT_ALGORITHM || 'dir';
|
|
50
|
+
this.encryption = options.JWT_ENCRYPTION || 'A256GCM';
|
|
51
|
+
this.expirationTime = options.JWT_EXPIRATION_TIME || '10m';
|
|
52
|
+
this.secretHashAlgorithm = options.JWT_SECRET_HASH_ALGORITHM || 'SHA-256';
|
|
53
|
+
this.issuer = options.JWT_ISSUER;
|
|
54
|
+
this.audience = options.JWT_AUDIENCE;
|
|
55
|
+
this.subject = options.JWT_SUBJECT;
|
|
56
|
+
this.clockTolerance = options.JWT_CLOCK_TOLERANCE ?? 30;
|
|
25
57
|
}
|
|
26
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Encrypt method options (camelCase naming convention, uses instance defaults when not provided)
|
|
61
|
+
*
|
|
62
|
+
* @typedef {Object} JwtEncryptOptions Encryption method options
|
|
63
|
+
* @property {string} [algorithm='dir'] JWE algorithm (overrides instance JWT_ALGORITHM)
|
|
64
|
+
* @property {string} [encryption='A256GCM'] Encryption method (overrides instance JWT_ENCRYPTION)
|
|
65
|
+
* @property {string} [expirationTime='10m'] Token expiration time (overrides instance JWT_EXPIRATION_TIME)
|
|
66
|
+
* @property {string} [secretHashAlgorithm='SHA-256'] Hash algorithm for secret derivation (overrides instance JWT_SECRET_HASH_ALGORITHM)
|
|
67
|
+
* @property {string?} [issuer] Optional JWT issuer claim (overrides instance JWT_ISSUER)
|
|
68
|
+
* @property {string?} [audience] Optional JWT audience claim (overrides instance JWT_AUDIENCE)
|
|
69
|
+
* @property {string?} [subject] Optional JWT subject claim (overrides instance JWT_SUBJECT)
|
|
70
|
+
*/
|
|
27
71
|
/**
|
|
28
72
|
* Generate JWT token for user session
|
|
73
|
+
*
|
|
29
74
|
* @param {import('jose').JWTPayload} data User data payload
|
|
30
75
|
* @param {string} secret Secret key or password for encryption
|
|
31
|
-
* @param {
|
|
32
|
-
* @param {string} [options.algorithm] Override default algorithm
|
|
33
|
-
* @param {string} [options.encryption] Override default encryption method
|
|
34
|
-
* @param {string} [options.expirationTime] Override default expiration time
|
|
35
|
-
* @param {string} [options.secretHashAlgorithm] Override default hash algorithm
|
|
36
|
-
* @param {string} [options.issuer] Override default issuer claim
|
|
37
|
-
* @param {string} [options.audience] Override default audience claim
|
|
38
|
-
* @param {string} [options.subject] Override default subject claim
|
|
76
|
+
* @param {JwtEncryptOptions} [options] Per-call configuration overrides (camelCase naming convention)
|
|
39
77
|
* @returns {Promise<string>} Returns encrypted JWT token
|
|
40
78
|
*/
|
|
41
79
|
async encrypt(data, secret, options = {}) {
|
|
42
|
-
const algorithm = options.algorithm
|
|
43
|
-
const encryption = options.encryption
|
|
44
|
-
const expirationTime = options.expirationTime
|
|
45
|
-
const secretHashAlgorithm = options.secretHashAlgorithm
|
|
46
|
-
const issuer = options.issuer
|
|
47
|
-
const audience = options.audience
|
|
48
|
-
const subject = options.subject
|
|
80
|
+
const algorithm = options.algorithm ?? this.algorithm;
|
|
81
|
+
const encryption = options.encryption ?? this.encryption;
|
|
82
|
+
const expirationTime = options.expirationTime ?? this.expirationTime;
|
|
83
|
+
const secretHashAlgorithm = options.secretHashAlgorithm ?? this.secretHashAlgorithm;
|
|
84
|
+
const issuer = options.issuer ?? this.issuer;
|
|
85
|
+
const audience = options.audience ?? this.audience;
|
|
86
|
+
const subject = options.subject ?? this.subject;
|
|
49
87
|
|
|
50
88
|
const secretHash = await crypto.subtle.digest(
|
|
51
89
|
secretHashAlgorithm,
|
|
@@ -69,23 +107,29 @@ export class JwtManager {
|
|
|
69
107
|
}
|
|
70
108
|
|
|
71
109
|
/**
|
|
72
|
-
* Decrypt
|
|
110
|
+
* Decrypt method options (camelCase naming convention, uses instance defaults when not provided)
|
|
111
|
+
*
|
|
112
|
+
* @typedef {Object} JwtDecryptOptions Decryption method options
|
|
113
|
+
* @property {number} [clockTolerance=30] Clock tolerance in seconds (overrides instance JWT_CLOCK_TOLERANCE)
|
|
114
|
+
* @property {string} [secretHashAlgorithm='SHA-256'] Hash algorithm for secret derivation (overrides instance JWT_SECRET_HASH_ALGORITHM)
|
|
115
|
+
* @property {string?} [issuer] Optional JWT issuer claim for validation (overrides instance JWT_ISSUER)
|
|
116
|
+
* @property {string?} [audience] Optional JWT audience claim for validation (overrides instance JWT_AUDIENCE)
|
|
117
|
+
* @property {string?} [subject] Optional JWT subject claim for validation (overrides instance JWT_SUBJECT)
|
|
118
|
+
**/
|
|
119
|
+
/**
|
|
120
|
+
* Decrypt JWT
|
|
121
|
+
*
|
|
73
122
|
* @param {string} token JWT token to decrypt
|
|
74
123
|
* @param {string} secret Secret key or password for decryption
|
|
75
|
-
* @param {
|
|
76
|
-
* @
|
|
77
|
-
* @param {string} [options.secretHashAlgorithm] Override default hash algorithm
|
|
78
|
-
* @param {string} [options.issuer] Expected issuer claim for validation
|
|
79
|
-
* @param {string} [options.audience] Expected audience claim for validation
|
|
80
|
-
* @param {string} [options.subject] Expected subject claim for validation
|
|
81
|
-
* @returns {Promise<import('jose').JWTDecryptResult<import('jose').EncryptJWT>>} Returns decrypted JWT token
|
|
124
|
+
* @param {JwtDecryptOptions} [options] Per-call configuration overrides (camelCase naming convention)
|
|
125
|
+
* @returns {Promise<import('jose').JWTDecryptResult<import('jose').EncryptJWT>} Returns decrypted JWT token
|
|
82
126
|
*/
|
|
83
127
|
async decrypt(token, secret, options = {}) {
|
|
84
128
|
const clockTolerance = options.clockTolerance ?? this.clockTolerance;
|
|
85
|
-
const secretHashAlgorithm = options.secretHashAlgorithm
|
|
86
|
-
const issuer = options.issuer
|
|
87
|
-
const audience = options.audience
|
|
88
|
-
const subject = options.subject
|
|
129
|
+
const secretHashAlgorithm = options.secretHashAlgorithm ?? this.secretHashAlgorithm;
|
|
130
|
+
const issuer = options.issuer ?? this.issuer;
|
|
131
|
+
const audience = options.audience ?? this.audience;
|
|
132
|
+
const subject = options.subject ?? this.subject;
|
|
89
133
|
|
|
90
134
|
const secretHash = await crypto.subtle.digest(
|
|
91
135
|
secretHashAlgorithm,
|
|
@@ -101,4 +145,4 @@ export class JwtManager {
|
|
|
101
145
|
|
|
102
146
|
return await jwtDecrypt(token, new Uint8Array(secretHash), decryptOptions);
|
|
103
147
|
}
|
|
104
|
-
}
|
|
148
|
+
}
|
package/components/session.js
CHANGED
|
@@ -2,13 +2,15 @@ import axios from 'axios';
|
|
|
2
2
|
import session from 'express-session';
|
|
3
3
|
import memStore from 'memorystore';
|
|
4
4
|
import { RedisStore } from 'connect-redis';
|
|
5
|
-
import { jwtDecrypt } from 'jose';
|
|
6
5
|
|
|
7
6
|
import { CustomError, httpCodes, httpHelper, httpMessages } from './http-handlers.js';
|
|
7
|
+
import { JwtManager } from './jwt.js';
|
|
8
8
|
import { RedisManager } from './redis.js';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Session configuration options
|
|
12
|
+
* Uses strict UPPERCASE naming convention for all property names
|
|
13
|
+
*/
|
|
12
14
|
export class SessionConfig {
|
|
13
15
|
/** @type {string} */
|
|
14
16
|
SSO_ENDPOINT_URL;
|
|
@@ -34,6 +36,23 @@ export class SessionConfig {
|
|
|
34
36
|
REDIS_URL;
|
|
35
37
|
/** @type {string} */
|
|
36
38
|
REDIS_CERT_PATH;
|
|
39
|
+
|
|
40
|
+
/** @type {string} */
|
|
41
|
+
JWT_ALGORITHM;
|
|
42
|
+
/** @type {string} */
|
|
43
|
+
JWT_ENCRYPTION;
|
|
44
|
+
/** @type {string} */
|
|
45
|
+
JWT_EXPIRATION_TIME;
|
|
46
|
+
/** @type {number} */
|
|
47
|
+
JWT_CLOCK_TOLERANCE;
|
|
48
|
+
/** @type {string} */
|
|
49
|
+
JWT_SECRET_HASH_ALGORITHM;
|
|
50
|
+
/** @type {string} */
|
|
51
|
+
JWT_ISSUER;
|
|
52
|
+
/** @type {string} */
|
|
53
|
+
JWT_AUDIENCE;
|
|
54
|
+
/** @type {string} */
|
|
55
|
+
JWT_SUBJECT;
|
|
37
56
|
}
|
|
38
57
|
|
|
39
58
|
export class SessionManager {
|
|
@@ -45,6 +64,8 @@ export class SessionManager {
|
|
|
45
64
|
#redisManager = null;
|
|
46
65
|
/** @type {import('axios').AxiosInstance} */
|
|
47
66
|
#idpRequest = null;
|
|
67
|
+
/** @type {import('./jwt.js').JwtManager} */
|
|
68
|
+
#jwtManager = null;
|
|
48
69
|
|
|
49
70
|
/**
|
|
50
71
|
* Create a new session manager
|
|
@@ -66,6 +87,15 @@ export class SessionManager {
|
|
|
66
87
|
// Redis
|
|
67
88
|
REDIS_URL: config.REDIS_URL,
|
|
68
89
|
REDIS_CERT_PATH: config.REDIS_CERT_PATH,
|
|
90
|
+
// JWT Manager
|
|
91
|
+
JWT_ALGORITHM: config.JWT_ALGORITHM || 'dir',
|
|
92
|
+
JWT_ENCRYPTION: config.JWT_ENCRYPTION || 'A256GCM',
|
|
93
|
+
JWT_EXPIRATION_TIME: config.JWT_EXPIRATION_TIME || '10m',
|
|
94
|
+
JWT_CLOCK_TOLERANCE: config.JWT_CLOCK_TOLERANCE ?? 30,
|
|
95
|
+
JWT_SECRET_HASH_ALGORITHM: config.JWT_SECRET_HASH_ALGORITHM || 'SHA-256',
|
|
96
|
+
JWT_ISSUER: config.JWT_ISSUER,
|
|
97
|
+
JWT_AUDIENCE: config.JWT_AUDIENCE,
|
|
98
|
+
JWT_SUBJECT: config.JWT_SUBJECT,
|
|
69
99
|
};
|
|
70
100
|
}
|
|
71
101
|
|
|
@@ -126,6 +156,7 @@ export class SessionManager {
|
|
|
126
156
|
*/
|
|
127
157
|
async setup(app, updateUser) {
|
|
128
158
|
this.#redisManager = new RedisManager();
|
|
159
|
+
this.#jwtManager = new JwtManager(this.#config);
|
|
129
160
|
// Identity Provider Request
|
|
130
161
|
this.#idpRequest = axios.create({
|
|
131
162
|
baseURL: this.#config.SSO_ENDPOINT_URL,
|
|
@@ -158,6 +189,7 @@ export class SessionManager {
|
|
|
158
189
|
#memorySession() {
|
|
159
190
|
// Memory Session
|
|
160
191
|
console.log('### Using Memory as the Session Store ###');
|
|
192
|
+
const MemoryStore = memStore(session);
|
|
161
193
|
return session({
|
|
162
194
|
cookie: { maxAge: this.#config.SESSION_AGE, path: this.#config.SESSION_COOKIE_PATH, sameSite: false },
|
|
163
195
|
store: new MemoryStore({}),
|
|
@@ -221,7 +253,7 @@ export class SessionManager {
|
|
|
221
253
|
*/
|
|
222
254
|
#saveSession = async (request, jwt, initUser) => {
|
|
223
255
|
/** @type {{ payload: { user: import('../models/types/user').UserModel, redirect_url: string } }} */
|
|
224
|
-
const { payload } = await this.#
|
|
256
|
+
const { payload } = await this.#jwtManager.decrypt(jwt, this.#config.SSO_CLIENT_SECRET);
|
|
225
257
|
if (payload?.user) {
|
|
226
258
|
console.debug('### CALLBACK USER ###');
|
|
227
259
|
request.session[this.#getSessionKey()] = initUser(payload.user);
|
|
@@ -365,18 +397,4 @@ export class SessionManager {
|
|
|
365
397
|
return callback(null);
|
|
366
398
|
});
|
|
367
399
|
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Decrypt JWT data for user session
|
|
371
|
-
* @param {string} data JWT data
|
|
372
|
-
* @param {string} input Input string for encryption
|
|
373
|
-
* @returns {Promise<import('jose').JWTDecryptResult<import('jose').EncryptJWT>>} Returns decrypted JWT payload
|
|
374
|
-
*/
|
|
375
|
-
async #decryptJWT(data, input) {
|
|
376
|
-
const secret = await crypto.subtle.digest(
|
|
377
|
-
'SHA-256',
|
|
378
|
-
new TextEncoder().encode(input)
|
|
379
|
-
);
|
|
380
|
-
return await jwtDecrypt(data, new Uint8Array(secret), { clockTolerance: 30 });
|
|
381
|
-
}
|
|
382
400
|
}
|
package/index.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ import { EncryptJWT, JWTDecryptResult, JWTPayload } from 'jose';
|
|
|
5
5
|
import { RedisClientType } from '@redis/client';
|
|
6
6
|
import { Application, RequestHandler, Request, Response, NextFunction, Router } from 'express';
|
|
7
7
|
|
|
8
|
-
// Session Configuration
|
|
8
|
+
// Session Configuration - uses strict UPPERCASE naming convention for all property names
|
|
9
9
|
export interface SessionConfig {
|
|
10
|
+
/** Identity Provider */
|
|
10
11
|
SSO_ENDPOINT_URL?: string;
|
|
11
12
|
SSO_CLIENT_ID?: string;
|
|
12
13
|
SSO_CLIENT_SECRET?: string;
|
|
@@ -58,7 +59,7 @@ export interface SessionUser {
|
|
|
58
59
|
export class SessionManager {
|
|
59
60
|
/**
|
|
60
61
|
* Constructor
|
|
61
|
-
* @param config - Session configuration
|
|
62
|
+
* @param config - Session configuration (uses strict UPPERCASE property names)
|
|
62
63
|
*/
|
|
63
64
|
constructor(config: SessionConfig);
|
|
64
65
|
|
|
@@ -187,7 +188,7 @@ export class RedisManager {
|
|
|
187
188
|
|
|
188
189
|
/**
|
|
189
190
|
* Determine if the Redis server is connected
|
|
190
|
-
* @returns Returns true if Redis server is connected
|
|
191
|
+
* @returns Returns true if the Redis server is connected
|
|
191
192
|
*/
|
|
192
193
|
isConnected(): Promise<boolean>;
|
|
193
194
|
|
|
@@ -198,57 +199,80 @@ export class RedisManager {
|
|
|
198
199
|
disConnect(): Promise<void>;
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
// JWT Manager Configuration
|
|
202
|
+
// JWT Manager Configuration - uses strict UPPERCASE naming convention with JWT_ prefix for all property names
|
|
202
203
|
export interface JwtManagerOptions {
|
|
203
|
-
/**
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
encryption
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
204
|
+
/** JWE algorithm (default: 'dir') */
|
|
205
|
+
JWT_ALGORITHM?: string;
|
|
206
|
+
|
|
207
|
+
/** JWE encryption method (default: 'A256GCM') */
|
|
208
|
+
JWT_ENCRYPTION?: string;
|
|
209
|
+
|
|
210
|
+
/** Token expiration time (default: '10m') */
|
|
211
|
+
JWT_EXPIRATION_TIME?: string;
|
|
212
|
+
|
|
213
|
+
/** Clock tolerance in seconds for token validation (default: 30) */
|
|
214
|
+
JWT_CLOCK_TOLERANCE?: number;
|
|
215
|
+
|
|
216
|
+
/** Hash algorithm for secret derivation (default: 'SHA-256') */
|
|
217
|
+
JWT_SECRET_HASH_ALGORITHM?: string;
|
|
218
|
+
|
|
219
|
+
/** Optional JWT issuer claim */
|
|
220
|
+
JWT_ISSUER?: string;
|
|
221
|
+
|
|
222
|
+
/** Optional JWT audience claim */
|
|
223
|
+
JWT_AUDIENCE?: string;
|
|
224
|
+
|
|
225
|
+
/** Optional JWT subject claim */
|
|
226
|
+
JWT_SUBJECT?: string;
|
|
219
227
|
}
|
|
220
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Options for encrypt() method - uses camelCase naming convention
|
|
231
|
+
*/
|
|
221
232
|
export interface JwtEncryptOptions {
|
|
222
|
-
/**
|
|
233
|
+
/** Override default algorithm */
|
|
223
234
|
algorithm?: string;
|
|
224
|
-
|
|
235
|
+
|
|
236
|
+
/** Override default encryption method */
|
|
225
237
|
encryption?: string;
|
|
226
|
-
|
|
238
|
+
|
|
239
|
+
/** Override default expiration time */
|
|
227
240
|
expirationTime?: string;
|
|
228
|
-
|
|
241
|
+
|
|
242
|
+
/** Override default hash algorithm */
|
|
229
243
|
secretHashAlgorithm?: string;
|
|
230
|
-
|
|
244
|
+
|
|
245
|
+
/** Override default issuer claim */
|
|
231
246
|
issuer?: string;
|
|
232
|
-
|
|
247
|
+
|
|
248
|
+
/** Override default audience claim */
|
|
233
249
|
audience?: string;
|
|
234
|
-
|
|
250
|
+
|
|
251
|
+
/** Override default subject claim */
|
|
235
252
|
subject?: string;
|
|
236
253
|
}
|
|
237
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Options for decrypt() method - uses camelCase naming convention
|
|
257
|
+
*/
|
|
238
258
|
export interface JwtDecryptOptions {
|
|
239
|
-
/**
|
|
259
|
+
/** Override default clock tolerance */
|
|
240
260
|
clockTolerance?: number;
|
|
241
|
-
|
|
261
|
+
|
|
262
|
+
/** Override default hash algorithm */
|
|
242
263
|
secretHashAlgorithm?: string;
|
|
243
|
-
|
|
264
|
+
|
|
265
|
+
/** Expected issuer claim for validation */
|
|
244
266
|
issuer?: string;
|
|
245
|
-
|
|
267
|
+
|
|
268
|
+
/** Expected audience claim for validation */
|
|
246
269
|
audience?: string;
|
|
247
|
-
|
|
270
|
+
|
|
271
|
+
/** Expected subject claim for validation */
|
|
248
272
|
subject?: string;
|
|
249
273
|
}
|
|
250
274
|
|
|
251
|
-
export type
|
|
275
|
+
export type JwtDecryptResult = JWTDecryptResult<EncryptJWT>;
|
|
252
276
|
// JwtManager class for JWT encryption and decryption
|
|
253
277
|
export class JwtManager {
|
|
254
278
|
algorithm: string;
|
|
@@ -262,7 +286,7 @@ export class JwtManager {
|
|
|
262
286
|
|
|
263
287
|
/**
|
|
264
288
|
* Create a new JwtManager instance with configurable defaults
|
|
265
|
-
* @param options Configuration options
|
|
289
|
+
* @param options Configuration options (uses strict UPPERCASE with JWT_ prefix property names)
|
|
266
290
|
*/
|
|
267
291
|
constructor(options?: JwtManagerOptions);
|
|
268
292
|
|
|
@@ -270,7 +294,7 @@ export class JwtManager {
|
|
|
270
294
|
* Generate JWT token for user session
|
|
271
295
|
* @param data User data payload
|
|
272
296
|
* @param input Secret key or password for encryption
|
|
273
|
-
* @param options Per-call configuration overrides
|
|
297
|
+
* @param options Per-call configuration overrides (uses strict UPPERCASE with JWT_ prefix property names)
|
|
274
298
|
* @returns Returns encrypted JWT token
|
|
275
299
|
*/
|
|
276
300
|
encrypt(data: JWTPayload, input: string, options?: JwtEncryptOptions): Promise<string>;
|
|
@@ -279,10 +303,10 @@ export class JwtManager {
|
|
|
279
303
|
* Decrypt JWT token for user session
|
|
280
304
|
* @param token JWT token to decrypt
|
|
281
305
|
* @param input Secret key or password for decryption
|
|
282
|
-
* @param options Per-call configuration overrides
|
|
306
|
+
* @param options Per-call configuration overrides (uses strict UPPERCASE with JWT_ prefix property names)
|
|
283
307
|
* @returns Returns decrypted JWT token
|
|
284
308
|
*/
|
|
285
|
-
decrypt(token: string, input: string, options?: JwtDecryptOptions): Promise<
|
|
309
|
+
decrypt(token: string, input: string, options?: JwtDecryptOptions): Promise<JwtDecryptResult>;
|
|
286
310
|
}
|
|
287
311
|
|
|
288
312
|
// HTTP status code keys (exposed for type safety)
|
|
@@ -400,4 +424,4 @@ declare module 'express-session' {
|
|
|
400
424
|
[key: string]: any;
|
|
401
425
|
user?: SessionUser;
|
|
402
426
|
}
|
|
403
|
-
}
|
|
427
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@igxjs/node-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Node components for igxjs",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -26,16 +26,23 @@
|
|
|
26
26
|
"axios": "^1.13.6",
|
|
27
27
|
"connect-redis": "^9.0.0",
|
|
28
28
|
"express-session": "^1.19.0",
|
|
29
|
-
"jose": "^6.
|
|
29
|
+
"jose": "^6.2.0",
|
|
30
30
|
"memorystore": "^1.6.7"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"chai": "^6.2.2",
|
|
34
34
|
"express": "^5.2.1",
|
|
35
|
-
"mocha": "^
|
|
35
|
+
"mocha": "^12.0.0-beta-10",
|
|
36
36
|
"sinon": "^21.0.2",
|
|
37
37
|
"supertest": "^7.0.0"
|
|
38
38
|
},
|
|
39
|
+
"files": [
|
|
40
|
+
"index.js",
|
|
41
|
+
"index.d.ts",
|
|
42
|
+
"components/",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"README.md"
|
|
45
|
+
],
|
|
39
46
|
"publishConfig": {
|
|
40
47
|
"access": "public"
|
|
41
48
|
},
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
|
3
|
-
|
|
4
|
-
name: Node.js CI
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
push:
|
|
8
|
-
branches: [ "main" ]
|
|
9
|
-
pull_request:
|
|
10
|
-
branches: [ "main" ]
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
build:
|
|
14
|
-
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
|
|
17
|
-
strategy:
|
|
18
|
-
matrix:
|
|
19
|
-
node-version: [18.x, 20.x, 22.x]
|
|
20
|
-
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
|
21
|
-
|
|
22
|
-
steps:
|
|
23
|
-
- uses: actions/checkout@v4
|
|
24
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
-
uses: actions/setup-node@v4
|
|
26
|
-
with:
|
|
27
|
-
node-version: ${{ matrix.node-version }}
|
|
28
|
-
cache: 'npm'
|
|
29
|
-
- run: npm ci
|
|
30
|
-
- run: npm run build --if-present
|
|
31
|
-
- run: npm test
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
-
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
|
|
3
|
-
|
|
4
|
-
name: Node.js Package
|
|
5
|
-
|
|
6
|
-
on:
|
|
7
|
-
release:
|
|
8
|
-
types: [created]
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
build:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
- uses: actions/setup-node@v4
|
|
16
|
-
with:
|
|
17
|
-
node-version: 20
|
|
18
|
-
- run: npm ci
|
|
19
|
-
- run: npm test
|
|
20
|
-
|
|
21
|
-
publish-npm:
|
|
22
|
-
needs: build
|
|
23
|
-
runs-on: ubuntu-latest
|
|
24
|
-
steps:
|
|
25
|
-
- uses: actions/checkout@v4
|
|
26
|
-
- uses: actions/setup-node@v4
|
|
27
|
-
with:
|
|
28
|
-
node-version: 20
|
|
29
|
-
registry-url: https://registry.npmjs.org/
|
|
30
|
-
- run: npm ci
|
|
31
|
-
- run: npm publish
|
|
32
|
-
env:
|
|
33
|
-
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
package/docs/README.md
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Node Components Documentation
|
|
2
|
-
|
|
3
|
-
Detailed documentation for `@igxjs/node-components` - shared components for Express.js applications.
|
|
4
|
-
|
|
5
|
-
## 📚 Component Documentation
|
|
6
|
-
|
|
7
|
-
### Core Modules
|
|
8
|
-
|
|
9
|
-
- **[SessionManager](./session-manager.md)** - SSO session management with Redis and memory storage
|
|
10
|
-
- Configuration options and singleton pattern
|
|
11
|
-
- Complete setup and usage examples
|
|
12
|
-
- API reference for all methods
|
|
13
|
-
|
|
14
|
-
- **[FlexRouter](./flex-router.md)** - Flexible routing utility for Express.js
|
|
15
|
-
- Context path and middleware management
|
|
16
|
-
- API versioning and route organization
|
|
17
|
-
- Advanced usage patterns
|
|
18
|
-
|
|
19
|
-
- **[RedisManager](./redis-manager.md)** - Redis connection management
|
|
20
|
-
- TLS/SSL support
|
|
21
|
-
- Connection monitoring and error handling
|
|
22
|
-
- Direct Redis operations
|
|
23
|
-
|
|
24
|
-
- **[JWT Manager](./jwt-manager.md)** - JWT encryption and decryption
|
|
25
|
-
- Secure token-based authentication
|
|
26
|
-
- Express.js integration patterns
|
|
27
|
-
- Refresh token implementation
|
|
28
|
-
|
|
29
|
-
- **[HTTP Handlers](./http-handlers.md)** - Standardized error handling
|
|
30
|
-
- Custom error classes and middleware
|
|
31
|
-
- HTTP status codes and messages
|
|
32
|
-
- Axios error handling and validation helpers
|
|
33
|
-
|
|
34
|
-
## 🚀 Quick Links
|
|
35
|
-
|
|
36
|
-
- [Main README](../README.md) - Package overview and installation
|
|
37
|
-
- [GitHub Repository](https://github.com/igxjs/node-components)
|
|
38
|
-
|
|
39
|
-
## 💡 Getting Help
|
|
40
|
-
|
|
41
|
-
If you need help:
|
|
42
|
-
1. Check the relevant component documentation above
|
|
43
|
-
2. Review the examples in each guide
|
|
44
|
-
3. Look at the type definitions in `index.d.ts`
|
|
45
|
-
4. Open an issue on GitHub
|
|
46
|
-
|
|
47
|
-
## 📖 Documentation Structure
|
|
48
|
-
|
|
49
|
-
Each component documentation includes:
|
|
50
|
-
- Overview of features
|
|
51
|
-
- Configuration options
|
|
52
|
-
- Basic and advanced usage examples
|
|
53
|
-
- Complete API reference
|
|
54
|
-
- Related documentation links
|