@carecard/jwt-read 1.0.0
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/dist/cjs/index.cjs +19 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/jwtLib.cjs +393 -0
- package/dist/cjs/jwtLib.d.ts +38 -0
- package/dist/cjs/jwtRoles.cjs +19 -0
- package/dist/cjs/jwtRoles.d.ts +2 -0
- package/dist/cjs/types.cjs +2 -0
- package/dist/cjs/types.d.ts +25 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/jwtLib.d.ts +38 -0
- package/dist/esm/jwtLib.js +325 -0
- package/dist/esm/jwtRoles.d.ts +2 -0
- package/dist/esm/jwtRoles.js +15 -0
- package/dist/esm/types.d.ts +25 -0
- package/dist/esm/types.js +1 -0
- package/package.json +61 -0
- package/readme.md +30 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./jwtLib"), exports);
|
|
18
|
+
__exportStar(require("./jwtRoles"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.jwtClientId = jwtClientId;
|
|
37
|
+
exports.visitorClientId = visitorClientId;
|
|
38
|
+
exports.doesJwtUserHasRole = doesJwtUserHasRole;
|
|
39
|
+
exports.throwError = throwError;
|
|
40
|
+
exports.isJwtExpired = isJwtExpired;
|
|
41
|
+
exports.jwtAgeInMilliseconds = jwtAgeInMilliseconds;
|
|
42
|
+
exports.validateAndExtractJwtObject = validateAndExtractJwtObject;
|
|
43
|
+
exports.validateAndExtractWebToken = validateAndExtractWebToken;
|
|
44
|
+
exports.validateAndExtractJwtObjectNoThrow = validateAndExtractJwtObjectNoThrow;
|
|
45
|
+
exports.validateAndExtractWebTokenObjectNoThrow = validateAndExtractWebTokenObjectNoThrow;
|
|
46
|
+
exports.validateAndExtractVisitorObjectNoThrow = validateAndExtractVisitorObjectNoThrow;
|
|
47
|
+
exports.verifyJwtAndRole = verifyJwtAndRole;
|
|
48
|
+
exports.verifyJwt = verifyJwt;
|
|
49
|
+
exports.verifyWebToken = verifyWebToken;
|
|
50
|
+
exports.verifyJwtNoThrow = verifyJwtNoThrow;
|
|
51
|
+
exports.verifyWebTokenNoThrow = verifyWebTokenNoThrow;
|
|
52
|
+
exports.verifyVisitorNoThrow = verifyVisitorNoThrow;
|
|
53
|
+
exports.throwUsedTokenError = throwUsedTokenError;
|
|
54
|
+
exports._isLoginRequired = _isLoginRequired;
|
|
55
|
+
exports._extractJwtObject = _extractJwtObject;
|
|
56
|
+
exports._extractJwtObjectNoThrow = _extractJwtObjectNoThrow;
|
|
57
|
+
exports._extractVisitorObjectNoThrow = _extractVisitorObjectNoThrow;
|
|
58
|
+
exports._isJwtSignatureValid = _isJwtSignatureValid;
|
|
59
|
+
exports._isJwtSignatureValidNoThrow = _isJwtSignatureValidNoThrow;
|
|
60
|
+
exports._validateJwt = _validateJwt;
|
|
61
|
+
exports._validateWebToken = _validateWebToken;
|
|
62
|
+
exports._validateJwtNoThrow = _validateJwtNoThrow;
|
|
63
|
+
exports._validateWebTokenNoThrow = _validateWebTokenNoThrow;
|
|
64
|
+
exports._validateVisitorNoThrow = _validateVisitorNoThrow;
|
|
65
|
+
exports._extractJwt = _extractJwt;
|
|
66
|
+
exports._extractWebToken = _extractWebToken;
|
|
67
|
+
exports._extractJwtNoThrow = _extractJwtNoThrow;
|
|
68
|
+
exports._extractWebTokenNoThrow = _extractWebTokenNoThrow;
|
|
69
|
+
const validate = __importStar(require("@carecard/validate"));
|
|
70
|
+
const jwtUtilAuth = __importStar(require("@carecard/auth-util"));
|
|
71
|
+
const common_util_1 = require("@carecard/common-util");
|
|
72
|
+
function jwtClientId(req) {
|
|
73
|
+
return req?.jwt?.payload?.client_id;
|
|
74
|
+
}
|
|
75
|
+
function visitorClientId(req) {
|
|
76
|
+
return req?.visitor?.payload?.client_id;
|
|
77
|
+
}
|
|
78
|
+
function doesJwtUserHasRole(req, userRole) {
|
|
79
|
+
if (userRole && typeof userRole === 'string') {
|
|
80
|
+
return req?.jwt?.payload?.roles?.includes(userRole);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
(0, common_util_1.throwNotAuthorizedError)();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function throwError(customErrorFunction) {
|
|
87
|
+
typeof customErrorFunction === 'function' ? customErrorFunction() : (0, common_util_1.throwLoginRequiredError)();
|
|
88
|
+
}
|
|
89
|
+
function isJwtExpired(req, jwtValiditySeconds) {
|
|
90
|
+
if (jwtValiditySeconds && typeof jwtValiditySeconds === 'number') {
|
|
91
|
+
return Math.abs(Math.round(jwtValiditySeconds)) * 1000 < jwtAgeInMilliseconds(req);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function jwtAgeInMilliseconds(req) {
|
|
98
|
+
// Ensure req.jwt exists (create it if undefined)
|
|
99
|
+
req.jwt ?? (req.jwt = {
|
|
100
|
+
header: { alg: 'sha512', typ: 'JWT' }, // or a minimal placeholder
|
|
101
|
+
payload: { iat: 0, client_id: '', roles: [], email_not_confirmed: false },
|
|
102
|
+
age: Infinity,
|
|
103
|
+
});
|
|
104
|
+
const iat = req.jwt.payload?.iat;
|
|
105
|
+
const age = typeof iat === 'number' && iat > 0 ? Date.now() - iat : Infinity;
|
|
106
|
+
req.jwt.age = age;
|
|
107
|
+
return age;
|
|
108
|
+
}
|
|
109
|
+
async function validateAndExtractJwtObject(req, publicKey, customErrorFunction) {
|
|
110
|
+
const jwtString = await _validateJwt(req, customErrorFunction);
|
|
111
|
+
const isJwtSignatureValid = await _isJwtSignatureValid(jwtString, publicKey, customErrorFunction);
|
|
112
|
+
if (jwtString && isJwtSignatureValid) {
|
|
113
|
+
await _extractJwtObject(req, jwtString, customErrorFunction);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
req['jwt'] = null;
|
|
117
|
+
throwError(customErrorFunction);
|
|
118
|
+
}
|
|
119
|
+
return req;
|
|
120
|
+
}
|
|
121
|
+
async function validateAndExtractWebToken(req, publicKey, headerName, customErrorFunction) {
|
|
122
|
+
const webTokenString = await _validateWebToken(req, headerName, customErrorFunction);
|
|
123
|
+
const isJwtSignatureValid = await _isJwtSignatureValid(webTokenString, publicKey, customErrorFunction);
|
|
124
|
+
if (webTokenString && isJwtSignatureValid) {
|
|
125
|
+
await _extractJwtObject(req, webTokenString, customErrorFunction);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
req['jwt'] = null;
|
|
129
|
+
throwError(customErrorFunction);
|
|
130
|
+
}
|
|
131
|
+
return req;
|
|
132
|
+
}
|
|
133
|
+
async function validateAndExtractJwtObjectNoThrow(req, publicKey) {
|
|
134
|
+
try {
|
|
135
|
+
const jwtString = await _validateJwtNoThrow(req);
|
|
136
|
+
const isJwtSignatureValid = await _isJwtSignatureValidNoThrow(jwtString, publicKey);
|
|
137
|
+
if (jwtString && isJwtSignatureValid) {
|
|
138
|
+
await _extractJwtObjectNoThrow(req, jwtString);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
req['jwt'] = null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
req['jwt'] = null;
|
|
146
|
+
}
|
|
147
|
+
return req;
|
|
148
|
+
}
|
|
149
|
+
async function validateAndExtractWebTokenObjectNoThrow(req, publicKey, headerName) {
|
|
150
|
+
try {
|
|
151
|
+
const jwtString = _validateWebTokenNoThrow(req, headerName);
|
|
152
|
+
const isJwtSignatureValid = await _isJwtSignatureValidNoThrow(jwtString, publicKey);
|
|
153
|
+
if (jwtString && isJwtSignatureValid) {
|
|
154
|
+
await _extractJwtObjectNoThrow(req, jwtString);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
req['jwt'] = null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
req['jwt'] = null;
|
|
162
|
+
}
|
|
163
|
+
return req;
|
|
164
|
+
}
|
|
165
|
+
async function validateAndExtractVisitorObjectNoThrow(req, publicKey) {
|
|
166
|
+
try {
|
|
167
|
+
const jwtString = await _validateVisitorNoThrow(req);
|
|
168
|
+
const isJwtSignatureValid = await _isJwtSignatureValidNoThrow(jwtString, publicKey);
|
|
169
|
+
if (jwtString && isJwtSignatureValid) {
|
|
170
|
+
await _extractVisitorObjectNoThrow(req, jwtString);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
req['visitor'] = null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
req['visitor'] = null;
|
|
178
|
+
}
|
|
179
|
+
return req;
|
|
180
|
+
}
|
|
181
|
+
function verifyJwtAndRole(role, publicKey, customErrorFunction) {
|
|
182
|
+
return async function (req, res, next) {
|
|
183
|
+
await validateAndExtractJwtObject(req, publicKey, customErrorFunction)
|
|
184
|
+
.then(req => doesJwtUserHasRole(req, role))
|
|
185
|
+
.then(isRoleExist => _isLoginRequired(isRoleExist, customErrorFunction))
|
|
186
|
+
.then(next)
|
|
187
|
+
.catch(next);
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function verifyJwt(publicKey, customErrorFunction) {
|
|
191
|
+
return async function (req, res, next) {
|
|
192
|
+
await validateAndExtractJwtObject(req, publicKey, customErrorFunction)
|
|
193
|
+
.then(() => process.nextTick(next))
|
|
194
|
+
.catch(next);
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function verifyWebToken(publicKey, headerName, customErrorFunction) {
|
|
198
|
+
return async function (req, res, next) {
|
|
199
|
+
await validateAndExtractWebToken(req, publicKey, headerName, customErrorFunction)
|
|
200
|
+
.then(() => process.nextTick(next))
|
|
201
|
+
.catch(next);
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function verifyJwtNoThrow(publicKey) {
|
|
205
|
+
return async function (req, res, next) {
|
|
206
|
+
await validateAndExtractJwtObjectNoThrow(req, publicKey)
|
|
207
|
+
.then(() => process.nextTick(next))
|
|
208
|
+
.catch(next);
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function verifyWebTokenNoThrow(publicKey, headerName) {
|
|
212
|
+
return async function (req, res, next) {
|
|
213
|
+
await validateAndExtractWebTokenObjectNoThrow(req, publicKey, headerName)
|
|
214
|
+
.then(() => process.nextTick(next))
|
|
215
|
+
.catch(next);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function verifyVisitorNoThrow(publicKey) {
|
|
219
|
+
return async function (req, res, next) {
|
|
220
|
+
await validateAndExtractVisitorObjectNoThrow(req, publicKey)
|
|
221
|
+
.then(() => process.nextTick(next))
|
|
222
|
+
.catch(next);
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function throwUsedTokenError() {
|
|
226
|
+
throw new Error('Used_Token');
|
|
227
|
+
}
|
|
228
|
+
/*********************
|
|
229
|
+
* Private functions *
|
|
230
|
+
*********************/
|
|
231
|
+
function _isLoginRequired(hasRequiredRole, customErrorFunction) {
|
|
232
|
+
if (!hasRequiredRole) {
|
|
233
|
+
throwError(customErrorFunction);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function _extractJwtObject(req, jwt, customErrorFunction) {
|
|
237
|
+
if (jwt && typeof jwt === 'string') {
|
|
238
|
+
req['jwt'] = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
throwError(customErrorFunction);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async function _extractJwtObjectNoThrow(req, jwt) {
|
|
245
|
+
if (jwt && typeof jwt === 'string') {
|
|
246
|
+
req['jwt'] = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
req['jwt'] = null;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function _extractVisitorObjectNoThrow(req, jwt) {
|
|
253
|
+
if (jwt && typeof jwt === 'string') {
|
|
254
|
+
req['visitor'] = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
req['visitor'] = null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async function _isJwtSignatureValid(jwt, publicKey, customErrorFunction) {
|
|
261
|
+
if (jwt && typeof jwt === 'string') {
|
|
262
|
+
return jwtUtilAuth.verifyJwtSignature(jwt, publicKey);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
throwError(customErrorFunction);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
async function _isJwtSignatureValidNoThrow(jwt, publicKey) {
|
|
269
|
+
if (jwt && typeof jwt === 'string') {
|
|
270
|
+
return jwtUtilAuth.verifyJwtSignature(jwt, publicKey);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async function _validateJwt(req, customErrorFunction) {
|
|
277
|
+
// Get from http header.
|
|
278
|
+
let jwtRaw = req.get('Authorization');
|
|
279
|
+
// Extract jwt from bearer schema.
|
|
280
|
+
let jwt = _extractJwt(jwtRaw, customErrorFunction);
|
|
281
|
+
// Validate characters string of jwt.
|
|
282
|
+
if (validate.isJwtString(jwt || '')) {
|
|
283
|
+
return jwt;
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
throwError(customErrorFunction);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async function _validateWebToken(req, headerName, customErrorFunction) {
|
|
290
|
+
// Get from http header.
|
|
291
|
+
let jwtRaw = req.get(headerName);
|
|
292
|
+
// Extract jwt from bearer schema.
|
|
293
|
+
let webToken = _extractWebToken(jwtRaw, customErrorFunction);
|
|
294
|
+
// Validate characters string of jwt.
|
|
295
|
+
if (validate.isJwtString(webToken || '')) {
|
|
296
|
+
return webToken;
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
throwError(customErrorFunction);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function _validateJwtNoThrow(req) {
|
|
303
|
+
// Get from http header.
|
|
304
|
+
let jwtRaw = req.get('Authorization');
|
|
305
|
+
if (!jwtRaw) {
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
// Extract jwt from bearer schema.
|
|
309
|
+
let jwt = _extractJwtNoThrow(jwtRaw);
|
|
310
|
+
// Validate characters string of jwt.
|
|
311
|
+
if (validate.isJwtString(jwt || '')) {
|
|
312
|
+
return jwt;
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
function _validateWebTokenNoThrow(req, headerName) {
|
|
317
|
+
// Get from http header.
|
|
318
|
+
let jwtRaw = req.get(headerName);
|
|
319
|
+
if (!jwtRaw) {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
// Extract jwt from bearer schema.
|
|
323
|
+
let webToken = _extractWebTokenNoThrow(jwtRaw);
|
|
324
|
+
// Validate characters string of jwt.
|
|
325
|
+
if (validate.isJwtString(webToken || '')) {
|
|
326
|
+
return webToken;
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
function _validateVisitorNoThrow(req) {
|
|
331
|
+
// Get from http header.
|
|
332
|
+
let jwtRaw = req.get('Visitor');
|
|
333
|
+
if (!jwtRaw) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
// Extract jwt from bearer schema.
|
|
337
|
+
let jwt = _extractJwtNoThrow(jwtRaw);
|
|
338
|
+
// Validate characters string of jwt.
|
|
339
|
+
if (validate.isJwtString(jwt || '')) {
|
|
340
|
+
return jwt;
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
function _extractJwt(jwtRaw, customErrorFunction) {
|
|
345
|
+
let jwtSplit = null;
|
|
346
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
347
|
+
jwtSplit = jwtRaw.split(' ');
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
throwError(customErrorFunction);
|
|
351
|
+
return null;
|
|
352
|
+
}
|
|
353
|
+
// Guard before indexing
|
|
354
|
+
if (!jwtSplit || jwtSplit.length < 2) {
|
|
355
|
+
throwError(customErrorFunction);
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
if (jwtSplit[0].toLowerCase() === 'bearer') {
|
|
359
|
+
return jwtSplit[1] ?? null;
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
throwError(customErrorFunction);
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function _extractWebToken(jwtRaw, customErrorFunction) {
|
|
367
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
368
|
+
return jwtRaw;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
throwError(customErrorFunction);
|
|
372
|
+
}
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
function _extractJwtNoThrow(jwtRaw) {
|
|
376
|
+
let jwtSplit = null;
|
|
377
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
378
|
+
jwtSplit = jwtRaw.split(' ');
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
if (jwtSplit[0]?.toLowerCase() === 'bearer') {
|
|
384
|
+
return jwtSplit[1];
|
|
385
|
+
}
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
function _extractWebTokenNoThrow(jwtRaw) {
|
|
389
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
390
|
+
return jwtRaw;
|
|
391
|
+
}
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Response, NextFunction } from 'express';
|
|
2
|
+
import { RequestWithJWToken, Role } from './types';
|
|
3
|
+
export declare function jwtClientId(req: RequestWithJWToken): string | undefined;
|
|
4
|
+
export declare function visitorClientId(req: RequestWithJWToken): string | undefined;
|
|
5
|
+
export declare function doesJwtUserHasRole(req: RequestWithJWToken, userRole: Role): boolean | undefined;
|
|
6
|
+
export declare function throwError(customErrorFunction?: any): void;
|
|
7
|
+
export declare function isJwtExpired(req: RequestWithJWToken, jwtValiditySeconds: number): boolean;
|
|
8
|
+
export declare function jwtAgeInMilliseconds(req: RequestWithJWToken): number;
|
|
9
|
+
export declare function validateAndExtractJwtObject(req: RequestWithJWToken, publicKey: string, customErrorFunction?: any): Promise<any>;
|
|
10
|
+
export declare function validateAndExtractWebToken(req: RequestWithJWToken, publicKey: string, headerName: string, customErrorFunction?: any): Promise<any>;
|
|
11
|
+
export declare function validateAndExtractJwtObjectNoThrow(req: RequestWithJWToken, publicKey: string): Promise<any>;
|
|
12
|
+
export declare function validateAndExtractWebTokenObjectNoThrow(req: RequestWithJWToken, publicKey: string, headerName: string): Promise<any>;
|
|
13
|
+
export declare function validateAndExtractVisitorObjectNoThrow(req: RequestWithJWToken, publicKey: string): Promise<any>;
|
|
14
|
+
export declare function verifyJwtAndRole(role: Role, publicKey: string, customErrorFunction?: any): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<any>;
|
|
15
|
+
export declare function verifyJwt(publicKey: string, customErrorFunction?: any): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<any>;
|
|
16
|
+
export declare function verifyWebToken(publicKey: string, headerName: string, customErrorFunction?: any): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<any>;
|
|
17
|
+
export declare function verifyJwtNoThrow(publicKey: string): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<void>;
|
|
18
|
+
export declare function verifyWebTokenNoThrow(publicKey: string, headerName: string): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<void>;
|
|
19
|
+
export declare function verifyVisitorNoThrow(publicKey: string): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<void>;
|
|
20
|
+
export declare function throwUsedTokenError(): void;
|
|
21
|
+
/*********************
|
|
22
|
+
* Private functions *
|
|
23
|
+
*********************/
|
|
24
|
+
export declare function _isLoginRequired(hasRequiredRole: boolean | undefined, customErrorFunction?: any): void;
|
|
25
|
+
export declare function _extractJwtObject(req: RequestWithJWToken, jwt: string, customErrorFunction?: any): Promise<any>;
|
|
26
|
+
export declare function _extractJwtObjectNoThrow(req: RequestWithJWToken, jwt: string): Promise<any>;
|
|
27
|
+
export declare function _extractVisitorObjectNoThrow(req: RequestWithJWToken, jwt: string): Promise<any>;
|
|
28
|
+
export declare function _isJwtSignatureValid(jwt: string, publicKey: string, customErrorFunction?: any): Promise<any>;
|
|
29
|
+
export declare function _isJwtSignatureValidNoThrow(jwt: string | null, publicKey: string): Promise<any>;
|
|
30
|
+
export declare function _validateJwt(req: RequestWithJWToken, customErrorFunction?: any): Promise<any>;
|
|
31
|
+
export declare function _validateWebToken(req: RequestWithJWToken, headerName: string, customErrorFunction?: any): Promise<any>;
|
|
32
|
+
export declare function _validateJwtNoThrow(req: RequestWithJWToken): string | null;
|
|
33
|
+
export declare function _validateWebTokenNoThrow(req: RequestWithJWToken, headerName: string): string | null;
|
|
34
|
+
export declare function _validateVisitorNoThrow(req: RequestWithJWToken): string | null;
|
|
35
|
+
export declare function _extractJwt(jwtRaw: string | undefined, customErrorFunction?: (msg?: string) => never | void): string | null;
|
|
36
|
+
export declare function _extractWebToken(jwtRaw: string | undefined, customErrorFunction?: any): string | null;
|
|
37
|
+
export declare function _extractJwtNoThrow(jwtRaw: string): string | null;
|
|
38
|
+
export declare function _extractWebTokenNoThrow(jwtRaw: string): string | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNameOfRoleFromCode = getNameOfRoleFromCode;
|
|
4
|
+
exports.getCodeFromNameOfRole = getCodeFromNameOfRole;
|
|
5
|
+
const codesToCategory = {
|
|
6
|
+
ad: 'admin',
|
|
7
|
+
su: 'super_admin',
|
|
8
|
+
};
|
|
9
|
+
function getNameOfRoleFromCode(roleCode) {
|
|
10
|
+
// Cast only at index, use nullish coalescing for fallback
|
|
11
|
+
return codesToCategory[roleCode] ?? '';
|
|
12
|
+
}
|
|
13
|
+
const namesToCode = {
|
|
14
|
+
admin: 'ad',
|
|
15
|
+
super_admin: 'su',
|
|
16
|
+
};
|
|
17
|
+
function getCodeFromNameOfRole(roleName) {
|
|
18
|
+
return namesToCode[roleName] ?? '';
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
export interface JwtHeader {
|
|
3
|
+
alg: string;
|
|
4
|
+
typ: string;
|
|
5
|
+
}
|
|
6
|
+
export type Role = string;
|
|
7
|
+
export type Roles = Role[];
|
|
8
|
+
export interface JwtPayload {
|
|
9
|
+
/** Issued-at timestamp */
|
|
10
|
+
iat: number;
|
|
11
|
+
/** Client identifier (UUID as string) */
|
|
12
|
+
client_id: string;
|
|
13
|
+
roles: Roles;
|
|
14
|
+
email_not_confirmed: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface JWToken {
|
|
17
|
+
header: JwtHeader;
|
|
18
|
+
payload: JwtPayload;
|
|
19
|
+
/** Age in milliseconds (number) */
|
|
20
|
+
age: number;
|
|
21
|
+
}
|
|
22
|
+
export interface RequestWithJWToken extends Request {
|
|
23
|
+
jwt?: JWToken | null | undefined;
|
|
24
|
+
visitor?: JWToken | null | undefined;
|
|
25
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Response, NextFunction } from 'express';
|
|
2
|
+
import { RequestWithJWToken, Role } from './types';
|
|
3
|
+
export declare function jwtClientId(req: RequestWithJWToken): string | undefined;
|
|
4
|
+
export declare function visitorClientId(req: RequestWithJWToken): string | undefined;
|
|
5
|
+
export declare function doesJwtUserHasRole(req: RequestWithJWToken, userRole: Role): boolean | undefined;
|
|
6
|
+
export declare function throwError(customErrorFunction?: any): void;
|
|
7
|
+
export declare function isJwtExpired(req: RequestWithJWToken, jwtValiditySeconds: number): boolean;
|
|
8
|
+
export declare function jwtAgeInMilliseconds(req: RequestWithJWToken): number;
|
|
9
|
+
export declare function validateAndExtractJwtObject(req: RequestWithJWToken, publicKey: string, customErrorFunction?: any): Promise<any>;
|
|
10
|
+
export declare function validateAndExtractWebToken(req: RequestWithJWToken, publicKey: string, headerName: string, customErrorFunction?: any): Promise<any>;
|
|
11
|
+
export declare function validateAndExtractJwtObjectNoThrow(req: RequestWithJWToken, publicKey: string): Promise<any>;
|
|
12
|
+
export declare function validateAndExtractWebTokenObjectNoThrow(req: RequestWithJWToken, publicKey: string, headerName: string): Promise<any>;
|
|
13
|
+
export declare function validateAndExtractVisitorObjectNoThrow(req: RequestWithJWToken, publicKey: string): Promise<any>;
|
|
14
|
+
export declare function verifyJwtAndRole(role: Role, publicKey: string, customErrorFunction?: any): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<any>;
|
|
15
|
+
export declare function verifyJwt(publicKey: string, customErrorFunction?: any): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<any>;
|
|
16
|
+
export declare function verifyWebToken(publicKey: string, headerName: string, customErrorFunction?: any): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<any>;
|
|
17
|
+
export declare function verifyJwtNoThrow(publicKey: string): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<void>;
|
|
18
|
+
export declare function verifyWebTokenNoThrow(publicKey: string, headerName: string): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<void>;
|
|
19
|
+
export declare function verifyVisitorNoThrow(publicKey: string): (req: RequestWithJWToken, res: Response, next: NextFunction) => Promise<void>;
|
|
20
|
+
export declare function throwUsedTokenError(): void;
|
|
21
|
+
/*********************
|
|
22
|
+
* Private functions *
|
|
23
|
+
*********************/
|
|
24
|
+
export declare function _isLoginRequired(hasRequiredRole: boolean | undefined, customErrorFunction?: any): void;
|
|
25
|
+
export declare function _extractJwtObject(req: RequestWithJWToken, jwt: string, customErrorFunction?: any): Promise<any>;
|
|
26
|
+
export declare function _extractJwtObjectNoThrow(req: RequestWithJWToken, jwt: string): Promise<any>;
|
|
27
|
+
export declare function _extractVisitorObjectNoThrow(req: RequestWithJWToken, jwt: string): Promise<any>;
|
|
28
|
+
export declare function _isJwtSignatureValid(jwt: string, publicKey: string, customErrorFunction?: any): Promise<any>;
|
|
29
|
+
export declare function _isJwtSignatureValidNoThrow(jwt: string | null, publicKey: string): Promise<any>;
|
|
30
|
+
export declare function _validateJwt(req: RequestWithJWToken, customErrorFunction?: any): Promise<any>;
|
|
31
|
+
export declare function _validateWebToken(req: RequestWithJWToken, headerName: string, customErrorFunction?: any): Promise<any>;
|
|
32
|
+
export declare function _validateJwtNoThrow(req: RequestWithJWToken): string | null;
|
|
33
|
+
export declare function _validateWebTokenNoThrow(req: RequestWithJWToken, headerName: string): string | null;
|
|
34
|
+
export declare function _validateVisitorNoThrow(req: RequestWithJWToken): string | null;
|
|
35
|
+
export declare function _extractJwt(jwtRaw: string | undefined, customErrorFunction?: (msg?: string) => never | void): string | null;
|
|
36
|
+
export declare function _extractWebToken(jwtRaw: string | undefined, customErrorFunction?: any): string | null;
|
|
37
|
+
export declare function _extractJwtNoThrow(jwtRaw: string): string | null;
|
|
38
|
+
export declare function _extractWebTokenNoThrow(jwtRaw: string): string | null;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import * as validate from '@carecard/validate';
|
|
2
|
+
import * as jwtUtilAuth from '@carecard/auth-util';
|
|
3
|
+
import { throwLoginRequiredError, throwNotAuthorizedError } from '@carecard/common-util';
|
|
4
|
+
export function jwtClientId(req) {
|
|
5
|
+
return req?.jwt?.payload?.client_id;
|
|
6
|
+
}
|
|
7
|
+
export function visitorClientId(req) {
|
|
8
|
+
return req?.visitor?.payload?.client_id;
|
|
9
|
+
}
|
|
10
|
+
export function doesJwtUserHasRole(req, userRole) {
|
|
11
|
+
if (userRole && typeof userRole === 'string') {
|
|
12
|
+
return req?.jwt?.payload?.roles?.includes(userRole);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
throwNotAuthorizedError();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function throwError(customErrorFunction) {
|
|
19
|
+
typeof customErrorFunction === 'function' ? customErrorFunction() : throwLoginRequiredError();
|
|
20
|
+
}
|
|
21
|
+
export function isJwtExpired(req, jwtValiditySeconds) {
|
|
22
|
+
if (jwtValiditySeconds && typeof jwtValiditySeconds === 'number') {
|
|
23
|
+
return Math.abs(Math.round(jwtValiditySeconds)) * 1000 < jwtAgeInMilliseconds(req);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function jwtAgeInMilliseconds(req) {
|
|
30
|
+
// Ensure req.jwt exists (create it if undefined)
|
|
31
|
+
req.jwt ?? (req.jwt = {
|
|
32
|
+
header: { alg: 'sha512', typ: 'JWT' }, // or a minimal placeholder
|
|
33
|
+
payload: { iat: 0, client_id: '', roles: [], email_not_confirmed: false },
|
|
34
|
+
age: Infinity,
|
|
35
|
+
});
|
|
36
|
+
const iat = req.jwt.payload?.iat;
|
|
37
|
+
const age = typeof iat === 'number' && iat > 0 ? Date.now() - iat : Infinity;
|
|
38
|
+
req.jwt.age = age;
|
|
39
|
+
return age;
|
|
40
|
+
}
|
|
41
|
+
export async function validateAndExtractJwtObject(req, publicKey, customErrorFunction) {
|
|
42
|
+
const jwtString = await _validateJwt(req, customErrorFunction);
|
|
43
|
+
const isJwtSignatureValid = await _isJwtSignatureValid(jwtString, publicKey, customErrorFunction);
|
|
44
|
+
if (jwtString && isJwtSignatureValid) {
|
|
45
|
+
await _extractJwtObject(req, jwtString, customErrorFunction);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
req['jwt'] = null;
|
|
49
|
+
throwError(customErrorFunction);
|
|
50
|
+
}
|
|
51
|
+
return req;
|
|
52
|
+
}
|
|
53
|
+
export async function validateAndExtractWebToken(req, publicKey, headerName, customErrorFunction) {
|
|
54
|
+
const webTokenString = await _validateWebToken(req, headerName, customErrorFunction);
|
|
55
|
+
const isJwtSignatureValid = await _isJwtSignatureValid(webTokenString, publicKey, customErrorFunction);
|
|
56
|
+
if (webTokenString && isJwtSignatureValid) {
|
|
57
|
+
await _extractJwtObject(req, webTokenString, customErrorFunction);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
req['jwt'] = null;
|
|
61
|
+
throwError(customErrorFunction);
|
|
62
|
+
}
|
|
63
|
+
return req;
|
|
64
|
+
}
|
|
65
|
+
export async function validateAndExtractJwtObjectNoThrow(req, publicKey) {
|
|
66
|
+
try {
|
|
67
|
+
const jwtString = await _validateJwtNoThrow(req);
|
|
68
|
+
const isJwtSignatureValid = await _isJwtSignatureValidNoThrow(jwtString, publicKey);
|
|
69
|
+
if (jwtString && isJwtSignatureValid) {
|
|
70
|
+
await _extractJwtObjectNoThrow(req, jwtString);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
req['jwt'] = null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
req['jwt'] = null;
|
|
78
|
+
}
|
|
79
|
+
return req;
|
|
80
|
+
}
|
|
81
|
+
export async function validateAndExtractWebTokenObjectNoThrow(req, publicKey, headerName) {
|
|
82
|
+
try {
|
|
83
|
+
const jwtString = _validateWebTokenNoThrow(req, headerName);
|
|
84
|
+
const isJwtSignatureValid = await _isJwtSignatureValidNoThrow(jwtString, publicKey);
|
|
85
|
+
if (jwtString && isJwtSignatureValid) {
|
|
86
|
+
await _extractJwtObjectNoThrow(req, jwtString);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
req['jwt'] = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
req['jwt'] = null;
|
|
94
|
+
}
|
|
95
|
+
return req;
|
|
96
|
+
}
|
|
97
|
+
export async function validateAndExtractVisitorObjectNoThrow(req, publicKey) {
|
|
98
|
+
try {
|
|
99
|
+
const jwtString = await _validateVisitorNoThrow(req);
|
|
100
|
+
const isJwtSignatureValid = await _isJwtSignatureValidNoThrow(jwtString, publicKey);
|
|
101
|
+
if (jwtString && isJwtSignatureValid) {
|
|
102
|
+
await _extractVisitorObjectNoThrow(req, jwtString);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
req['visitor'] = null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
req['visitor'] = null;
|
|
110
|
+
}
|
|
111
|
+
return req;
|
|
112
|
+
}
|
|
113
|
+
export function verifyJwtAndRole(role, publicKey, customErrorFunction) {
|
|
114
|
+
return async function (req, res, next) {
|
|
115
|
+
await validateAndExtractJwtObject(req, publicKey, customErrorFunction)
|
|
116
|
+
.then(req => doesJwtUserHasRole(req, role))
|
|
117
|
+
.then(isRoleExist => _isLoginRequired(isRoleExist, customErrorFunction))
|
|
118
|
+
.then(next)
|
|
119
|
+
.catch(next);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function verifyJwt(publicKey, customErrorFunction) {
|
|
123
|
+
return async function (req, res, next) {
|
|
124
|
+
await validateAndExtractJwtObject(req, publicKey, customErrorFunction)
|
|
125
|
+
.then(() => process.nextTick(next))
|
|
126
|
+
.catch(next);
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export function verifyWebToken(publicKey, headerName, customErrorFunction) {
|
|
130
|
+
return async function (req, res, next) {
|
|
131
|
+
await validateAndExtractWebToken(req, publicKey, headerName, customErrorFunction)
|
|
132
|
+
.then(() => process.nextTick(next))
|
|
133
|
+
.catch(next);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export function verifyJwtNoThrow(publicKey) {
|
|
137
|
+
return async function (req, res, next) {
|
|
138
|
+
await validateAndExtractJwtObjectNoThrow(req, publicKey)
|
|
139
|
+
.then(() => process.nextTick(next))
|
|
140
|
+
.catch(next);
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export function verifyWebTokenNoThrow(publicKey, headerName) {
|
|
144
|
+
return async function (req, res, next) {
|
|
145
|
+
await validateAndExtractWebTokenObjectNoThrow(req, publicKey, headerName)
|
|
146
|
+
.then(() => process.nextTick(next))
|
|
147
|
+
.catch(next);
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function verifyVisitorNoThrow(publicKey) {
|
|
151
|
+
return async function (req, res, next) {
|
|
152
|
+
await validateAndExtractVisitorObjectNoThrow(req, publicKey)
|
|
153
|
+
.then(() => process.nextTick(next))
|
|
154
|
+
.catch(next);
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
export function throwUsedTokenError() {
|
|
158
|
+
throw new Error('Used_Token');
|
|
159
|
+
}
|
|
160
|
+
/*********************
|
|
161
|
+
* Private functions *
|
|
162
|
+
*********************/
|
|
163
|
+
export function _isLoginRequired(hasRequiredRole, customErrorFunction) {
|
|
164
|
+
if (!hasRequiredRole) {
|
|
165
|
+
throwError(customErrorFunction);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export async function _extractJwtObject(req, jwt, customErrorFunction) {
|
|
169
|
+
if (jwt && typeof jwt === 'string') {
|
|
170
|
+
req['jwt'] = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
throwError(customErrorFunction);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export async function _extractJwtObjectNoThrow(req, jwt) {
|
|
177
|
+
if (jwt && typeof jwt === 'string') {
|
|
178
|
+
req['jwt'] = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
req['jwt'] = null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export async function _extractVisitorObjectNoThrow(req, jwt) {
|
|
185
|
+
if (jwt && typeof jwt === 'string') {
|
|
186
|
+
req['visitor'] = jwtUtilAuth.getHeaderPayloadFromJwt(jwt);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
req['visitor'] = null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export async function _isJwtSignatureValid(jwt, publicKey, customErrorFunction) {
|
|
193
|
+
if (jwt && typeof jwt === 'string') {
|
|
194
|
+
return jwtUtilAuth.verifyJwtSignature(jwt, publicKey);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
throwError(customErrorFunction);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export async function _isJwtSignatureValidNoThrow(jwt, publicKey) {
|
|
201
|
+
if (jwt && typeof jwt === 'string') {
|
|
202
|
+
return jwtUtilAuth.verifyJwtSignature(jwt, publicKey);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export async function _validateJwt(req, customErrorFunction) {
|
|
209
|
+
// Get from http header.
|
|
210
|
+
let jwtRaw = req.get('Authorization');
|
|
211
|
+
// Extract jwt from bearer schema.
|
|
212
|
+
let jwt = _extractJwt(jwtRaw, customErrorFunction);
|
|
213
|
+
// Validate characters string of jwt.
|
|
214
|
+
if (validate.isJwtString(jwt || '')) {
|
|
215
|
+
return jwt;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
throwError(customErrorFunction);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
export async function _validateWebToken(req, headerName, customErrorFunction) {
|
|
222
|
+
// Get from http header.
|
|
223
|
+
let jwtRaw = req.get(headerName);
|
|
224
|
+
// Extract jwt from bearer schema.
|
|
225
|
+
let webToken = _extractWebToken(jwtRaw, customErrorFunction);
|
|
226
|
+
// Validate characters string of jwt.
|
|
227
|
+
if (validate.isJwtString(webToken || '')) {
|
|
228
|
+
return webToken;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
throwError(customErrorFunction);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
export function _validateJwtNoThrow(req) {
|
|
235
|
+
// Get from http header.
|
|
236
|
+
let jwtRaw = req.get('Authorization');
|
|
237
|
+
if (!jwtRaw) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
// Extract jwt from bearer schema.
|
|
241
|
+
let jwt = _extractJwtNoThrow(jwtRaw);
|
|
242
|
+
// Validate characters string of jwt.
|
|
243
|
+
if (validate.isJwtString(jwt || '')) {
|
|
244
|
+
return jwt;
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
export function _validateWebTokenNoThrow(req, headerName) {
|
|
249
|
+
// Get from http header.
|
|
250
|
+
let jwtRaw = req.get(headerName);
|
|
251
|
+
if (!jwtRaw) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
// Extract jwt from bearer schema.
|
|
255
|
+
let webToken = _extractWebTokenNoThrow(jwtRaw);
|
|
256
|
+
// Validate characters string of jwt.
|
|
257
|
+
if (validate.isJwtString(webToken || '')) {
|
|
258
|
+
return webToken;
|
|
259
|
+
}
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
export function _validateVisitorNoThrow(req) {
|
|
263
|
+
// Get from http header.
|
|
264
|
+
let jwtRaw = req.get('Visitor');
|
|
265
|
+
if (!jwtRaw) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
// Extract jwt from bearer schema.
|
|
269
|
+
let jwt = _extractJwtNoThrow(jwtRaw);
|
|
270
|
+
// Validate characters string of jwt.
|
|
271
|
+
if (validate.isJwtString(jwt || '')) {
|
|
272
|
+
return jwt;
|
|
273
|
+
}
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
export function _extractJwt(jwtRaw, customErrorFunction) {
|
|
277
|
+
let jwtSplit = null;
|
|
278
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
279
|
+
jwtSplit = jwtRaw.split(' ');
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
throwError(customErrorFunction);
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
// Guard before indexing
|
|
286
|
+
if (!jwtSplit || jwtSplit.length < 2) {
|
|
287
|
+
throwError(customErrorFunction);
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
if (jwtSplit[0].toLowerCase() === 'bearer') {
|
|
291
|
+
return jwtSplit[1] ?? null;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
throwError(customErrorFunction);
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
export function _extractWebToken(jwtRaw, customErrorFunction) {
|
|
299
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
300
|
+
return jwtRaw;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
throwError(customErrorFunction);
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
export function _extractJwtNoThrow(jwtRaw) {
|
|
308
|
+
let jwtSplit = null;
|
|
309
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
310
|
+
jwtSplit = jwtRaw.split(' ');
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
if (jwtSplit[0]?.toLowerCase() === 'bearer') {
|
|
316
|
+
return jwtSplit[1];
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
export function _extractWebTokenNoThrow(jwtRaw) {
|
|
321
|
+
if (jwtRaw && typeof jwtRaw === 'string') {
|
|
322
|
+
return jwtRaw;
|
|
323
|
+
}
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const codesToCategory = {
|
|
2
|
+
ad: 'admin',
|
|
3
|
+
su: 'super_admin',
|
|
4
|
+
};
|
|
5
|
+
export function getNameOfRoleFromCode(roleCode) {
|
|
6
|
+
// Cast only at index, use nullish coalescing for fallback
|
|
7
|
+
return codesToCategory[roleCode] ?? '';
|
|
8
|
+
}
|
|
9
|
+
const namesToCode = {
|
|
10
|
+
admin: 'ad',
|
|
11
|
+
super_admin: 'su',
|
|
12
|
+
};
|
|
13
|
+
export function getCodeFromNameOfRole(roleName) {
|
|
14
|
+
return namesToCode[roleName] ?? '';
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
export interface JwtHeader {
|
|
3
|
+
alg: string;
|
|
4
|
+
typ: string;
|
|
5
|
+
}
|
|
6
|
+
export type Role = string;
|
|
7
|
+
export type Roles = Role[];
|
|
8
|
+
export interface JwtPayload {
|
|
9
|
+
/** Issued-at timestamp */
|
|
10
|
+
iat: number;
|
|
11
|
+
/** Client identifier (UUID as string) */
|
|
12
|
+
client_id: string;
|
|
13
|
+
roles: Roles;
|
|
14
|
+
email_not_confirmed: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface JWToken {
|
|
17
|
+
header: JwtHeader;
|
|
18
|
+
payload: JwtPayload;
|
|
19
|
+
/** Age in milliseconds (number) */
|
|
20
|
+
age: number;
|
|
21
|
+
}
|
|
22
|
+
export interface RequestWithJWToken extends Request {
|
|
23
|
+
jwt?: JWToken | null | undefined;
|
|
24
|
+
visitor?: JWToken | null | undefined;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@carecard/jwt-read",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Jwt read functions",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"author": "PK Singh",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https:github.com/CareCard-ca/pkg-jwt-read.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"auth",
|
|
14
|
+
"utility",
|
|
15
|
+
"cryptology"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/cjs/index.cjs",
|
|
22
|
+
"module": "./dist/esm/index.js",
|
|
23
|
+
"types": "./dist/esm/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": "./dist/esm/index.js",
|
|
27
|
+
"require": "./dist/cjs/index.cjs",
|
|
28
|
+
"types": "./dist/esm/index.d.ts"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "npm run build:esm && npm run build:cjs",
|
|
36
|
+
"build:esm": "tsc -p tsconfig.esm.json",
|
|
37
|
+
"build:cjs": "tsc -p tsconfig.cjs.json && node ./scripts/rename-cjs.js",
|
|
38
|
+
"test": "NODE_NO_WARNINGS=1 jest --coverage",
|
|
39
|
+
"format": "prettier --write .",
|
|
40
|
+
"format:check": "prettier --check .",
|
|
41
|
+
"lint": "eslint",
|
|
42
|
+
"prepare": "husky"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/express": "5.0.6",
|
|
46
|
+
"@types/jest": "30.0.0",
|
|
47
|
+
"eslint": "9.39.2",
|
|
48
|
+
"husky": "9.1.7",
|
|
49
|
+
"jest": "30.2.0",
|
|
50
|
+
"prettier": "3.7.4",
|
|
51
|
+
"ts-jest": "29.4.6",
|
|
52
|
+
"typescript": "5.9.3",
|
|
53
|
+
"typescript-eslint": "8.50.1"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@carecard/auth-util": "1.0.1",
|
|
57
|
+
"@carecard/common-util": "1.0.1",
|
|
58
|
+
"@carecard/validate": "1.0.1",
|
|
59
|
+
"express": "5.2.1"
|
|
60
|
+
}
|
|
61
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Jwt read utility
|
|
2
|
+
|
|
3
|
+
## Main Functionality
|
|
4
|
+
|
|
5
|
+
This is a collection of jwt reading functions.
|
|
6
|
+
|
|
7
|
+
### Main functions
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
const jwtReader = require( '@carecard/jwt-read' );
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Read jwt
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
const jwtMiddleware = jwtReader.verifyJwtAndRole( "admin", publicKey, jwtReader.throwUsedTokenError );
|
|
17
|
+
await jwtMiddleware( req, res, next );
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Following the above ```req.jwt``` contains
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
{
|
|
24
|
+
header: {
|
|
25
|
+
alg: ''
|
|
26
|
+
}
|
|
27
|
+
payload: {
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|