@villedemontreal/jwt-validator 5.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +313 -0
  3. package/dist/scripts/index.d.ts +6 -0
  4. package/dist/scripts/index.js +16 -0
  5. package/dist/scripts/index.js.map +1 -0
  6. package/dist/scripts/lint.d.ts +6 -0
  7. package/dist/scripts/lint.js +18 -0
  8. package/dist/scripts/lint.js.map +1 -0
  9. package/dist/scripts/lintFix.d.ts +6 -0
  10. package/dist/scripts/lintFix.js +21 -0
  11. package/dist/scripts/lintFix.js.map +1 -0
  12. package/dist/scripts/showCoverage.d.ts +13 -0
  13. package/dist/scripts/showCoverage.js +40 -0
  14. package/dist/scripts/showCoverage.js.map +1 -0
  15. package/dist/scripts/test.d.ts +13 -0
  16. package/dist/scripts/test.js +29 -0
  17. package/dist/scripts/test.js.map +1 -0
  18. package/dist/scripts/testUnits.d.ts +15 -0
  19. package/dist/scripts/testUnits.js +95 -0
  20. package/dist/scripts/testUnits.js.map +1 -0
  21. package/dist/scripts/watch.d.ts +14 -0
  22. package/dist/scripts/watch.js +96 -0
  23. package/dist/scripts/watch.js.map +1 -0
  24. package/dist/src/config/configs.d.ts +88 -0
  25. package/dist/src/config/configs.js +123 -0
  26. package/dist/src/config/configs.js.map +1 -0
  27. package/dist/src/config/constants.d.ts +56 -0
  28. package/dist/src/config/constants.js +66 -0
  29. package/dist/src/config/constants.js.map +1 -0
  30. package/dist/src/config/init.d.ts +15 -0
  31. package/dist/src/config/init.js +48 -0
  32. package/dist/src/config/init.js.map +1 -0
  33. package/dist/src/index.d.ts +10 -0
  34. package/dist/src/index.js +32 -0
  35. package/dist/src/index.js.map +1 -0
  36. package/dist/src/jwtValidator.d.ts +21 -0
  37. package/dist/src/jwtValidator.js +129 -0
  38. package/dist/src/jwtValidator.js.map +1 -0
  39. package/dist/src/jwtValidator.test.d.ts +1 -0
  40. package/dist/src/jwtValidator.test.js +500 -0
  41. package/dist/src/jwtValidator.test.js.map +1 -0
  42. package/dist/src/middleware/jwtMiddleware.d.ts +7 -0
  43. package/dist/src/middleware/jwtMiddleware.js +27 -0
  44. package/dist/src/middleware/jwtMiddleware.js.map +1 -0
  45. package/dist/src/models/customError.d.ts +11 -0
  46. package/dist/src/models/customError.js +38 -0
  47. package/dist/src/models/customError.js.map +1 -0
  48. package/dist/src/models/expressRequest.d.ts +15 -0
  49. package/dist/src/models/expressRequest.js +17 -0
  50. package/dist/src/models/expressRequest.js.map +1 -0
  51. package/dist/src/models/gluuUserType.d.ts +9 -0
  52. package/dist/src/models/gluuUserType.js +14 -0
  53. package/dist/src/models/gluuUserType.js.map +1 -0
  54. package/dist/src/models/jwtPayload.d.ts +30 -0
  55. package/dist/src/models/jwtPayload.js +19 -0
  56. package/dist/src/models/jwtPayload.js.map +1 -0
  57. package/dist/src/models/pagination.d.ts +16 -0
  58. package/dist/src/models/pagination.js +16 -0
  59. package/dist/src/models/pagination.js.map +1 -0
  60. package/dist/src/models/publicKey.d.ts +29 -0
  61. package/dist/src/models/publicKey.js +13 -0
  62. package/dist/src/models/publicKey.js.map +1 -0
  63. package/dist/src/repositories/cachedPublicKeyRepository.d.ts +53 -0
  64. package/dist/src/repositories/cachedPublicKeyRepository.js +102 -0
  65. package/dist/src/repositories/cachedPublicKeyRepository.js.map +1 -0
  66. package/dist/src/repositories/publicKeyRepository.d.ts +19 -0
  67. package/dist/src/repositories/publicKeyRepository.js +44 -0
  68. package/dist/src/repositories/publicKeyRepository.js.map +1 -0
  69. package/dist/src/userValidator.d.ts +30 -0
  70. package/dist/src/userValidator.js +35 -0
  71. package/dist/src/userValidator.js.map +1 -0
  72. package/dist/src/userValidator.test.d.ts +1 -0
  73. package/dist/src/userValidator.test.js +251 -0
  74. package/dist/src/userValidator.test.js.map +1 -0
  75. package/dist/src/utils/jwtMock.d.ts +31 -0
  76. package/dist/src/utils/jwtMock.js +221 -0
  77. package/dist/src/utils/jwtMock.js.map +1 -0
  78. package/dist/src/utils/logger.d.ts +11 -0
  79. package/dist/src/utils/logger.js +54 -0
  80. package/dist/src/utils/logger.js.map +1 -0
  81. package/dist/src/utils/testingConfigurations.d.ts +7 -0
  82. package/dist/src/utils/testingConfigurations.js +16 -0
  83. package/dist/src/utils/testingConfigurations.js.map +1 -0
  84. package/package.json +82 -0
  85. package/src/config/configs.ts +145 -0
  86. package/src/config/constants.ts +83 -0
  87. package/src/config/init.ts +58 -0
  88. package/src/index.ts +15 -0
  89. package/src/jwtValidator.test.ts +607 -0
  90. package/src/jwtValidator.ts +162 -0
  91. package/src/middleware/jwtMiddleware.ts +33 -0
  92. package/src/models/customError.ts +37 -0
  93. package/src/models/expressRequest.ts +27 -0
  94. package/src/models/gluuUserType.ts +9 -0
  95. package/src/models/jwtPayload.ts +58 -0
  96. package/src/models/pagination.ts +26 -0
  97. package/src/models/publicKey.ts +33 -0
  98. package/src/repositories/cachedPublicKeyRepository.ts +121 -0
  99. package/src/repositories/publicKeyRepository.ts +75 -0
  100. package/src/userValidator.test.ts +279 -0
  101. package/src/userValidator.ts +54 -0
  102. package/src/utils/jwtMock.ts +243 -0
  103. package/src/utils/logger.ts +60 -0
  104. package/src/utils/testingConfigurations.ts +12 -0
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.jwtValidator = void 0;
4
+ const general_utils_1 = require("@villedemontreal/general-utils");
5
+ const jwt = require("jsonwebtoken");
6
+ const moment = require("moment");
7
+ const constants_1 = require("./config/constants");
8
+ const customError_1 = require("./models/customError");
9
+ const jwtPayload_1 = require("./models/jwtPayload");
10
+ const publicKey_1 = require("./models/publicKey");
11
+ const cachedPublicKeyRepository_1 = require("./repositories/cachedPublicKeyRepository");
12
+ /**
13
+ * JWT Validator
14
+ */
15
+ class JwtValidator {
16
+ async verifyAuthorizationHeader(header) {
17
+ if (general_utils_1.utils.isBlank(header)) {
18
+ throw (0, customError_1.createInvalidAuthHeaderError)({
19
+ code: constants_1.constants.errors.codes.NULL_VALUE,
20
+ target: 'Authorization header',
21
+ message: 'Empty Authorization header',
22
+ });
23
+ }
24
+ const parts = header.trim().split(' ');
25
+ if (parts[0] !== 'Bearer') {
26
+ throw (0, customError_1.createInvalidAuthHeaderError)({
27
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
28
+ target: 'Authorization header',
29
+ message: 'Bad authentication scheme, "Bearer" required',
30
+ });
31
+ }
32
+ return await this.verifyToken(parts[1]);
33
+ }
34
+ async verifyToken(token) {
35
+ const payload = this.parseJwt(token);
36
+ const key = await this.getJwtPublicKey(payload);
37
+ this.validateJwtCreationTimestamp(payload, key);
38
+ this.validateJwtExpirationTimestamp(payload, key);
39
+ return this.verifyJwt(token, key.publicKey);
40
+ }
41
+ parseJwt(token) {
42
+ const payload = jwt.decode(token);
43
+ if (!payload) {
44
+ throw (0, customError_1.createInvalidJwtError)({
45
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
46
+ target: 'jwt',
47
+ message: 'jwt malformed',
48
+ });
49
+ }
50
+ return payload;
51
+ }
52
+ verifyJwt(token, publicKey) {
53
+ let payload;
54
+ try {
55
+ payload = jwt.verify(token, publicKey);
56
+ }
57
+ catch (err) {
58
+ throw (0, customError_1.createInvalidJwtError)({
59
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
60
+ target: 'jwt',
61
+ message: err.message,
62
+ });
63
+ }
64
+ if ((0, jwtPayload_1.isJWTPayload)(payload)) {
65
+ return payload;
66
+ }
67
+ throw (0, customError_1.createInvalidJwtError)({
68
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
69
+ target: 'jwt',
70
+ message: 'expected a valid JWT payload',
71
+ });
72
+ }
73
+ async getJwtPublicKey(payload) {
74
+ const keyId = payload.keyId;
75
+ if (!keyId || keyId <= 0) {
76
+ throw (0, customError_1.createInvalidJwtError)({
77
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
78
+ target: 'jwt',
79
+ message: 'missing public key ID',
80
+ });
81
+ }
82
+ const key = await cachedPublicKeyRepository_1.cachedPublicKeyRepository.getOne(keyId);
83
+ // Check key state
84
+ if (!key || key.state !== publicKey_1.PublicKeyState.ACTIVE) {
85
+ throw (0, customError_1.createInvalidJwtError)({
86
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
87
+ target: 'jwt',
88
+ message: 'this keyId is no longer active',
89
+ });
90
+ }
91
+ return key;
92
+ }
93
+ validateJwtCreationTimestamp(payload, key) {
94
+ // Check the jwt was not created before the creation date of the key
95
+ const payloadIat = moment.utc(payload.iat * 1000);
96
+ const keyCreatedAt = moment.utc(key.createdAt);
97
+ if (payloadIat.diff(keyCreatedAt) < 0) {
98
+ throw (0, customError_1.createInvalidJwtError)({
99
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
100
+ target: 'jwt',
101
+ message: "this jwt can't be created before the public key",
102
+ });
103
+ }
104
+ }
105
+ validateJwtExpirationTimestamp(payload, key) {
106
+ // Check expiration date
107
+ if (key.expiresAt) {
108
+ const keyexpiresAt = moment.utc(key.expiresAt);
109
+ if (moment.utc().diff(keyexpiresAt) > 0) {
110
+ throw (0, customError_1.createInvalidJwtError)({
111
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
112
+ target: 'jwt',
113
+ message: 'this keyId is expired',
114
+ });
115
+ }
116
+ // Check the jwt was not created after the expiration date of the key
117
+ const payloadIat = moment.utc(payload.iat * 1000);
118
+ if (payloadIat.diff(keyexpiresAt) > 0) {
119
+ throw (0, customError_1.createInvalidJwtError)({
120
+ code: constants_1.constants.errors.codes.INVALID_VALUE,
121
+ target: 'jwt',
122
+ message: "this jwt can't be created after the expiration of the public key",
123
+ });
124
+ }
125
+ }
126
+ }
127
+ }
128
+ exports.jwtValidator = new JwtValidator();
129
+ //# sourceMappingURL=jwtValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwtValidator.js","sourceRoot":"","sources":["../../src/jwtValidator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,500 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const src_1 = require("@villedemontreal/general-utils/dist/src");
4
+ const chai_1 = require("chai");
5
+ const jwt = require("jsonwebtoken");
6
+ const nock = require("nock");
7
+ const validator = require("validator");
8
+ const configs_1 = require("./config/configs");
9
+ const constants_1 = require("./config/constants");
10
+ const jwtValidator_1 = require("./jwtValidator");
11
+ const expressRequest_1 = require("./models/expressRequest");
12
+ const cachedPublicKeyRepository_1 = require("./repositories/cachedPublicKeyRepository");
13
+ const jwtMock_1 = require("./utils/jwtMock");
14
+ const testingConfigurations_1 = require("./utils/testingConfigurations");
15
+ const httpMocks = require('node-mocks-http');
16
+ // ==========================================
17
+ // Set Testing configurations
18
+ // ==========================================
19
+ (0, testingConfigurations_1.setTestingConfigurations)();
20
+ // ==========================================
21
+ // JWT Validator
22
+ // ==========================================
23
+ let date;
24
+ let publicKeys;
25
+ function createPathRegex() {
26
+ const regExpEscape = (s) => {
27
+ return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
28
+ };
29
+ return new RegExp(`${regExpEscape(configs_1.configs.getEndpoint())}(.*)`);
30
+ }
31
+ before('JWT Validator - init app & get jwt public key', async () => {
32
+ nock.cleanAll();
33
+ // Use mock keys
34
+ await jwtMock_1.jwtMock.mockPublicKeys();
35
+ publicKeys = await cachedPublicKeyRepository_1.cachedPublicKeyRepository.getAll();
36
+ chai_1.assert.match(publicKeys[1].publicKey, /^-----BEGIN PUBLIC KEY-----\n/m);
37
+ chai_1.assert.match(publicKeys[1].publicKey, /^-----BEGIN PUBLIC KEY-----\n/m);
38
+ chai_1.assert.match(publicKeys[1].publicKey, /\n-----END PUBLIC KEY-----$/m);
39
+ const key = publicKeys[1].publicKey
40
+ .replace(/^-----BEGIN PUBLIC KEY-----\n/m, '')
41
+ .replace(/\n-----END PUBLIC KEY-----$/m, '')
42
+ .split('\n')
43
+ .join('');
44
+ chai_1.assert.isTrue(validator.default.isBase64(key));
45
+ });
46
+ it('JWT Validator - verifyHeader - should reject null header', async () => {
47
+ const response = await jwtValidator_1.jwtValidator.verifyAuthorizationHeader(null).catch((err) => {
48
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_AUTHORIZATION_HEADER);
49
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
50
+ chai_1.assert.strictEqual(err.error.message, 'Invalid Authorization header');
51
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.NULL_VALUE);
52
+ chai_1.assert.strictEqual(err.error.details[0].target, 'Authorization header');
53
+ chai_1.assert.strictEqual(err.error.details[0].message, 'Empty Authorization header');
54
+ });
55
+ chai_1.assert.isUndefined(response);
56
+ });
57
+ it('JWT Validator - verifyHeader - should reject empty header', async () => {
58
+ const response = await jwtValidator_1.jwtValidator.verifyAuthorizationHeader('').catch((err) => {
59
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_AUTHORIZATION_HEADER);
60
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
61
+ chai_1.assert.strictEqual(err.error.message, 'Invalid Authorization header');
62
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.NULL_VALUE);
63
+ chai_1.assert.strictEqual(err.error.details[0].target, 'Authorization header');
64
+ chai_1.assert.strictEqual(err.error.details[0].message, 'Empty Authorization header');
65
+ });
66
+ chai_1.assert.isUndefined(response);
67
+ });
68
+ it('JWT Validator - verifyHeader - should reject unknow authentication scheme', async () => {
69
+ const response = await jwtValidator_1.jwtValidator.verifyAuthorizationHeader('Unknow JWT').catch((err) => {
70
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_AUTHORIZATION_HEADER);
71
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
72
+ chai_1.assert.strictEqual(err.error.message, 'Invalid Authorization header');
73
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
74
+ chai_1.assert.strictEqual(err.error.details[0].target, 'Authorization header');
75
+ chai_1.assert.strictEqual(err.error.details[0].message, 'Bad authentication scheme, "Bearer" required');
76
+ });
77
+ chai_1.assert.isUndefined(response);
78
+ });
79
+ it('JWT Validator - verifyHeader - should reject bad token', async () => {
80
+ const response = await jwtValidator_1.jwtValidator.verifyAuthorizationHeader('Bearer JWT').catch((err) => {
81
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
82
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
83
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
84
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
85
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
86
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt malformed');
87
+ });
88
+ chai_1.assert.isUndefined(response);
89
+ });
90
+ it('JWT Validator - verifyHeader - should accept good token', async () => {
91
+ date = new Date(publicKeys[5].createdAt);
92
+ date.setHours(date.getHours() + 24);
93
+ const payload = {
94
+ accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
95
+ iss: 'Issuer',
96
+ inum: 'MyInum',
97
+ iat: date.getTime() / 1000,
98
+ exp: date.getTime() / 1000 + 3600,
99
+ sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
100
+ keyId: 5,
101
+ };
102
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
103
+ algorithm: 'RS256',
104
+ });
105
+ const response = await jwtValidator_1.jwtValidator.verifyAuthorizationHeader('Bearer ' + token);
106
+ chai_1.assert.deepEqual(response, payload);
107
+ });
108
+ it('JWT Validator - verify - should reject bad token', async () => {
109
+ const response = await jwtValidator_1.jwtValidator.verifyToken('JWT').catch((err) => {
110
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
111
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
112
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
113
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
114
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
115
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt malformed');
116
+ });
117
+ chai_1.assert.isUndefined(response);
118
+ });
119
+ it('JWT Validator - verify - should reject invalid token: missing signature', async () => {
120
+ let token = '';
121
+ token += Buffer.from('{}', 'base64');
122
+ token += '.';
123
+ token += Buffer.from('{}', 'base64');
124
+ token += '.';
125
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
126
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
127
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
128
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
129
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
130
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
131
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt malformed');
132
+ });
133
+ chai_1.assert.isUndefined(response);
134
+ });
135
+ it('JWT Validator - verify - should reject invalid token: empty JSON', async () => {
136
+ let token = '';
137
+ token += Buffer.from('{}', 'base64');
138
+ token += '.';
139
+ token += Buffer.from('{}', 'base64');
140
+ token += '.';
141
+ token += 'TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ';
142
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
143
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
144
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
145
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
146
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
147
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
148
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt malformed');
149
+ });
150
+ chai_1.assert.isUndefined(response);
151
+ });
152
+ it('JWT Validator - verify - should reject invalid token: missing public key ID', async () => {
153
+ const token = jwt.sign('{"a":"a"}', 'key', { algorithm: 'HS256' });
154
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
155
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
156
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
157
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
158
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
159
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
160
+ chai_1.assert.strictEqual(err.error.details[0].message, 'missing public key ID');
161
+ });
162
+ chai_1.assert.isUndefined(response);
163
+ });
164
+ it('JWT Validator - verify - should reject invalid token: keyId is no longer active', async () => {
165
+ const token = jwt.sign('{"a":"a", "keyId": "1"}', 'key', { algorithm: 'HS256' });
166
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
167
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
168
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
169
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
170
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
171
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
172
+ chai_1.assert.strictEqual(err.error.details[0].message, 'this keyId is no longer active');
173
+ });
174
+ chai_1.assert.isUndefined(response);
175
+ });
176
+ it('JWT Validator - verify - should reject invalid token: keyId not found', async () => {
177
+ const pathRegex = createPathRegex();
178
+ // Intercept request
179
+ nock(configs_1.configs.getHost()).get(pathRegex).reply(404);
180
+ const token = jwt.sign('{"a":"a", "keyId": "25"}', 'key', { algorithm: 'HS256' });
181
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
182
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
183
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
184
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
185
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
186
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
187
+ chai_1.assert.strictEqual(err.error.details[0].message, 'this keyId is no longer active');
188
+ });
189
+ chai_1.assert.isUndefined(response);
190
+ });
191
+ it('JWT Validator - verify - should reject invalid algorithm: bad signature', async () => {
192
+ let token = '';
193
+ token += Buffer.from('{"alg":"HS256","typ":"JWT"}', 'base64');
194
+ token += '.';
195
+ token += Buffer.from('{"a":"a", "keyId": 5}', 'base64');
196
+ token += '.';
197
+ token += 'TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ';
198
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
199
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
200
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
201
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
202
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
203
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
204
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt malformed');
205
+ });
206
+ chai_1.assert.isUndefined(response);
207
+ });
208
+ it('JWT Validator - verify - should reject invalid algorithm: bad signature (algorithm)', async () => {
209
+ const token = jwt.sign('{"a":"a", "keyId": 5}', 'key', { algorithm: 'HS256' });
210
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
211
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
212
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
213
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
214
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
215
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
216
+ chai_1.assert.strictEqual(err.error.details[0].message, 'invalid algorithm');
217
+ });
218
+ chai_1.assert.isUndefined(response);
219
+ });
220
+ it('JWT Validator - verify - should reject expired token', async () => {
221
+ date = new Date(publicKeys[5].createdAt);
222
+ date.setHours(date.getHours() + 24);
223
+ const payload = {
224
+ b: 'b',
225
+ iat: date.getTime() / 1000,
226
+ exp: 1,
227
+ keyId: 5,
228
+ };
229
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
230
+ algorithm: 'RS256',
231
+ });
232
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
233
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
234
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
235
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
236
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
237
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
238
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt expired');
239
+ });
240
+ chai_1.assert.isUndefined(response);
241
+ });
242
+ it('JWT Validator - verify - should reject expired public key', async () => {
243
+ const payload = {
244
+ b: 'b',
245
+ keyId: 2,
246
+ };
247
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
248
+ algorithm: 'RS256',
249
+ });
250
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
251
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
252
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
253
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
254
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
255
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
256
+ chai_1.assert.strictEqual(err.error.details[0].message, 'this keyId is expired');
257
+ });
258
+ chai_1.assert.isUndefined(response);
259
+ });
260
+ it('JWT Validator - verify - should reject expired public key (by state)', async () => {
261
+ const payload = {
262
+ b: 'b',
263
+ keyId: 1,
264
+ };
265
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
266
+ algorithm: 'RS256',
267
+ });
268
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
269
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
270
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
271
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
272
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
273
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
274
+ chai_1.assert.strictEqual(err.error.details[0].message, 'this keyId is no longer active');
275
+ });
276
+ chai_1.assert.isUndefined(response);
277
+ });
278
+ it('JWT Validator - verify - should reject revoked public key', async () => {
279
+ const payload = {
280
+ b: 'b',
281
+ keyId: 3,
282
+ };
283
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
284
+ algorithm: 'RS256',
285
+ });
286
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
287
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
288
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
289
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
290
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
291
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
292
+ chai_1.assert.strictEqual(err.error.details[0].message, 'this keyId is no longer active');
293
+ });
294
+ chai_1.assert.isUndefined(response);
295
+ });
296
+ it('JWT Validator - verify - should reject jwt created after the expiration date of the key', async () => {
297
+ date = new Date(publicKeys[4].expiresAt);
298
+ date.setHours(date.getHours() + 24);
299
+ const payload = {
300
+ b: 'b',
301
+ iat: date.getTime() / 1000,
302
+ keyId: 4,
303
+ };
304
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
305
+ algorithm: 'RS256',
306
+ });
307
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
308
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
309
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
310
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
311
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
312
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
313
+ chai_1.assert.strictEqual(err.error.details[0].message, "this jwt can't be created after the expiration of the public key");
314
+ });
315
+ chai_1.assert.isUndefined(response);
316
+ });
317
+ it('JWT Validator - verify - should reject jwt created before the creation date of the key', async () => {
318
+ date = new Date(publicKeys[4].createdAt);
319
+ date.setHours(date.getHours() - 48);
320
+ const payload = {
321
+ b: 'b',
322
+ iat: date.getTime() / 1000,
323
+ keyId: 4,
324
+ };
325
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
326
+ algorithm: 'RS256',
327
+ });
328
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
329
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
330
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
331
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
332
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
333
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
334
+ chai_1.assert.strictEqual(err.error.details[0].message, "this jwt can't be created before the public key");
335
+ });
336
+ chai_1.assert.isUndefined(response);
337
+ });
338
+ it('JWT Validator - verify - should accept good token', async () => {
339
+ date = new Date();
340
+ const payload = {
341
+ accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
342
+ iss: 'Issuer',
343
+ inum: 'MyInum',
344
+ iat: date.getTime() / 1000,
345
+ exp: date.getTime() / 1000 + 3600,
346
+ sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
347
+ keyId: 4,
348
+ };
349
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
350
+ algorithm: 'RS256',
351
+ });
352
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token);
353
+ chai_1.assert.deepEqual(response, payload);
354
+ });
355
+ it('isRequestWithJwt', async () => {
356
+ const req = httpMocks.createRequest({ method: 'GET', url: '/' });
357
+ chai_1.assert.isFalse((0, expressRequest_1.isRequestWithJwt)(req));
358
+ req[constants_1.constants.requestExtraVariables.JWT] = 'Bonjour la police';
359
+ chai_1.assert.isTrue((0, expressRequest_1.isRequestWithJwt)(req));
360
+ });
361
+ it('JWT Validator - unable to get public key', async () => {
362
+ const pathRegex = createPathRegex();
363
+ // Intercept request
364
+ nock(configs_1.configs.getHost()).get(pathRegex).reply(500);
365
+ const token = jwt.sign('{"a":"a", "keyId": "25"}', 'key', { algorithm: 'HS256' });
366
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token).catch((err) => {
367
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.UNABLE_TO_GET_PUBLIC_KEY);
368
+ chai_1.assert.strictEqual(err.httpStatus, 500);
369
+ });
370
+ chai_1.assert.isUndefined(response);
371
+ });
372
+ it('JWT Validator - network error - should accept good token if cached', async () => {
373
+ // Invalidate cache
374
+ const currentNextUpdate = cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate;
375
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = undefined;
376
+ const pathRegex = createPathRegex();
377
+ // Intercept request
378
+ nock(configs_1.configs.getHost()).get(pathRegex).replyWithError({ code: 'ABORTED' });
379
+ date = new Date();
380
+ const payload = {
381
+ accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
382
+ iss: 'Issuer',
383
+ inum: 'MyInum',
384
+ iat: date.getTime() / 1000,
385
+ exp: date.getTime() / 1000 + 3600,
386
+ sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
387
+ keyId: 4,
388
+ };
389
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
390
+ algorithm: 'RS256',
391
+ });
392
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token);
393
+ chai_1.assert.deepEqual(response, payload);
394
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = currentNextUpdate;
395
+ });
396
+ it('JWT Validator - 500 error from api - should accept good token if cached', async () => {
397
+ // Invalidate cache
398
+ const currentNextUpdate = cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate;
399
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = undefined;
400
+ const pathRegex = createPathRegex();
401
+ // Error from api
402
+ // Intercept request
403
+ nock(configs_1.configs.getHost())
404
+ .get(pathRegex)
405
+ .reply(500, (0, src_1.createServerError)('Error while sending request'));
406
+ date = new Date();
407
+ const payload = {
408
+ accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
409
+ iss: 'Issuer',
410
+ inum: 'MyInum',
411
+ iat: date.getTime() / 1000,
412
+ exp: date.getTime() / 1000 + 3600,
413
+ sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
414
+ keyId: 4,
415
+ };
416
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
417
+ algorithm: 'RS256',
418
+ });
419
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token);
420
+ chai_1.assert.deepEqual(response, payload);
421
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = currentNextUpdate;
422
+ });
423
+ it('JWT Validator - 429 error from api - should accept good token if cached', async () => {
424
+ // Invalidate cache
425
+ const currentNextUpdate = cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate;
426
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = undefined;
427
+ const pathRegex = createPathRegex();
428
+ // Error from api
429
+ // Intercept request
430
+ nock(configs_1.configs.getHost()).get(pathRegex).reply(429);
431
+ date = new Date();
432
+ const payload = {
433
+ accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
434
+ iss: 'Issuer',
435
+ inum: 'MyInum',
436
+ iat: date.getTime() / 1000,
437
+ exp: date.getTime() / 1000 + 3600,
438
+ sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
439
+ keyId: 4,
440
+ };
441
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
442
+ algorithm: 'RS256',
443
+ });
444
+ const response = await jwtValidator_1.jwtValidator.verifyToken(token);
445
+ chai_1.assert.deepEqual(response, payload);
446
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = currentNextUpdate;
447
+ });
448
+ it('JWT Validator - 400 error from api - should reject', async () => {
449
+ // Invalidate cache
450
+ const currentNextUpdate = cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate;
451
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = undefined;
452
+ const pathRegex = createPathRegex();
453
+ // Error from api
454
+ // Intercept request
455
+ nock(configs_1.configs.getHost())
456
+ .get(pathRegex)
457
+ .reply(400, (0, src_1.createInvalidParameterError)('Something is wrong'));
458
+ date = new Date();
459
+ const payload = {
460
+ accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
461
+ iss: 'Issuer',
462
+ inum: 'MyInum',
463
+ iat: date.getTime() / 1000,
464
+ exp: date.getTime() / 1000 + 3600,
465
+ sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
466
+ keyId: 4,
467
+ };
468
+ const token = jwt.sign(JSON.stringify(payload), jwtMock_1.jwtMock.getPrivateKey(), {
469
+ algorithm: 'RS256',
470
+ });
471
+ let error;
472
+ try {
473
+ await jwtValidator_1.jwtValidator.verifyToken(token);
474
+ }
475
+ catch (e) {
476
+ error = e;
477
+ }
478
+ chai_1.assert.isDefined(error);
479
+ chai_1.assert.instanceOf(error, src_1.ApiErrorAndInfo);
480
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = currentNextUpdate;
481
+ });
482
+ it('JWT Validator - network error - should reject bad token anyway', async () => {
483
+ // Invalidate cache
484
+ const currentNextUpdate = cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate;
485
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = undefined;
486
+ const pathRegex = createPathRegex();
487
+ // Intercept request
488
+ nock(configs_1.configs.getHost()).get(pathRegex).replyWithError({ code: 'ABORTED' });
489
+ const response = await jwtValidator_1.jwtValidator.verifyToken('JWT').catch((err) => {
490
+ chai_1.assert.strictEqual(err.error.code, constants_1.constants.errors.codes.INVALID_JWT);
491
+ chai_1.assert.strictEqual(err.error.target, 'Authorization header');
492
+ chai_1.assert.strictEqual(err.error.message, 'Invalid JWT');
493
+ chai_1.assert.strictEqual(err.error.details[0].code, constants_1.constants.errors.codes.INVALID_VALUE);
494
+ chai_1.assert.strictEqual(err.error.details[0].target, 'jwt');
495
+ chai_1.assert.strictEqual(err.error.details[0].message, 'jwt malformed');
496
+ });
497
+ chai_1.assert.isUndefined(response);
498
+ cachedPublicKeyRepository_1.cachedPublicKeyRepository._nextUpdate = currentNextUpdate;
499
+ });
500
+ //# sourceMappingURL=jwtValidator.test.js.map