@carecard/jwt-read 3.0.1 → 3.0.3
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/index.d.ts +78 -0
- package/lib/jwtLib.js +25 -19
- package/lib/jwtRoles.js +5 -5
- package/package.json +12 -6
package/index.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for reading and verifying JWTs.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Verifies a JWT from the 'Authorization: Bearer <token>' header and extracts it into req.jwt.
|
|
7
|
+
* Throws an error if invalid.
|
|
8
|
+
*/
|
|
9
|
+
export function verifyJwt(req: any, publicKey: string, customErrorFunction?: () => void): Promise<any>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Verifies a JWT from a custom header and extracts it into req.jwt.
|
|
13
|
+
* Throws an error if invalid.
|
|
14
|
+
*/
|
|
15
|
+
export function verifyWebToken(req: any, publicKey: string, headerName: string, customErrorFunction?: () => void): Promise<any>;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Verifies a JWT from the 'Authorization: Bearer <token>' header and extracts it into req.jwt.
|
|
19
|
+
* Returns false instead of throwing if invalid.
|
|
20
|
+
*/
|
|
21
|
+
export function verifyJwtNoThrow(req: any, publicKey: string): Promise<boolean>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Verifies a JWT from a custom header and extracts it into req.jwt.
|
|
25
|
+
* Returns false instead of throwing if invalid.
|
|
26
|
+
*/
|
|
27
|
+
export function verifyWebTokenNoThrow(req: any, publicKey: string, headerName: string): Promise<boolean>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Verifies a visitor token from the 'x-visitor-token' header and extracts it into req.visitor.
|
|
31
|
+
* Returns false instead of throwing if invalid.
|
|
32
|
+
*/
|
|
33
|
+
export function verifyVisitorNoThrow(req: any, publicKey: string): Promise<boolean>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Returns the client_id from the extracted JWT in req.jwt.
|
|
37
|
+
*/
|
|
38
|
+
export function jwtClientId(req: any): string | undefined;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns the client_id from the extracted visitor token in req.visitor.
|
|
42
|
+
*/
|
|
43
|
+
export function visitorClientId(req: any): string | undefined;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Checks if the extracted JWT in req.jwt has expired.
|
|
47
|
+
*/
|
|
48
|
+
export function isJwtExpired(req: any, jwtValiditySeconds?: number): boolean;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Returns the age of the extracted JWT in seconds.
|
|
52
|
+
*/
|
|
53
|
+
export function jwtAgeInSeconds(req: any): number;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Verifies the JWT and checks if the user has the required role.
|
|
57
|
+
*/
|
|
58
|
+
export function verifyJwtAndRole(req: any, publicKey: string, userRole: string, customErrorFunction?: () => void): Promise<any>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Throws a Used_Token error.
|
|
62
|
+
*/
|
|
63
|
+
export function throwUsedTokenError(): never;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Checks if the user in the extracted JWT has the specified role.
|
|
67
|
+
*/
|
|
68
|
+
export function doesJwtUserHasRole(req: any, userRole: string): boolean;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets the full name of a role from its code (e.g., 'ad' -> 'admin').
|
|
72
|
+
*/
|
|
73
|
+
export function getNameOfRole(roleCode: string): string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Gets the code of a role from its name (e.g., 'admin' -> 'ad').
|
|
77
|
+
*/
|
|
78
|
+
export function getCodeOfRole(roleName: string): string;
|
package/lib/jwtLib.js
CHANGED
|
@@ -44,6 +44,12 @@ function isJwtExpired( req, jwtValiditySeconds ) {
|
|
|
44
44
|
req = undefined;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
const jwtObj = req?.jwt || this;
|
|
48
|
+
|
|
49
|
+
if ( jwtObj?.payload?.exp ) {
|
|
50
|
+
return ( Math.floor( Date.now() / 1000 ) ) >= jwtObj.payload.exp;
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
if ( jwtValiditySeconds && typeof jwtValiditySeconds === "number" ) {
|
|
48
54
|
return ( parseInt( jwtValiditySeconds ) ) < jwtAgeInSeconds.call( this, req );
|
|
49
55
|
} else {
|
|
@@ -75,12 +81,12 @@ function jwtAgeInSeconds( req ) {
|
|
|
75
81
|
|
|
76
82
|
async function validateAndExtractJwtObject( req, publicKey, customErrorFunction ) {
|
|
77
83
|
|
|
78
|
-
const jwtString =
|
|
84
|
+
const jwtString = _validateJwt( req, customErrorFunction );
|
|
79
85
|
|
|
80
|
-
const isJwtSignatureValid =
|
|
86
|
+
const isJwtSignatureValid = jwtUtilAuth.verifyJwtSignature( jwtString, publicKey );
|
|
81
87
|
|
|
82
88
|
if ( jwtString && isJwtSignatureValid ) {
|
|
83
|
-
|
|
89
|
+
_extractJwtObject( req, jwtString, customErrorFunction );
|
|
84
90
|
} else {
|
|
85
91
|
req[ "jwt" ] = null;
|
|
86
92
|
throwError( customErrorFunction );
|
|
@@ -91,12 +97,12 @@ async function validateAndExtractJwtObject( req, publicKey, customErrorFunction
|
|
|
91
97
|
|
|
92
98
|
async function validateAndExtractWebToken( req, publicKey, headerName, customErrorFunction ) {
|
|
93
99
|
|
|
94
|
-
const webTokenString =
|
|
100
|
+
const webTokenString = _validateWebToken( req, headerName, customErrorFunction );
|
|
95
101
|
|
|
96
|
-
const isJwtSignatureValid =
|
|
102
|
+
const isJwtSignatureValid = jwtUtilAuth.verifyJwtSignature( webTokenString, publicKey );
|
|
97
103
|
|
|
98
104
|
if ( webTokenString && isJwtSignatureValid ) {
|
|
99
|
-
|
|
105
|
+
_extractJwtObject( req, webTokenString, customErrorFunction );
|
|
100
106
|
} else {
|
|
101
107
|
req[ "jwt" ] = null;
|
|
102
108
|
throwError( customErrorFunction );
|
|
@@ -109,12 +115,12 @@ async function validateAndExtractJwtObjectNoThrow( req, publicKey ) {
|
|
|
109
115
|
|
|
110
116
|
try {
|
|
111
117
|
|
|
112
|
-
const jwtString =
|
|
118
|
+
const jwtString = _validateJwtNoThrow( req );
|
|
113
119
|
|
|
114
|
-
const isJwtSignatureValid =
|
|
120
|
+
const isJwtSignatureValid = jwtUtilAuth.verifyJwtSignature( jwtString, publicKey );
|
|
115
121
|
|
|
116
122
|
if ( jwtString && isJwtSignatureValid ) {
|
|
117
|
-
|
|
123
|
+
_extractJwtObjectNoThrow( req, jwtString );
|
|
118
124
|
} else {
|
|
119
125
|
req[ "jwt" ] = null;
|
|
120
126
|
}
|
|
@@ -134,10 +140,10 @@ async function validateAndExtractWebTokenObjectNoThrow( req, publicKey, headerNa
|
|
|
134
140
|
|
|
135
141
|
const jwtString = _validateWebTokenNoThrow( req, headerName );
|
|
136
142
|
|
|
137
|
-
const isJwtSignatureValid =
|
|
143
|
+
const isJwtSignatureValid = jwtUtilAuth.verifyJwtSignature( jwtString, publicKey );
|
|
138
144
|
|
|
139
145
|
if ( jwtString && isJwtSignatureValid ) {
|
|
140
|
-
|
|
146
|
+
_extractJwtObjectNoThrow( req, jwtString );
|
|
141
147
|
} else {
|
|
142
148
|
req[ "jwt" ] = null;
|
|
143
149
|
}
|
|
@@ -155,12 +161,12 @@ async function validateAndExtractVisitorObjectNoThrow( req, publicKey ) {
|
|
|
155
161
|
|
|
156
162
|
try {
|
|
157
163
|
|
|
158
|
-
const jwtString =
|
|
164
|
+
const jwtString = _validateVisitorNoThrow( req );
|
|
159
165
|
|
|
160
|
-
const isJwtSignatureValid =
|
|
166
|
+
const isJwtSignatureValid = jwtUtilAuth.verifyJwtSignature( jwtString, publicKey );
|
|
161
167
|
|
|
162
168
|
if ( jwtString && isJwtSignatureValid ) {
|
|
163
|
-
|
|
169
|
+
_extractVisitorObjectNoThrow( req, jwtString );
|
|
164
170
|
} else {
|
|
165
171
|
req[ "visitor" ] = null;
|
|
166
172
|
}
|
|
@@ -239,7 +245,7 @@ function _isLoginRequired( hasRequiredRole, customErrorFunction ) {
|
|
|
239
245
|
|
|
240
246
|
}
|
|
241
247
|
|
|
242
|
-
|
|
248
|
+
function _extractJwtObject( req, jwt, customErrorFunction ) {
|
|
243
249
|
if ( jwt && typeof jwt === "string" ) {
|
|
244
250
|
const jwtObj = jwtUtilAuth.getHeaderPayloadFromJwt( jwt );
|
|
245
251
|
_attachJwtMethods( jwtObj );
|
|
@@ -249,7 +255,7 @@ async function _extractJwtObject( req, jwt, customErrorFunction ) {
|
|
|
249
255
|
}
|
|
250
256
|
}
|
|
251
257
|
|
|
252
|
-
|
|
258
|
+
function _extractJwtObjectNoThrow( req, jwt ) {
|
|
253
259
|
if ( jwt && typeof jwt === "string" ) {
|
|
254
260
|
const jwtObj = jwtUtilAuth.getHeaderPayloadFromJwt( jwt );
|
|
255
261
|
_attachJwtMethods( jwtObj );
|
|
@@ -259,7 +265,7 @@ async function _extractJwtObjectNoThrow( req, jwt ) {
|
|
|
259
265
|
}
|
|
260
266
|
}
|
|
261
267
|
|
|
262
|
-
|
|
268
|
+
function _extractVisitorObjectNoThrow( req, jwt ) {
|
|
263
269
|
if ( jwt && typeof jwt === "string" ) {
|
|
264
270
|
const visitorObj = jwtUtilAuth.getHeaderPayloadFromJwt( jwt );
|
|
265
271
|
_attachVisitorMethods( visitorObj );
|
|
@@ -306,7 +312,7 @@ async function _isJwtSignatureValidNoThrow( jwt, publicKey ) {
|
|
|
306
312
|
}
|
|
307
313
|
}
|
|
308
314
|
|
|
309
|
-
|
|
315
|
+
function _validateJwt( req, customErrorFunction ) {
|
|
310
316
|
|
|
311
317
|
// Get from http header.
|
|
312
318
|
let jwtRaw = req.get( "Authorization" );
|
|
@@ -322,7 +328,7 @@ async function _validateJwt( req, customErrorFunction ) {
|
|
|
322
328
|
}
|
|
323
329
|
}
|
|
324
330
|
|
|
325
|
-
|
|
331
|
+
function _validateWebToken( req, headerName, customErrorFunction ) {
|
|
326
332
|
|
|
327
333
|
// Get from http header.
|
|
328
334
|
let jwtRaw = req.get( headerName );
|
package/lib/jwtRoles.js
CHANGED
|
@@ -7,14 +7,14 @@ function getNameOfRoleFromCode( roleCode ) {
|
|
|
7
7
|
const codesToCategory = {
|
|
8
8
|
"ad": "admin",
|
|
9
9
|
"su": "super_admin",
|
|
10
|
-
}
|
|
10
|
+
};
|
|
11
11
|
return codesToCategory[ roleCode ] || "";
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function getCodeFromNameOfRole(
|
|
15
|
-
const
|
|
14
|
+
function getCodeFromNameOfRole( roleName ) {
|
|
15
|
+
const namesToCode = {
|
|
16
16
|
"admin": "ad",
|
|
17
17
|
"super_admin": "su",
|
|
18
|
-
}
|
|
19
|
-
return
|
|
18
|
+
};
|
|
19
|
+
return namesToCode[ roleName ] || "";
|
|
20
20
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carecard/jwt-read",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/CareCard-ca/pkg-jwt-read.git"
|
|
7
7
|
},
|
|
8
8
|
"description": "Jwt read functions",
|
|
9
9
|
"main": "index.js",
|
|
10
|
+
"types": "index.d.ts",
|
|
10
11
|
"scripts": {
|
|
11
|
-
"test": "export NODE_ENV=test && mocha --watch --recursive"
|
|
12
|
+
"test": "export NODE_ENV=test && mocha --watch --recursive",
|
|
13
|
+
"test:types": "tsc --noEmit && mocha -r ts-node/register test/types.test.ts"
|
|
12
14
|
},
|
|
13
15
|
"keywords": [
|
|
14
16
|
"auth",
|
|
@@ -18,11 +20,15 @@
|
|
|
18
20
|
"author": "CareCard team",
|
|
19
21
|
"license": "ISC",
|
|
20
22
|
"devDependencies": {
|
|
21
|
-
"mocha": "
|
|
23
|
+
"@types/mocha": "10.0.10",
|
|
24
|
+
"@types/node": "25.5.0",
|
|
25
|
+
"mocha": "11.7.5",
|
|
26
|
+
"ts-node": "10.9.2",
|
|
27
|
+
"typescript": "5.9.3"
|
|
22
28
|
},
|
|
23
29
|
"dependencies": {
|
|
24
|
-
"@carecard/auth-util": "3.0.
|
|
25
|
-
"@carecard/common-util": "
|
|
26
|
-
"@carecard/validate": "
|
|
30
|
+
"@carecard/auth-util": "3.0.3",
|
|
31
|
+
"@carecard/common-util": "3.0.3",
|
|
32
|
+
"@carecard/validate": "3.0.3"
|
|
27
33
|
}
|
|
28
34
|
}
|