@carecard/jwt-read 3.1.12 → 3.1.14
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/.prettierrc.js +12 -0
- package/eslint.config.mjs +14 -0
- package/index.d.ts +71 -27
- package/index.js +46 -45
- package/lib/jwtLib.js +241 -258
- package/lib/jwtRoles.js +32 -13
- package/package.json +18 -10
- package/readme.md +6 -5
package/.prettierrc.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
arrowParens: 'avoid',
|
|
3
|
+
bracketSameLine: true,
|
|
4
|
+
bracketSpacing: true,
|
|
5
|
+
singleQuote: true,
|
|
6
|
+
trailingComma: 'all',
|
|
7
|
+
printWidth: 140,
|
|
8
|
+
useTabs: false,
|
|
9
|
+
endOfLine: 'auto',
|
|
10
|
+
importOrderSeparation: true,
|
|
11
|
+
importOrderSortSpecifiers: true,
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig, globalIgnores } from 'eslint/config';
|
|
2
|
+
|
|
3
|
+
const eslintConfig = defineConfig([
|
|
4
|
+
globalIgnores([
|
|
5
|
+
// Default ignores of eslint-config-next:
|
|
6
|
+
'.next/**',
|
|
7
|
+
'out/**',
|
|
8
|
+
'build/**',
|
|
9
|
+
'next-env.d.ts',
|
|
10
|
+
'node_modules/**',
|
|
11
|
+
]),
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
export default eslintConfig;
|
package/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Utility functions for authentication and authorization in the CareCard ecosystem.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { Request, Response
|
|
5
|
+
import {NextFunction, Request, Response} from 'express';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Represents the standard JWT header structure.
|
|
@@ -50,44 +50,50 @@ export interface JwtParts {
|
|
|
50
50
|
* Structure of the JWT object attached to the request.
|
|
51
51
|
*/
|
|
52
52
|
export interface JwtRequestObject {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
header: JwtHeader;
|
|
54
|
+
payload: JwtPayload;
|
|
55
|
+
age?: number;
|
|
56
|
+
jwtClientId: (req?: any) => string | undefined;
|
|
57
|
+
doesJwtUserHasRole: (role: string) => boolean;
|
|
58
|
+
isJwtExpired: (jwtValiditySeconds?: number) => boolean;
|
|
59
|
+
jwtAgeInSeconds: (req?: any) => number;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Structure of the visitor object attached to the request.
|
|
64
64
|
*/
|
|
65
65
|
export interface VisitorRequestObject {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
header: JwtHeader;
|
|
67
|
+
payload: JwtPayload;
|
|
68
|
+
visitorClientId: (req?: any) => string | undefined;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Extended Express Request to include jwt and visitor objects.
|
|
73
73
|
*/
|
|
74
74
|
export interface AuthenticatedRequest extends Request {
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
jwt?: JwtRequestObject | null;
|
|
76
|
+
visitor?: VisitorRequestObject | null;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
80
79
|
/**
|
|
81
80
|
* Returns a middleware that verifies a JWT from the 'Authorization: Bearer <token>' header
|
|
82
81
|
* and extracts it into req.jwt. Throws an error if invalid.
|
|
83
82
|
*/
|
|
84
|
-
export function jwtVerify(
|
|
83
|
+
export function jwtVerify(
|
|
84
|
+
publicKey: string,
|
|
85
|
+
customErrorFunction?: () => void,
|
|
86
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
85
87
|
|
|
86
88
|
/**
|
|
87
89
|
* Returns a middleware that verifies a JWT from a custom header and extracts it into req.jwt.
|
|
88
90
|
* Throws an error if invalid.
|
|
89
91
|
*/
|
|
90
|
-
export function jwtVerifyWebToken(
|
|
92
|
+
export function jwtVerifyWebToken(
|
|
93
|
+
publicKey: string,
|
|
94
|
+
headerName: string,
|
|
95
|
+
customErrorFunction?: () => void,
|
|
96
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
91
97
|
|
|
92
98
|
/**
|
|
93
99
|
* Returns a middleware that verifies a JWT from the 'Authorization: Bearer <token>' header
|
|
@@ -99,7 +105,10 @@ export function jwtVerifyNoThrow(publicKey: string): (req: AuthenticatedRequest,
|
|
|
99
105
|
* Returns a middleware that verifies a JWT from a custom header and extracts it into req.jwt.
|
|
100
106
|
* Returns false instead of throwing if invalid.
|
|
101
107
|
*/
|
|
102
|
-
export function jwtVerifyWebTokenNoThrow(
|
|
108
|
+
export function jwtVerifyWebTokenNoThrow(
|
|
109
|
+
publicKey: string,
|
|
110
|
+
headerName: string,
|
|
111
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
103
112
|
|
|
104
113
|
/**
|
|
105
114
|
* Returns a middleware that verifies a visitor token from the 'Visitor' header
|
|
@@ -132,7 +141,11 @@ export function jwtGetAgeInSeconds(req?: any): number;
|
|
|
132
141
|
/**
|
|
133
142
|
* Returns a middleware that verifies the JWT and checks if the user has the required role.
|
|
134
143
|
*/
|
|
135
|
-
export function jwtVerifyAndHasRole(
|
|
144
|
+
export function jwtVerifyAndHasRole(
|
|
145
|
+
userRole: string,
|
|
146
|
+
publicKey: string,
|
|
147
|
+
customErrorFunction?: () => void,
|
|
148
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
136
149
|
|
|
137
150
|
/**
|
|
138
151
|
* Gets the full name of a role from its code (e.g., 'ad' -> 'admin').
|
|
@@ -144,6 +157,22 @@ export function jwtGetRoleName(roleCode: string): string;
|
|
|
144
157
|
*/
|
|
145
158
|
export function jwtGetRoleCode(roleName: string): string;
|
|
146
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Represents the context derived from the JWT request.
|
|
162
|
+
*/
|
|
163
|
+
export interface JwtContext {
|
|
164
|
+
/** The user ID (sub) from the JWT. Always returned. */
|
|
165
|
+
user_id: string | undefined;
|
|
166
|
+
/** The role of the user. Only set to 'super_admin' when roles contains 'ad'. */
|
|
167
|
+
role?: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Returns the context derived from the JWT in req.jwt.
|
|
172
|
+
* Always returns user_id. If the roles array contains 'ad', also returns role: 'super_admin'.
|
|
173
|
+
*/
|
|
174
|
+
export function jwtGetContext(req: any): JwtContext;
|
|
175
|
+
|
|
147
176
|
/**
|
|
148
177
|
* Validates the JWT from the Authorization header and extracts it into req.jwt.
|
|
149
178
|
*/
|
|
@@ -152,7 +181,12 @@ export function jwtValidateAndExtract(req: AuthenticatedRequest, publicKey: stri
|
|
|
152
181
|
/**
|
|
153
182
|
* Validates the JWT from a custom header and extracts it into req.jwt.
|
|
154
183
|
*/
|
|
155
|
-
export function jwtValidateAndExtractWebToken(
|
|
184
|
+
export function jwtValidateAndExtractWebToken(
|
|
185
|
+
req: AuthenticatedRequest,
|
|
186
|
+
publicKey: string,
|
|
187
|
+
headerName: string,
|
|
188
|
+
customErrorFunction?: () => void,
|
|
189
|
+
): void;
|
|
156
190
|
|
|
157
191
|
/**
|
|
158
192
|
* Validates the JWT from the Authorization header and extracts it into req.jwt (no-throw).
|
|
@@ -169,20 +203,26 @@ export function jwtValidateAndExtractWebTokenNoThrow(req: AuthenticatedRequest,
|
|
|
169
203
|
*/
|
|
170
204
|
export function jwtValidateAndExtractVisitorNoThrow(req: AuthenticatedRequest, publicKey: string): void;
|
|
171
205
|
|
|
172
|
-
|
|
173
206
|
/**
|
|
174
207
|
* Returns a middleware that verifies a JWT from the 'Authorization: Bearer <token>' header
|
|
175
208
|
* and extracts it into req.jwt. Throws an error if invalid.
|
|
176
209
|
* @deprecated use jwtVerify
|
|
177
210
|
*/
|
|
178
|
-
export function verifyJwt(
|
|
211
|
+
export function verifyJwt(
|
|
212
|
+
publicKey: string,
|
|
213
|
+
customErrorFunction?: () => void,
|
|
214
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
179
215
|
|
|
180
216
|
/**
|
|
181
217
|
* Returns a middleware that verifies a JWT from a custom header and extracts it into req.jwt.
|
|
182
218
|
* Throws an error if invalid.
|
|
183
219
|
* @deprecated use jwtVerifyWebToken
|
|
184
220
|
*/
|
|
185
|
-
export function verifyWebToken(
|
|
221
|
+
export function verifyWebToken(
|
|
222
|
+
publicKey: string,
|
|
223
|
+
headerName: string,
|
|
224
|
+
customErrorFunction?: () => void,
|
|
225
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
186
226
|
|
|
187
227
|
/**
|
|
188
228
|
* Returns a middleware that verifies a JWT from the 'Authorization: Bearer <token>' header
|
|
@@ -196,7 +236,10 @@ export function verifyJwtNoThrow(publicKey: string): (req: AuthenticatedRequest,
|
|
|
196
236
|
* Returns false instead of throwing if invalid.
|
|
197
237
|
* @deprecated use jwtVerifyWebTokenNoThrow
|
|
198
238
|
*/
|
|
199
|
-
export function verifyWebTokenNoThrow(
|
|
239
|
+
export function verifyWebTokenNoThrow(
|
|
240
|
+
publicKey: string,
|
|
241
|
+
headerName: string,
|
|
242
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
200
243
|
|
|
201
244
|
/**
|
|
202
245
|
* Returns a middleware that verifies a visitor token from the 'Visitor' header
|
|
@@ -237,7 +280,11 @@ export function jwtAgeInSeconds(req?: any): number;
|
|
|
237
280
|
* Returns a middleware that verifies the JWT and checks if the user has the required role.
|
|
238
281
|
* @deprecated use jwtVerifyAndHasRole
|
|
239
282
|
*/
|
|
240
|
-
export function verifyJwtAndRole(
|
|
283
|
+
export function verifyJwtAndRole(
|
|
284
|
+
userRole: string,
|
|
285
|
+
publicKey: string,
|
|
286
|
+
customErrorFunction?: () => void,
|
|
287
|
+
): (req: AuthenticatedRequest, res: Response, next: NextFunction) => void;
|
|
241
288
|
|
|
242
289
|
/**
|
|
243
290
|
* Throws a Used_Token error.
|
|
@@ -245,7 +292,6 @@ export function verifyJwtAndRole(userRole: string, publicKey: string, customErro
|
|
|
245
292
|
*/
|
|
246
293
|
export function throwUsedTokenError(): never;
|
|
247
294
|
|
|
248
|
-
|
|
249
295
|
/**
|
|
250
296
|
* Checks if the user in the extracted JWT has the specified role.
|
|
251
297
|
* @deprecated use jwtDoesJwtUserHasRole
|
|
@@ -260,10 +306,8 @@ export function doesJwtUserHasRole(userRole: string): boolean;
|
|
|
260
306
|
*/
|
|
261
307
|
export function getNameOfRole(roleCode: string): string;
|
|
262
308
|
|
|
263
|
-
|
|
264
309
|
/**
|
|
265
310
|
* Gets the code of a role from its name (e.g., 'admin' -> 'ad').
|
|
266
311
|
* @deprecated use jwtGetRoleCode
|
|
267
312
|
*/
|
|
268
313
|
export function getCodeOfRole(roleName: string): string;
|
|
269
|
-
|
package/index.js
CHANGED
|
@@ -2,50 +2,51 @@ const jwtLib = require('./lib/jwtLib');
|
|
|
2
2
|
const jwtRoles = require('./lib/jwtRoles');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
5
|
+
jwtVerify: jwtLib.verifyJwt,
|
|
6
|
+
jwtVerifyWebToken: jwtLib.verifyWebToken,
|
|
7
|
+
jwtVerifyNoThrow: jwtLib.verifyJwtNoThrow,
|
|
8
|
+
jwtVerifyWebTokenNoThrow: jwtLib.verifyWebTokenNoThrow,
|
|
9
|
+
jwtVerifyVisitorNoThrow: jwtLib.verifyVisitorNoThrow,
|
|
10
|
+
jwtGetClientId: jwtLib.jwtClientId,
|
|
11
|
+
jwtGetVisitorClientId: jwtLib.visitorClientId,
|
|
12
|
+
jwtIsExpired: jwtLib.isJwtExpired,
|
|
13
|
+
jwtGetAgeInSeconds: jwtLib.jwtAgeInSeconds,
|
|
14
|
+
jwtVerifyAndHasRole: jwtLib.verifyJwtAndRole,
|
|
15
|
+
jwtGetRoleName: jwtRoles.getNameOfRoleFromCode,
|
|
16
|
+
jwtGetRoleCode: jwtRoles.getCodeFromNameOfRole,
|
|
17
|
+
jwtGetContext: jwtRoles.getContext,
|
|
18
|
+
jwtValidateAndExtract: jwtLib.validateAndExtractJwtObject,
|
|
19
|
+
jwtValidateAndExtractWebToken: jwtLib.validateAndExtractWebToken,
|
|
20
|
+
jwtValidateAndExtractNoThrow: jwtLib.validateAndExtractJwtObjectNoThrow,
|
|
21
|
+
jwtValidateAndExtractWebTokenNoThrow: jwtLib.validateAndExtractWebTokenObjectNoThrow,
|
|
22
|
+
jwtValidateAndExtractVisitorNoThrow: jwtLib.validateAndExtractVisitorObjectNoThrow,
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
24
|
+
/** @deprecated use jwtVerify */
|
|
25
|
+
verifyJwt: jwtLib.verifyJwt,
|
|
26
|
+
/** @deprecated use jwtVerifyWebToken */
|
|
27
|
+
verifyWebToken: jwtLib.verifyWebToken,
|
|
28
|
+
/** @deprecated use jwtVerifyNoThrow */
|
|
29
|
+
verifyJwtNoThrow: jwtLib.verifyJwtNoThrow,
|
|
30
|
+
/** @deprecated use jwtVerifyWebTokenNoThrow */
|
|
31
|
+
verifyWebTokenNoThrow: jwtLib.verifyWebTokenNoThrow,
|
|
32
|
+
/** @deprecated use jwtVerifyVisitorNoThrow */
|
|
33
|
+
verifyVisitorNoThrow: jwtLib.verifyVisitorNoThrow,
|
|
34
|
+
/** @deprecated use jwtGetClientId */
|
|
35
|
+
jwtClientId: jwtLib.jwtClientId,
|
|
36
|
+
/** @deprecated use jwtGetVisitorClientId */
|
|
37
|
+
visitorClientId: jwtLib.visitorClientId,
|
|
38
|
+
/** @deprecated use jwtIsExpired */
|
|
39
|
+
isJwtExpired: jwtLib.isJwtExpired,
|
|
40
|
+
/** @deprecated use jwtGetAgeInSeconds */
|
|
41
|
+
jwtAgeInSeconds: jwtLib.jwtAgeInSeconds,
|
|
42
|
+
/** @deprecated use jwtVerifyAndHasRole */
|
|
43
|
+
verifyJwtAndRole: jwtLib.verifyJwtAndRole,
|
|
44
|
+
/** @deprecated use jwtThrowUsedTokenError */
|
|
45
|
+
throwUsedTokenError: jwtLib.throwUsedTokenError,
|
|
46
|
+
/** @deprecated use jwtDoesJwtUserHasRole */
|
|
47
|
+
doesJwtUserHasRole: jwtLib.doesJwtUserHasRole,
|
|
48
|
+
/** @deprecated use jwtGetRoleName */
|
|
49
|
+
getNameOfRole: jwtRoles.getNameOfRoleFromCode,
|
|
50
|
+
/** @deprecated use jwtGetRoleCode */
|
|
51
|
+
getCodeOfRole: jwtRoles.getCodeFromNameOfRole,
|
|
51
52
|
};
|
package/lib/jwtLib.js
CHANGED
|
@@ -1,411 +1,394 @@
|
|
|
1
|
-
const {isJwtString} = require('@carecard/validate')
|
|
2
|
-
const {jwtVerifySignedToken, jwtGetHeaderPayload} = require('@carecard/auth-util');
|
|
1
|
+
const { isJwtString } = require('@carecard/validate');
|
|
2
|
+
const { jwtVerifySignedToken, jwtGetHeaderPayload } = require('@carecard/auth-util');
|
|
3
3
|
|
|
4
|
-
const {
|
|
5
|
-
throwLoginRequiredError,
|
|
6
|
-
throwNotAuthorizedError
|
|
7
|
-
} = require("@carecard/common-util").error;
|
|
4
|
+
const { throwLoginRequiredError, throwNotAuthorizedError } = require('@carecard/common-util');
|
|
8
5
|
|
|
9
6
|
function jwtClientId(req) {
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
const jwtObj = req?.jwt || this;
|
|
8
|
+
return jwtObj?.payload?.sub;
|
|
12
9
|
}
|
|
13
10
|
|
|
14
11
|
function visitorClientId(req) {
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const visitorObj = req?.visitor || this;
|
|
13
|
+
return visitorObj?.payload?.sub;
|
|
17
14
|
}
|
|
18
15
|
|
|
19
16
|
function doesJwtUserHasRole(req, userRole) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
// Check if called as req.jwt.doesJwtUserHasRole(userRole) or doesJwtUserHasRole(role)
|
|
18
|
+
if (arguments.length === 1 && typeof req === 'string') {
|
|
19
|
+
userRole = req;
|
|
20
|
+
req = undefined;
|
|
21
|
+
}
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
const jwtObj = req?.jwt || this;
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
if (!userRole || typeof userRole !== 'string' || !jwtObj?.payload?.roles || !Array.isArray(jwtObj.payload.roles)) {
|
|
26
|
+
throwNotAuthorizedError();
|
|
27
|
+
}
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
return jwtObj.payload.roles.includes(userRole);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
function throwError(customErrorFunction) {
|
|
36
|
-
|
|
37
|
-
customErrorFunction() :
|
|
38
|
-
throwLoginRequiredError()
|
|
33
|
+
typeof customErrorFunction === 'function' ? customErrorFunction() : throwLoginRequiredError();
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
function isJwtExpired(req, jwtValiditySeconds) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
// Check if called as req.jwt.isJwtExpired(seconds) or isJwtExpired(seconds)
|
|
38
|
+
if (arguments.length === 1 && typeof req === 'number') {
|
|
39
|
+
jwtValiditySeconds = req;
|
|
40
|
+
req = undefined;
|
|
41
|
+
}
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (jwtObj?.payload?.exp) {
|
|
51
|
-
return (Math.floor(Date.now() / 1000)) >= jwtObj.payload.exp;
|
|
52
|
-
}
|
|
43
|
+
const jwtObj = req?.jwt || this;
|
|
53
44
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
45
|
+
if (jwtObj?.payload?.exp) {
|
|
46
|
+
return Math.floor(Date.now() / 1000) >= jwtObj.payload.exp;
|
|
47
|
+
}
|
|
59
48
|
|
|
49
|
+
if (jwtValiditySeconds && typeof jwtValiditySeconds === 'number') {
|
|
50
|
+
return parseInt(jwtValiditySeconds) < jwtAgeInSeconds.call(this, req);
|
|
51
|
+
} else {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
60
54
|
}
|
|
61
55
|
|
|
62
56
|
function jwtAgeInSeconds(req) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (jwtObj?.payload?.iat) {
|
|
66
|
-
|
|
67
|
-
let iat = jwtObj.payload.iat;
|
|
68
|
-
if (iat > 1000000000000) {
|
|
69
|
-
iat = Math.floor(iat / 1000);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
jwtObj["age"] = Math.floor(Date.now() / 1000) - iat;
|
|
73
|
-
return jwtObj.age;
|
|
74
|
-
|
|
75
|
-
} else {
|
|
76
|
-
|
|
77
|
-
jwtObj["age"] = Infinity
|
|
78
|
-
return jwtObj.age;
|
|
57
|
+
const jwtObj = req?.jwt || this;
|
|
79
58
|
|
|
59
|
+
if (jwtObj?.payload?.iat) {
|
|
60
|
+
let iat = jwtObj.payload.iat;
|
|
61
|
+
if (iat > 1000000000000) {
|
|
62
|
+
iat = Math.floor(iat / 1000);
|
|
80
63
|
}
|
|
64
|
+
|
|
65
|
+
jwtObj['age'] = Math.floor(Date.now() / 1000) - iat;
|
|
66
|
+
return jwtObj.age;
|
|
67
|
+
} else {
|
|
68
|
+
jwtObj['age'] = Infinity;
|
|
69
|
+
return jwtObj.age;
|
|
70
|
+
}
|
|
81
71
|
}
|
|
82
72
|
|
|
83
73
|
function validateAndExtractJwtObject(req, publicKey, customErrorFunction) {
|
|
74
|
+
const jwtString = _validateJwt(req, customErrorFunction);
|
|
84
75
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const isJwtSignatureValid = jwtVerifySignedToken(jwtString, publicKey);
|
|
76
|
+
const isJwtSignatureValid = jwtVerifySignedToken(jwtString, publicKey);
|
|
88
77
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
78
|
+
if (jwtString && isJwtSignatureValid) {
|
|
79
|
+
_extractJwtObject(req, jwtString, customErrorFunction);
|
|
80
|
+
} else {
|
|
81
|
+
req['jwt'] = null;
|
|
82
|
+
throwError(customErrorFunction);
|
|
83
|
+
}
|
|
95
84
|
|
|
96
|
-
|
|
85
|
+
return req;
|
|
97
86
|
}
|
|
98
87
|
|
|
99
88
|
function validateAndExtractWebToken(req, publicKey, headerName, customErrorFunction) {
|
|
89
|
+
const webTokenString = _validateWebToken(req, headerName, customErrorFunction);
|
|
100
90
|
|
|
101
|
-
|
|
91
|
+
const isJwtSignatureValid = jwtVerifySignedToken(webTokenString, publicKey);
|
|
102
92
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
throwError(customErrorFunction);
|
|
110
|
-
}
|
|
93
|
+
if (webTokenString && isJwtSignatureValid) {
|
|
94
|
+
_extractJwtObject(req, webTokenString, customErrorFunction);
|
|
95
|
+
} else {
|
|
96
|
+
req['jwt'] = null;
|
|
97
|
+
throwError(customErrorFunction);
|
|
98
|
+
}
|
|
111
99
|
|
|
112
|
-
|
|
100
|
+
return req;
|
|
113
101
|
}
|
|
114
102
|
|
|
115
103
|
function validateAndExtractJwtObjectNoThrow(req, publicKey) {
|
|
116
|
-
|
|
104
|
+
return _validateAndExtractGenericNoThrow(req, publicKey, _validateJwtNoThrow, _extractJwtObjectNoThrow, 'jwt');
|
|
117
105
|
}
|
|
118
106
|
|
|
119
107
|
function validateAndExtractWebTokenObjectNoThrow(req, publicKey, headerName) {
|
|
120
|
-
|
|
108
|
+
return _validateAndExtractGenericNoThrow(req, publicKey, r => _validateWebTokenNoThrow(r, headerName), _extractJwtObjectNoThrow, 'jwt');
|
|
121
109
|
}
|
|
122
110
|
|
|
123
111
|
function validateAndExtractVisitorObjectNoThrow(req, publicKey) {
|
|
124
|
-
|
|
112
|
+
return _validateAndExtractGenericNoThrow(req, publicKey, _validateVisitorNoThrow, _extractVisitorObjectNoThrow, 'visitor');
|
|
125
113
|
}
|
|
126
114
|
|
|
127
115
|
function verifyJwtAndRole(role, publicKey, customErrorFunction) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
116
|
+
return function (req, res, next) {
|
|
117
|
+
try {
|
|
118
|
+
validateAndExtractJwtObject(req, publicKey, customErrorFunction);
|
|
119
|
+
const isRoleExist = doesJwtUserHasRole(req, role);
|
|
120
|
+
_isLoginRequired(isRoleExist, customErrorFunction);
|
|
121
|
+
next();
|
|
122
|
+
} catch (err) {
|
|
123
|
+
next(err);
|
|
137
124
|
}
|
|
125
|
+
};
|
|
138
126
|
}
|
|
139
127
|
|
|
140
128
|
function verifyJwt(publicKey, customErrorFunction) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
129
|
+
return function (req, res, next) {
|
|
130
|
+
try {
|
|
131
|
+
validateAndExtractJwtObject(req, publicKey, customErrorFunction);
|
|
132
|
+
next();
|
|
133
|
+
} catch (err) {
|
|
134
|
+
next(err);
|
|
148
135
|
}
|
|
136
|
+
};
|
|
149
137
|
}
|
|
150
138
|
|
|
151
139
|
function verifyWebToken(publicKey, headerName, customErrorFunction) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
140
|
+
return function (req, res, next) {
|
|
141
|
+
try {
|
|
142
|
+
validateAndExtractWebToken(req, publicKey, headerName, customErrorFunction);
|
|
143
|
+
next();
|
|
144
|
+
} catch (err) {
|
|
145
|
+
next(err);
|
|
159
146
|
}
|
|
147
|
+
};
|
|
160
148
|
}
|
|
161
149
|
|
|
162
150
|
function verifyJwtNoThrow(publicKey) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
151
|
+
return function (req, res, next) {
|
|
152
|
+
try {
|
|
153
|
+
validateAndExtractJwtObjectNoThrow(req, publicKey);
|
|
154
|
+
next();
|
|
155
|
+
} catch (err) {
|
|
156
|
+
next(err);
|
|
170
157
|
}
|
|
158
|
+
};
|
|
171
159
|
}
|
|
172
160
|
|
|
173
161
|
function verifyWebTokenNoThrow(publicKey, headerName) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
162
|
+
return function (req, res, next) {
|
|
163
|
+
try {
|
|
164
|
+
validateAndExtractWebTokenObjectNoThrow(req, publicKey, headerName);
|
|
165
|
+
next();
|
|
166
|
+
} catch (err) {
|
|
167
|
+
next(err);
|
|
181
168
|
}
|
|
169
|
+
};
|
|
182
170
|
}
|
|
183
171
|
|
|
184
172
|
function verifyVisitorNoThrow(publicKey) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
173
|
+
return function (req, res, next) {
|
|
174
|
+
try {
|
|
175
|
+
validateAndExtractVisitorObjectNoThrow(req, publicKey);
|
|
176
|
+
next();
|
|
177
|
+
} catch (err) {
|
|
178
|
+
next(err);
|
|
192
179
|
}
|
|
180
|
+
};
|
|
193
181
|
}
|
|
194
182
|
|
|
195
183
|
function throwUsedTokenError() {
|
|
196
|
-
|
|
184
|
+
throw new Error('Used_Token');
|
|
197
185
|
}
|
|
198
186
|
|
|
199
187
|
/*********************
|
|
200
188
|
* Private functions *
|
|
201
189
|
*********************/
|
|
202
190
|
function _isLoginRequired(hasRequiredRole, customErrorFunction) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
191
|
+
if (!hasRequiredRole) {
|
|
192
|
+
throwError(customErrorFunction);
|
|
193
|
+
}
|
|
208
194
|
}
|
|
209
195
|
|
|
210
196
|
function _validateGenericNoThrow(req, headerName, extractor) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
197
|
+
let jwtRaw = req.get(headerName);
|
|
198
|
+
if (!jwtRaw) return null;
|
|
199
|
+
let jwt = extractor(jwtRaw);
|
|
200
|
+
return isJwtString(jwt) ? jwt : null;
|
|
215
201
|
}
|
|
216
202
|
|
|
217
203
|
function _validateGeneric(req, headerName, extractor, customErrorFunction) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
204
|
+
let jwtRaw = req.get(headerName);
|
|
205
|
+
let jwt = extractor(jwtRaw, customErrorFunction);
|
|
206
|
+
if (isJwtString(jwt)) return jwt;
|
|
207
|
+
throwError(customErrorFunction);
|
|
208
|
+
return null;
|
|
223
209
|
}
|
|
224
210
|
|
|
225
211
|
function _validateAndExtractGenericNoThrow(req, publicKey, validator, extractor, propertyName) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
} catch (err) {
|
|
236
|
-
if (req) req[propertyName] = null;
|
|
237
|
-
throw err;
|
|
212
|
+
try {
|
|
213
|
+
const jwtString = validator(req);
|
|
214
|
+
const isJwtSignatureValid = jwtVerifySignedToken(jwtString, publicKey);
|
|
215
|
+
|
|
216
|
+
if (jwtString && isJwtSignatureValid) {
|
|
217
|
+
extractor(req, jwtString);
|
|
218
|
+
} else {
|
|
219
|
+
req[propertyName] = null;
|
|
238
220
|
}
|
|
239
|
-
|
|
221
|
+
} catch (err) {
|
|
222
|
+
if (req) req[propertyName] = null;
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
225
|
+
return req;
|
|
240
226
|
}
|
|
241
227
|
|
|
242
228
|
function _extractGenericObjectNoThrow(req, jwt, attacher, propertyName) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
229
|
+
if (jwt && typeof jwt === 'string') {
|
|
230
|
+
const obj = jwtGetHeaderPayload(jwt);
|
|
231
|
+
attacher(obj);
|
|
232
|
+
req[propertyName] = obj;
|
|
233
|
+
} else {
|
|
234
|
+
if (req) req[propertyName] = null;
|
|
235
|
+
}
|
|
250
236
|
}
|
|
251
237
|
|
|
252
238
|
function _extractJwtObject(req, jwt, customErrorFunction) {
|
|
253
|
-
|
|
239
|
+
_extractJwtObjectNoThrow(req, jwt);
|
|
254
240
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
241
|
+
if (!req['jwt']) {
|
|
242
|
+
throwError(customErrorFunction);
|
|
243
|
+
}
|
|
258
244
|
}
|
|
259
245
|
|
|
260
246
|
function _extractJwtObjectNoThrow(req, jwt) {
|
|
261
|
-
|
|
247
|
+
_extractGenericObjectNoThrow(req, jwt, _attachJwtMethods, 'jwt');
|
|
262
248
|
}
|
|
263
249
|
|
|
264
250
|
function _extractVisitorObjectNoThrow(req, jwt) {
|
|
265
|
-
|
|
251
|
+
_extractGenericObjectNoThrow(req, jwt, _attachVisitorMethods, 'visitor');
|
|
266
252
|
}
|
|
267
253
|
|
|
268
254
|
function _attachJwtMethods(jwtObj) {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
255
|
+
if (jwtObj) {
|
|
256
|
+
Object.defineProperties(jwtObj, {
|
|
257
|
+
jwtClientId: { value: jwtClientId, enumerable: false },
|
|
258
|
+
doesJwtUserHasRole: { value: doesJwtUserHasRole, enumerable: false },
|
|
259
|
+
isJwtExpired: { value: isJwtExpired, enumerable: false },
|
|
260
|
+
jwtAgeInSeconds: { value: jwtAgeInSeconds, enumerable: false },
|
|
261
|
+
});
|
|
262
|
+
}
|
|
277
263
|
}
|
|
278
264
|
|
|
279
265
|
function _attachVisitorMethods(visitorObj) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
266
|
+
if (visitorObj) {
|
|
267
|
+
Object.defineProperties(visitorObj, {
|
|
268
|
+
visitorClientId: { value: visitorClientId, enumerable: false },
|
|
269
|
+
});
|
|
270
|
+
}
|
|
285
271
|
}
|
|
286
272
|
|
|
287
273
|
async function _isJwtSignatureValid(jwt, publicKey, customErrorFunction) {
|
|
274
|
+
const isValid = await _isJwtSignatureValidNoThrow(jwt, publicKey);
|
|
288
275
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
throwError(customErrorFunction);
|
|
295
|
-
}
|
|
276
|
+
if (isValid) {
|
|
277
|
+
return isValid;
|
|
278
|
+
} else {
|
|
279
|
+
throwError(customErrorFunction);
|
|
280
|
+
}
|
|
296
281
|
}
|
|
297
282
|
|
|
298
283
|
async function _isJwtSignatureValidNoThrow(jwt, publicKey) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
284
|
+
if (jwt && typeof jwt === 'string') {
|
|
285
|
+
return jwtVerifySignedToken(jwt, publicKey);
|
|
286
|
+
} else {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
305
289
|
}
|
|
306
290
|
|
|
307
291
|
function _validateJwt(req, customErrorFunction) {
|
|
308
|
-
|
|
292
|
+
return _validateGeneric(req, 'Authorization', _extractJwt, customErrorFunction);
|
|
309
293
|
}
|
|
310
294
|
|
|
311
295
|
function _validateWebToken(req, headerName, customErrorFunction) {
|
|
312
|
-
|
|
296
|
+
return _validateGeneric(req, headerName, _extractWebToken, customErrorFunction);
|
|
313
297
|
}
|
|
314
298
|
|
|
315
299
|
function _validateJwtNoThrow(req) {
|
|
316
|
-
|
|
300
|
+
return _validateGenericNoThrow(req, 'Authorization', _extractJwtNoThrow);
|
|
317
301
|
}
|
|
318
302
|
|
|
319
303
|
function _validateWebTokenNoThrow(req, headerName) {
|
|
320
|
-
|
|
304
|
+
return _validateGenericNoThrow(req, headerName, _extractWebTokenNoThrow);
|
|
321
305
|
}
|
|
322
306
|
|
|
323
307
|
function _validateVisitorNoThrow(req) {
|
|
324
|
-
|
|
308
|
+
return _validateGenericNoThrow(req, 'Visitor', _extractJwtNoThrow);
|
|
325
309
|
}
|
|
326
310
|
|
|
327
311
|
function _extractJwt(jwtRaw, customErrorFunction) {
|
|
328
|
-
|
|
312
|
+
const jwt = _extractJwtNoThrow(jwtRaw);
|
|
329
313
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
314
|
+
if (jwt !== null) {
|
|
315
|
+
return jwt;
|
|
316
|
+
} else {
|
|
317
|
+
throwError(customErrorFunction);
|
|
318
|
+
}
|
|
335
319
|
|
|
336
|
-
|
|
320
|
+
return null;
|
|
337
321
|
}
|
|
338
322
|
|
|
339
323
|
function _extractWebToken(jwtRaw, customErrorFunction) {
|
|
340
|
-
|
|
324
|
+
const webToken = _extractWebTokenNoThrow(jwtRaw);
|
|
341
325
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
326
|
+
if (webToken !== null) {
|
|
327
|
+
return webToken;
|
|
328
|
+
} else {
|
|
329
|
+
throwError(customErrorFunction);
|
|
330
|
+
}
|
|
347
331
|
|
|
348
|
-
|
|
332
|
+
return null;
|
|
349
333
|
}
|
|
350
334
|
|
|
351
335
|
function _extractJwtNoThrow(jwtRaw) {
|
|
352
|
-
|
|
336
|
+
let jwtSplit = null;
|
|
353
337
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
338
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
339
|
+
jwtSplit = jwtRaw.split(' ');
|
|
340
|
+
} else {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
359
343
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
344
|
+
if (jwtSplit[0]?.toLowerCase() === 'bearer') {
|
|
345
|
+
return jwtSplit[1];
|
|
346
|
+
}
|
|
363
347
|
|
|
364
|
-
|
|
348
|
+
return null;
|
|
365
349
|
}
|
|
366
350
|
|
|
367
351
|
function _extractWebTokenNoThrow(jwtRaw) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return null;
|
|
352
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
353
|
+
return jwtRaw;
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
373
356
|
}
|
|
374
357
|
|
|
375
358
|
module.exports = {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
359
|
+
_validateJwt,
|
|
360
|
+
_validateJwtNoThrow,
|
|
361
|
+
_isJwtSignatureValid,
|
|
362
|
+
_isJwtSignatureValidNoThrow,
|
|
363
|
+
_extractJwtObject,
|
|
364
|
+
validateAndExtractJwtObject,
|
|
365
|
+
validateAndExtractWebToken,
|
|
366
|
+
jwtAgeInSeconds,
|
|
367
|
+
isJwtExpired,
|
|
368
|
+
doesJwtUserHasRole,
|
|
369
|
+
jwtClientId,
|
|
370
|
+
visitorClientId,
|
|
371
|
+
verifyJwtAndRole,
|
|
372
|
+
verifyJwt,
|
|
373
|
+
verifyWebTokenNoThrow,
|
|
374
|
+
verifyWebToken,
|
|
375
|
+
verifyJwtNoThrow,
|
|
376
|
+
throwUsedTokenError,
|
|
377
|
+
throwError,
|
|
378
|
+
verifyVisitorNoThrow,
|
|
379
|
+
validateAndExtractVisitorObjectNoThrow,
|
|
380
|
+
validateAndExtractJwtObjectNoThrow,
|
|
381
|
+
validateAndExtractWebTokenObjectNoThrow,
|
|
382
|
+
_extractJwtNoThrow,
|
|
383
|
+
_extractWebTokenNoThrow,
|
|
384
|
+
_extractJwt,
|
|
385
|
+
_validateWebTokenNoThrow,
|
|
386
|
+
_validateVisitorNoThrow,
|
|
387
|
+
_extractJwtObjectNoThrow,
|
|
388
|
+
_extractVisitorObjectNoThrow,
|
|
389
|
+
_extractWebToken,
|
|
390
|
+
_isLoginRequired,
|
|
391
|
+
_attachJwtMethods,
|
|
392
|
+
_attachVisitorMethods,
|
|
393
|
+
_validateWebToken,
|
|
394
|
+
};
|
package/lib/jwtRoles.js
CHANGED
|
@@ -1,20 +1,39 @@
|
|
|
1
|
+
const { jwtClientId } = require('./jwtLib');
|
|
2
|
+
|
|
1
3
|
module.exports = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
+
getNameOfRoleFromCode,
|
|
5
|
+
getCodeFromNameOfRole,
|
|
6
|
+
getContext,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function getNameOfRoleFromCode(roleCode) {
|
|
10
|
+
const codesToCategory = {
|
|
11
|
+
ad: 'admin',
|
|
12
|
+
su: 'super_admin',
|
|
13
|
+
};
|
|
14
|
+
return codesToCategory[roleCode] || '';
|
|
4
15
|
}
|
|
5
16
|
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
17
|
+
function getCodeFromNameOfRole(roleName) {
|
|
18
|
+
const namesToCode = {
|
|
19
|
+
admin: 'ad',
|
|
20
|
+
super_admin: 'su',
|
|
21
|
+
};
|
|
22
|
+
return namesToCode[roleName] || '';
|
|
12
23
|
}
|
|
13
24
|
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
25
|
+
function getContext(req) {
|
|
26
|
+
const userId = jwtClientId(req);
|
|
27
|
+
const roles = req.jwt?.payload?.roles;
|
|
28
|
+
|
|
29
|
+
if (Array.isArray(roles) && roles.includes('ad')) {
|
|
30
|
+
return {
|
|
31
|
+
user_id: userId,
|
|
32
|
+
role: 'super_admin',
|
|
18
33
|
};
|
|
19
|
-
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
user_id: userId,
|
|
38
|
+
};
|
|
20
39
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carecard/jwt-read",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.14",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/CareCard-ca/pkg-jwt-read.git"
|
|
@@ -9,10 +9,15 @@
|
|
|
9
9
|
"main": "index.js",
|
|
10
10
|
"types": "index.d.ts",
|
|
11
11
|
"scripts": {
|
|
12
|
-
"test": "
|
|
12
|
+
"test": "mocha --recursive",
|
|
13
13
|
"test:types": "tsc --noEmit && mocha -r ts-node/register test/types.test.ts",
|
|
14
|
-
"test:coverage": "tsc --noEmit &&
|
|
15
|
-
"
|
|
14
|
+
"test:coverage": "tsc --noEmit && nyc mocha --recursive -r ts-node/register 'test/**/*.{js,ts}'",
|
|
15
|
+
"test:All": "npm run test && npm run test:types",
|
|
16
|
+
"format": "prettier --write .",
|
|
17
|
+
"format:check": "prettier --check .",
|
|
18
|
+
"prepare": "husky",
|
|
19
|
+
"lint:fix": "eslint --fix",
|
|
20
|
+
"lint": "eslint"
|
|
16
21
|
},
|
|
17
22
|
"keywords": [
|
|
18
23
|
"auth",
|
|
@@ -25,16 +30,19 @@
|
|
|
25
30
|
"devDependencies": {
|
|
26
31
|
"@types/express": "5.0.6",
|
|
27
32
|
"@types/mocha": "10.0.10",
|
|
28
|
-
"@types/node": "25.
|
|
29
|
-
"
|
|
33
|
+
"@types/node": "25.6.2",
|
|
34
|
+
"eslint": "9.39.4",
|
|
35
|
+
"husky": "9.1.7",
|
|
36
|
+
"lint-staged": "17.0.3",
|
|
30
37
|
"mocha": "11.7.5",
|
|
31
|
-
"nyc": "
|
|
38
|
+
"nyc": "18.0.0",
|
|
39
|
+
"prettier": "3.8.3",
|
|
32
40
|
"ts-node": "10.9.2",
|
|
33
41
|
"typescript": "5.9.3"
|
|
34
42
|
},
|
|
35
43
|
"dependencies": {
|
|
36
|
-
"@carecard/common-util": "3.1.
|
|
37
|
-
"@carecard/auth-util": "3.1.
|
|
38
|
-
"@carecard/validate": "3.
|
|
44
|
+
"@carecard/common-util": "3.1.13",
|
|
45
|
+
"@carecard/auth-util": "3.1.13",
|
|
46
|
+
"@carecard/validate": "3.1.16"
|
|
39
47
|
}
|
|
40
48
|
}
|
package/readme.md
CHANGED
|
@@ -31,11 +31,11 @@ const verifyAdmin = verifyJwtAndRole('admin', publicKey, throwUsedTokenError);
|
|
|
31
31
|
|
|
32
32
|
// In an Express controller/middleware
|
|
33
33
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
await verifyAdmin(req, res, next);
|
|
35
|
+
// If successful, req.jwt contains { header, payload }
|
|
36
|
+
console.log(req.jwt.payload.sub);
|
|
37
37
|
} catch (error) {
|
|
38
|
-
|
|
38
|
+
// Handle verification error
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
@@ -46,7 +46,7 @@ const { verifyJwt, isJwtExpired } = require('@carecard/jwt-read');
|
|
|
46
46
|
|
|
47
47
|
const result = verifyJwt(rawJwt, publicKey);
|
|
48
48
|
if (result && !isJwtExpired(result)) {
|
|
49
|
-
|
|
49
|
+
console.log('JWT is valid and not expired:', result.payload);
|
|
50
50
|
}
|
|
51
51
|
```
|
|
52
52
|
|
|
@@ -82,6 +82,7 @@ npm run test:types
|
|
|
82
82
|
## Architecture
|
|
83
83
|
|
|
84
84
|
The package is organized into several modules:
|
|
85
|
+
|
|
85
86
|
- `jwtLib`: Main logic for JWT verification, extraction, and Express integration.
|
|
86
87
|
- `jwtRoles`: Role mapping between internal codes and names.
|
|
87
88
|
|