@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.
- package/LICENSE +21 -0
- package/README.md +313 -0
- package/dist/scripts/index.d.ts +6 -0
- package/dist/scripts/index.js +16 -0
- package/dist/scripts/index.js.map +1 -0
- package/dist/scripts/lint.d.ts +6 -0
- package/dist/scripts/lint.js +18 -0
- package/dist/scripts/lint.js.map +1 -0
- package/dist/scripts/lintFix.d.ts +6 -0
- package/dist/scripts/lintFix.js +21 -0
- package/dist/scripts/lintFix.js.map +1 -0
- package/dist/scripts/showCoverage.d.ts +13 -0
- package/dist/scripts/showCoverage.js +40 -0
- package/dist/scripts/showCoverage.js.map +1 -0
- package/dist/scripts/test.d.ts +13 -0
- package/dist/scripts/test.js +29 -0
- package/dist/scripts/test.js.map +1 -0
- package/dist/scripts/testUnits.d.ts +15 -0
- package/dist/scripts/testUnits.js +95 -0
- package/dist/scripts/testUnits.js.map +1 -0
- package/dist/scripts/watch.d.ts +14 -0
- package/dist/scripts/watch.js +96 -0
- package/dist/scripts/watch.js.map +1 -0
- package/dist/src/config/configs.d.ts +88 -0
- package/dist/src/config/configs.js +123 -0
- package/dist/src/config/configs.js.map +1 -0
- package/dist/src/config/constants.d.ts +56 -0
- package/dist/src/config/constants.js +66 -0
- package/dist/src/config/constants.js.map +1 -0
- package/dist/src/config/init.d.ts +15 -0
- package/dist/src/config/init.js +48 -0
- package/dist/src/config/init.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.js +32 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/jwtValidator.d.ts +21 -0
- package/dist/src/jwtValidator.js +129 -0
- package/dist/src/jwtValidator.js.map +1 -0
- package/dist/src/jwtValidator.test.d.ts +1 -0
- package/dist/src/jwtValidator.test.js +500 -0
- package/dist/src/jwtValidator.test.js.map +1 -0
- package/dist/src/middleware/jwtMiddleware.d.ts +7 -0
- package/dist/src/middleware/jwtMiddleware.js +27 -0
- package/dist/src/middleware/jwtMiddleware.js.map +1 -0
- package/dist/src/models/customError.d.ts +11 -0
- package/dist/src/models/customError.js +38 -0
- package/dist/src/models/customError.js.map +1 -0
- package/dist/src/models/expressRequest.d.ts +15 -0
- package/dist/src/models/expressRequest.js +17 -0
- package/dist/src/models/expressRequest.js.map +1 -0
- package/dist/src/models/gluuUserType.d.ts +9 -0
- package/dist/src/models/gluuUserType.js +14 -0
- package/dist/src/models/gluuUserType.js.map +1 -0
- package/dist/src/models/jwtPayload.d.ts +30 -0
- package/dist/src/models/jwtPayload.js +19 -0
- package/dist/src/models/jwtPayload.js.map +1 -0
- package/dist/src/models/pagination.d.ts +16 -0
- package/dist/src/models/pagination.js +16 -0
- package/dist/src/models/pagination.js.map +1 -0
- package/dist/src/models/publicKey.d.ts +29 -0
- package/dist/src/models/publicKey.js +13 -0
- package/dist/src/models/publicKey.js.map +1 -0
- package/dist/src/repositories/cachedPublicKeyRepository.d.ts +53 -0
- package/dist/src/repositories/cachedPublicKeyRepository.js +102 -0
- package/dist/src/repositories/cachedPublicKeyRepository.js.map +1 -0
- package/dist/src/repositories/publicKeyRepository.d.ts +19 -0
- package/dist/src/repositories/publicKeyRepository.js +44 -0
- package/dist/src/repositories/publicKeyRepository.js.map +1 -0
- package/dist/src/userValidator.d.ts +30 -0
- package/dist/src/userValidator.js +35 -0
- package/dist/src/userValidator.js.map +1 -0
- package/dist/src/userValidator.test.d.ts +1 -0
- package/dist/src/userValidator.test.js +251 -0
- package/dist/src/userValidator.test.js.map +1 -0
- package/dist/src/utils/jwtMock.d.ts +31 -0
- package/dist/src/utils/jwtMock.js +221 -0
- package/dist/src/utils/jwtMock.js.map +1 -0
- package/dist/src/utils/logger.d.ts +11 -0
- package/dist/src/utils/logger.js +54 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/testingConfigurations.d.ts +7 -0
- package/dist/src/utils/testingConfigurations.js +16 -0
- package/dist/src/utils/testingConfigurations.js.map +1 -0
- package/package.json +82 -0
- package/src/config/configs.ts +145 -0
- package/src/config/constants.ts +83 -0
- package/src/config/init.ts +58 -0
- package/src/index.ts +15 -0
- package/src/jwtValidator.test.ts +607 -0
- package/src/jwtValidator.ts +162 -0
- package/src/middleware/jwtMiddleware.ts +33 -0
- package/src/models/customError.ts +37 -0
- package/src/models/expressRequest.ts +27 -0
- package/src/models/gluuUserType.ts +9 -0
- package/src/models/jwtPayload.ts +58 -0
- package/src/models/pagination.ts +26 -0
- package/src/models/publicKey.ts +33 -0
- package/src/repositories/cachedPublicKeyRepository.ts +121 -0
- package/src/repositories/publicKeyRepository.ts +75 -0
- package/src/userValidator.test.ts +279 -0
- package/src/userValidator.ts +54 -0
- package/src/utils/jwtMock.ts +243 -0
- package/src/utils/logger.ts +60 -0
- package/src/utils/testingConfigurations.ts +12 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { assert } from 'chai';
|
|
2
|
+
import * as nock from 'nock';
|
|
3
|
+
import * as validator from 'validator';
|
|
4
|
+
|
|
5
|
+
import { configs } from './config/configs';
|
|
6
|
+
import { IPaginatedResult } from './models/pagination';
|
|
7
|
+
import { IPublicKey, IPublicKeys, PublicKeyState } from './models/publicKey';
|
|
8
|
+
import { cachedPublicKeyRepository } from './repositories/cachedPublicKeyRepository';
|
|
9
|
+
import { UserValidator } from './userValidator';
|
|
10
|
+
import { setTestingConfigurations } from './utils/testingConfigurations';
|
|
11
|
+
|
|
12
|
+
// ==========================================
|
|
13
|
+
// Set Testing configurations
|
|
14
|
+
// ==========================================
|
|
15
|
+
setTestingConfigurations();
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
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
|
|
67
|
+
-----END RSA PRIVATE KEY-----`;
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
const nockPublicKey = `-----BEGIN PUBLIC KEY-----
|
|
71
|
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzVZZXij6LgAUuH6ZcvGM
|
|
72
|
+
vskXj+a8T5uBkvFFEPnTdRN7dYdWrhxeqsDkvwpyxJehMRAANCP+AYXgLE2BA7qt
|
|
73
|
+
u0SCW+Hj+1+ZubQqwaD/EQtk72yU04rJw4YfDg6VyQbSdUQRQ7ktjVitglj4dBZA
|
|
74
|
+
x99O+4guId52bRZrqSLe4OUVeRSI6tSV6n7ta+vsvPxUdAylFI9mAlh2we7vAu18
|
|
75
|
+
X7cC/5Rzq4NIuHhWpkOwwE6h7RUu7oqWfpNYl+Ugzp7qgd/vosP4FtDTW0+N82Jj
|
|
76
|
+
iuKILc1bWicynv5ka22R4wNrGewPGDCyTckogxrUYkx80YFad4UBF2hGzTDfXng4
|
|
77
|
+
gIU61eJTiB5gy3t6AgHHaVbDPnGZIefPlE+4A35Ics4uIV1z5Kbmq2+aaP+YXE42
|
|
78
|
+
a/WoYJfkXqOHs1PjIJmVj/szVRKyKbpq9Qp3xIM+YZQlYUvgql/O6vbl5N1NbkV3
|
|
79
|
+
Cjpp+zknfYXmSUJ+0FGK/ZGcFRmOSeLyJnULeFS5EAF7CUnLMEfi0hFEiyOXSngT
|
|
80
|
+
BIPL2GKsvtliZvPS78ik2mfXyG0YJQiVM7hYyRV+AnudI0Pz/zjX2DvjM0s3jMeI
|
|
81
|
+
om+l3zpAZ4SmFDkKzhAvuxoSl2koH+VXm9QtsRFSZQwF3/K5l3Zx0yi1e16dMOWw
|
|
82
|
+
YPtMOiCbEausVW7wgzdoj+kCAwEAAQ==
|
|
83
|
+
-----END PUBLIC KEY-----`;
|
|
84
|
+
|
|
85
|
+
let date: Date = new Date();
|
|
86
|
+
date.setHours(-1);
|
|
87
|
+
|
|
88
|
+
date.setMonth(date.getMonth() - 1);
|
|
89
|
+
const lastMonth = date.toISOString();
|
|
90
|
+
|
|
91
|
+
date.setMonth(date.getMonth() - 1);
|
|
92
|
+
const expiredDate = date.toISOString();
|
|
93
|
+
|
|
94
|
+
date = new Date();
|
|
95
|
+
date.setMonth(date.getMonth() + 1);
|
|
96
|
+
const newCreatedDate = date.toISOString();
|
|
97
|
+
|
|
98
|
+
date.setHours(date.getHours() + 1);
|
|
99
|
+
const newExpiredDate = date.toISOString();
|
|
100
|
+
|
|
101
|
+
const nocKPublicKeyExpired = {
|
|
102
|
+
id: 1,
|
|
103
|
+
algorithm: 'RSA256',
|
|
104
|
+
publicKey: nockPublicKey,
|
|
105
|
+
state: PublicKeyState.EXPIRED,
|
|
106
|
+
createdAt: expiredDate,
|
|
107
|
+
expiresAt: lastMonth,
|
|
108
|
+
};
|
|
109
|
+
const nocKPublicKeyExpiredNotState: IPublicKey = {
|
|
110
|
+
id: 2,
|
|
111
|
+
algorithm: 'RSA256',
|
|
112
|
+
publicKey: nockPublicKey,
|
|
113
|
+
state: PublicKeyState.ACTIVE,
|
|
114
|
+
createdAt: expiredDate,
|
|
115
|
+
expiresAt: lastMonth,
|
|
116
|
+
};
|
|
117
|
+
const nocKPublicKeyRevoked: IPublicKey = {
|
|
118
|
+
id: 3,
|
|
119
|
+
algorithm: 'RSA256',
|
|
120
|
+
publicKey: nockPublicKey,
|
|
121
|
+
state: PublicKeyState.REVOKED,
|
|
122
|
+
createdAt: lastMonth,
|
|
123
|
+
expiresAt: newExpiredDate,
|
|
124
|
+
};
|
|
125
|
+
const nocKPublicKeyActiveOld: IPublicKey = {
|
|
126
|
+
id: 4,
|
|
127
|
+
algorithm: 'RSA256',
|
|
128
|
+
publicKey: nockPublicKey,
|
|
129
|
+
state: PublicKeyState.ACTIVE,
|
|
130
|
+
createdAt: lastMonth,
|
|
131
|
+
expiresAt: newExpiredDate,
|
|
132
|
+
};
|
|
133
|
+
const nocKPublicKeyActive: IPublicKey = {
|
|
134
|
+
id: 5,
|
|
135
|
+
algorithm: 'RSA256',
|
|
136
|
+
publicKey: nockPublicKey,
|
|
137
|
+
state: PublicKeyState.ACTIVE,
|
|
138
|
+
createdAt: newCreatedDate,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const nockListPublicKeys: IPaginatedResult<IPublicKey> = {
|
|
142
|
+
paging: {
|
|
143
|
+
limit: 25,
|
|
144
|
+
offset: 0,
|
|
145
|
+
totalCount: 5,
|
|
146
|
+
},
|
|
147
|
+
items: [
|
|
148
|
+
nocKPublicKeyExpired,
|
|
149
|
+
nocKPublicKeyExpiredNotState,
|
|
150
|
+
nocKPublicKeyRevoked,
|
|
151
|
+
nocKPublicKeyActiveOld,
|
|
152
|
+
nocKPublicKeyActive,
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// ==========================================
|
|
157
|
+
// User Validator
|
|
158
|
+
// ==========================================
|
|
159
|
+
let publicKeys: IPublicKeys;
|
|
160
|
+
|
|
161
|
+
const regExpEscape = (s: any) => {
|
|
162
|
+
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const pathRegex = new RegExp(`${regExpEscape(configs.getEndpoint())}(.*)`);
|
|
166
|
+
|
|
167
|
+
it('User Validator - init app & get jwt public key', async () => {
|
|
168
|
+
nock.cleanAll();
|
|
169
|
+
|
|
170
|
+
cachedPublicKeyRepository.clearCache();
|
|
171
|
+
|
|
172
|
+
// Intercept request
|
|
173
|
+
nock(configs.getHost()).get(pathRegex).reply(200, nockListPublicKeys);
|
|
174
|
+
|
|
175
|
+
publicKeys = await cachedPublicKeyRepository.getAll();
|
|
176
|
+
|
|
177
|
+
assert.match(publicKeys[1].publicKey, /^-----BEGIN PUBLIC KEY-----\n/m);
|
|
178
|
+
assert.match(publicKeys[1].publicKey, /^-----BEGIN PUBLIC KEY-----\n/m);
|
|
179
|
+
assert.match(publicKeys[1].publicKey, /\n-----END PUBLIC KEY-----$/m);
|
|
180
|
+
|
|
181
|
+
const key: string = publicKeys[1].publicKey
|
|
182
|
+
.replace(/^-----BEGIN PUBLIC KEY-----\n/m, '')
|
|
183
|
+
.replace(/\n-----END PUBLIC KEY-----$/m, '')
|
|
184
|
+
.split('\n')
|
|
185
|
+
.join('');
|
|
186
|
+
assert.isTrue(validator.default.isBase64(key));
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const mockRequest = require('mock-express-request');
|
|
190
|
+
|
|
191
|
+
it('should consider mtlIdentityId field when verifying user', async () => {
|
|
192
|
+
let hasThrown = false;
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
const userId = 'voodoo';
|
|
196
|
+
const request = new mockRequest();
|
|
197
|
+
|
|
198
|
+
request.jwt = {
|
|
199
|
+
mtlIdentityId: 'voodoo',
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const userValidator: UserValidator = new UserValidator(request);
|
|
203
|
+
userValidator.verifyUser(userId);
|
|
204
|
+
} catch (err) {
|
|
205
|
+
hasThrown = true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
assert.isFalse(hasThrown);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should throw when either fields are matching', async () => {
|
|
212
|
+
let hasThrown = false;
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
const userId = 'wrongVoodoo';
|
|
216
|
+
const request = new mockRequest();
|
|
217
|
+
|
|
218
|
+
request.jwt = {
|
|
219
|
+
mtlIdentityId: 'voodoo',
|
|
220
|
+
sub: 'voodoo',
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const userValidator: UserValidator = new UserValidator(request);
|
|
224
|
+
userValidator.verifyUser(userId);
|
|
225
|
+
} catch (err) {
|
|
226
|
+
hasThrown = true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
assert.isTrue(hasThrown);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
it('User Validator - verifyHeaderUser - should reject missing inum ', async function () {
|
|
234
|
+
|
|
235
|
+
let token: string = jwt.sign('{"a":"a", "keyId": 4}', nockPrivateKey, { algorithm: 'RS256' });
|
|
236
|
+
|
|
237
|
+
let response = await jwtValidator.verifyHeaderUser('Bearer ' + token, 'MyInum')
|
|
238
|
+
.catch((err) => {
|
|
239
|
+
assert.strictEqual(err.error.code, constants.errors.codes.INVALID_JWT);
|
|
240
|
+
assert.strictEqual(err.error.target, 'Authorization header');
|
|
241
|
+
assert.strictEqual(err.error.message, "Invalid JWT");
|
|
242
|
+
assert.strictEqual(err.error.details[0].code, constants.errors.codes.INVALID_VALUE);
|
|
243
|
+
assert.strictEqual(err.error.details[0].target, 'jwt');
|
|
244
|
+
assert.strictEqual(err.error.details[0].message, 'Invalid JWT content');
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
assert.isUndefined(response);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('User Validator - verifyHeaderUser - should reject bad inum ', async function () {
|
|
251
|
+
|
|
252
|
+
let token: string = jwt.sign('{"inum":"a", "keyId": 4}', nockPrivateKey, { algorithm: 'RS256' });
|
|
253
|
+
|
|
254
|
+
let response = await jwtValidator.verifyHeaderUser('Bearer ' + token, 'MyInum')
|
|
255
|
+
.catch((err) => {
|
|
256
|
+
assert.strictEqual(err.error.code, constants.errors.codes.INVALID_JWT);
|
|
257
|
+
assert.strictEqual(err.error.target, 'Authorization header');
|
|
258
|
+
assert.strictEqual(err.error.message, "Invalid JWT");
|
|
259
|
+
assert.strictEqual(err.error.details[0].code, constants.errors.codes.UNAUTHORIZED_ACCESS);
|
|
260
|
+
assert.strictEqual(err.error.details[0].target, 'jwt');
|
|
261
|
+
assert.strictEqual(err.error.details[0].message, 'Unauthorized access');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
assert.isUndefined(response);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('User Validator - verifyHeaderUser - should accept good token ', async function () {
|
|
268
|
+
|
|
269
|
+
let payload: any = {
|
|
270
|
+
inum: "MyInum",
|
|
271
|
+
keyId: 4
|
|
272
|
+
};
|
|
273
|
+
let token: string = jwt.sign(JSON.stringify(payload), nockPrivateKey, { algorithm: 'RS256' });
|
|
274
|
+
|
|
275
|
+
let response = await jwtValidator.verifyHeaderUser('Bearer ' + token, 'MyInum');
|
|
276
|
+
|
|
277
|
+
assert.deepEqual(response, payload);
|
|
278
|
+
});
|
|
279
|
+
*/
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as express from 'express';
|
|
2
|
+
import { constants } from './config/constants';
|
|
3
|
+
import { createInvalidJwtError } from './models/customError';
|
|
4
|
+
import { IRequestWithJwt, isRequestWithJwt } from './models/expressRequest';
|
|
5
|
+
|
|
6
|
+
export interface IUserValidator {
|
|
7
|
+
/**
|
|
8
|
+
* TODO commentaire pas à jour
|
|
9
|
+
* Verify a header containg a jwt and check the jwt with the public key and returns the decoded payload
|
|
10
|
+
* @param {string} userId
|
|
11
|
+
* @return {void}
|
|
12
|
+
*/
|
|
13
|
+
isUser(userId: string): boolean;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* TODO commentaire pas à jour
|
|
17
|
+
* Verify a header containg a jwt and check the jwt with the public key and returns the decoded payload
|
|
18
|
+
* @param {string} userId
|
|
19
|
+
* @return {void}
|
|
20
|
+
*/
|
|
21
|
+
verifyUser(userId: string): void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* User Validator
|
|
26
|
+
*/
|
|
27
|
+
export class UserValidator implements IUserValidator {
|
|
28
|
+
private _request: IRequestWithJwt;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Create a new instance of UserValidator
|
|
32
|
+
* @param {express.Request} req
|
|
33
|
+
*/
|
|
34
|
+
public constructor(req: express.Request) {
|
|
35
|
+
if (!isRequestWithJwt(req)) {
|
|
36
|
+
throw new Error(`Expecting a request with a '.jwt' here! : ${req}`);
|
|
37
|
+
}
|
|
38
|
+
this._request = req;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public isUser(userId: string) {
|
|
42
|
+
return this._request.jwt.sub !== userId;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public verifyUser(userId: string) {
|
|
46
|
+
if (this._request.jwt.sub !== userId && this._request.jwt.mtlIdentityId !== userId) {
|
|
47
|
+
throw createInvalidJwtError({
|
|
48
|
+
code: constants.errors.codes.UNAUTHORIZED_ACCESS,
|
|
49
|
+
target: 'jwt',
|
|
50
|
+
message: 'Unauthorized access',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import * as jwt from 'jsonwebtoken';
|
|
2
|
+
import { defaults } from 'lodash';
|
|
3
|
+
// import * as nock from 'nock';
|
|
4
|
+
import { configs } from '../config/configs';
|
|
5
|
+
import { IJWTPayload } from '../models/jwtPayload';
|
|
6
|
+
import { IPublicKey, PublicKeyState } from '../models/publicKey';
|
|
7
|
+
import { cachedPublicKeyRepository } from '../repositories/cachedPublicKeyRepository';
|
|
8
|
+
|
|
9
|
+
let nock: any;
|
|
10
|
+
|
|
11
|
+
const nockPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
|
12
|
+
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
|
|
61
|
+
-----END RSA PRIVATE KEY-----`;
|
|
62
|
+
|
|
63
|
+
const nockPublicKey = `-----BEGIN PUBLIC KEY-----
|
|
64
|
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzVZZXij6LgAUuH6ZcvGM
|
|
65
|
+
vskXj+a8T5uBkvFFEPnTdRN7dYdWrhxeqsDkvwpyxJehMRAANCP+AYXgLE2BA7qt
|
|
66
|
+
u0SCW+Hj+1+ZubQqwaD/EQtk72yU04rJw4YfDg6VyQbSdUQRQ7ktjVitglj4dBZA
|
|
67
|
+
x99O+4guId52bRZrqSLe4OUVeRSI6tSV6n7ta+vsvPxUdAylFI9mAlh2we7vAu18
|
|
68
|
+
X7cC/5Rzq4NIuHhWpkOwwE6h7RUu7oqWfpNYl+Ugzp7qgd/vosP4FtDTW0+N82Jj
|
|
69
|
+
iuKILc1bWicynv5ka22R4wNrGewPGDCyTckogxrUYkx80YFad4UBF2hGzTDfXng4
|
|
70
|
+
gIU61eJTiB5gy3t6AgHHaVbDPnGZIefPlE+4A35Ics4uIV1z5Kbmq2+aaP+YXE42
|
|
71
|
+
a/WoYJfkXqOHs1PjIJmVj/szVRKyKbpq9Qp3xIM+YZQlYUvgql/O6vbl5N1NbkV3
|
|
72
|
+
Cjpp+zknfYXmSUJ+0FGK/ZGcFRmOSeLyJnULeFS5EAF7CUnLMEfi0hFEiyOXSngT
|
|
73
|
+
BIPL2GKsvtliZvPS78ik2mfXyG0YJQiVM7hYyRV+AnudI0Pz/zjX2DvjM0s3jMeI
|
|
74
|
+
om+l3zpAZ4SmFDkKzhAvuxoSl2koH+VXm9QtsRFSZQwF3/K5l3Zx0yi1e16dMOWw
|
|
75
|
+
YPtMOiCbEausVW7wgzdoj+kCAwEAAQ==
|
|
76
|
+
-----END PUBLIC KEY-----`;
|
|
77
|
+
|
|
78
|
+
let date = new Date();
|
|
79
|
+
|
|
80
|
+
date.setHours(-1);
|
|
81
|
+
|
|
82
|
+
date.setMonth(date.getMonth() - 1);
|
|
83
|
+
const lastMonth = date.toISOString();
|
|
84
|
+
|
|
85
|
+
date.setMonth(date.getMonth() - 1);
|
|
86
|
+
const expiredDate = date.toISOString();
|
|
87
|
+
|
|
88
|
+
date = new Date();
|
|
89
|
+
date.setMonth(date.getMonth() + 1);
|
|
90
|
+
const newCreatedDate = date.toISOString();
|
|
91
|
+
date.setHours(date.getHours() + 1);
|
|
92
|
+
const newExpiredDate = date.toISOString();
|
|
93
|
+
|
|
94
|
+
const nocKPublicKeyExpired: IPublicKey = {
|
|
95
|
+
id: 1,
|
|
96
|
+
algorithm: 'RSA256',
|
|
97
|
+
publicKey: nockPublicKey,
|
|
98
|
+
state: PublicKeyState.EXPIRED,
|
|
99
|
+
createdAt: expiredDate,
|
|
100
|
+
expiresAt: lastMonth,
|
|
101
|
+
};
|
|
102
|
+
const nocKPublicKeyExpiredNotState: IPublicKey = {
|
|
103
|
+
id: 2,
|
|
104
|
+
algorithm: 'RSA256',
|
|
105
|
+
publicKey: nockPublicKey,
|
|
106
|
+
state: PublicKeyState.ACTIVE,
|
|
107
|
+
createdAt: expiredDate,
|
|
108
|
+
expiresAt: lastMonth,
|
|
109
|
+
};
|
|
110
|
+
const nocKPublicKeyRevoked: IPublicKey = {
|
|
111
|
+
id: 3,
|
|
112
|
+
algorithm: 'RSA256',
|
|
113
|
+
publicKey: nockPublicKey,
|
|
114
|
+
state: PublicKeyState.REVOKED,
|
|
115
|
+
createdAt: lastMonth,
|
|
116
|
+
expiresAt: newExpiredDate,
|
|
117
|
+
};
|
|
118
|
+
const nocKPublicKeyActiveOld: IPublicKey = {
|
|
119
|
+
id: 4,
|
|
120
|
+
algorithm: 'RSA256',
|
|
121
|
+
publicKey: nockPublicKey,
|
|
122
|
+
state: PublicKeyState.ACTIVE,
|
|
123
|
+
createdAt: lastMonth,
|
|
124
|
+
expiresAt: newExpiredDate,
|
|
125
|
+
};
|
|
126
|
+
const nocKPublicKeyActive: IPublicKey = {
|
|
127
|
+
id: 5,
|
|
128
|
+
algorithm: 'RSA256',
|
|
129
|
+
publicKey: nockPublicKey,
|
|
130
|
+
state: PublicKeyState.ACTIVE,
|
|
131
|
+
createdAt: newCreatedDate,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const nockListPublicKeys: any = {
|
|
135
|
+
paging: {
|
|
136
|
+
limit: 25,
|
|
137
|
+
offset: 0,
|
|
138
|
+
totalCount: 5,
|
|
139
|
+
},
|
|
140
|
+
items: [
|
|
141
|
+
nocKPublicKeyExpired,
|
|
142
|
+
nocKPublicKeyExpiredNotState,
|
|
143
|
+
nocKPublicKeyRevoked,
|
|
144
|
+
nocKPublicKeyActiveOld,
|
|
145
|
+
nocKPublicKeyActive,
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const regExpEscape = (s: any) => {
|
|
150
|
+
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const pathRegex = new RegExp(`${regExpEscape(configs.getEndpoint())}(.*)`);
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Tools to mock JWT
|
|
157
|
+
*/
|
|
158
|
+
export class JwtMock {
|
|
159
|
+
/**
|
|
160
|
+
* Return a public key from the mock db
|
|
161
|
+
*/
|
|
162
|
+
public getPublicKey(keyId: number): IPublicKey {
|
|
163
|
+
const key: IPublicKey = nockListPublicKeys.items[keyId - 1];
|
|
164
|
+
|
|
165
|
+
return key;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Return the public keys from the mock db
|
|
170
|
+
*/
|
|
171
|
+
public getPublicKeys(): IPublicKey[] {
|
|
172
|
+
return nockListPublicKeys.items;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Return the private keys from the mock db
|
|
177
|
+
*/
|
|
178
|
+
public getPrivateKey(): string {
|
|
179
|
+
return nockPrivateKey;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Flush the public keys in cache and add the mocked public keys
|
|
184
|
+
*/
|
|
185
|
+
public async mockPublicKeys(options?: any): Promise<void> {
|
|
186
|
+
cachedPublicKeyRepository.clearCache();
|
|
187
|
+
|
|
188
|
+
// Intercept request
|
|
189
|
+
if (!nock) {
|
|
190
|
+
// Note that we lazy-load the nock module
|
|
191
|
+
// until we really need it, to avoid patching
|
|
192
|
+
// the http module for nothing.
|
|
193
|
+
nock = require('nock');
|
|
194
|
+
}
|
|
195
|
+
nock(configs.getHost(), options).get(pathRegex).once().reply(200, nockListPublicKeys);
|
|
196
|
+
|
|
197
|
+
await cachedPublicKeyRepository.getAll();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Generate a fake JWT signed with the mocked keys
|
|
202
|
+
*/
|
|
203
|
+
public generateJwt(jwtProperties = {}): string {
|
|
204
|
+
const jwtPayload: IJWTPayload = defaults(jwtProperties, {
|
|
205
|
+
accessToken: 'c9ba5a95-d7f9-41f9-9a24-a7e41882f7ef',
|
|
206
|
+
iss: 'jwt-mock',
|
|
207
|
+
|
|
208
|
+
// From Introspect
|
|
209
|
+
exp: Date.now() + 3600,
|
|
210
|
+
iat: Date.now(),
|
|
211
|
+
keyId: 5,
|
|
212
|
+
|
|
213
|
+
// From ClientInfo
|
|
214
|
+
displayName: 'Service Account',
|
|
215
|
+
aud: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0008!2212.0010',
|
|
216
|
+
|
|
217
|
+
// From UserInfo
|
|
218
|
+
name: 'Guillaume Smaha',
|
|
219
|
+
sub: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
|
|
220
|
+
inum: '@!4025.CA62.9BB6.16C5!0001!2212.0010!0000!0000.0001',
|
|
221
|
+
userName: 'xsmahgu@ville.montreal.qc.ca',
|
|
222
|
+
givenName: 'Guillaume',
|
|
223
|
+
familyName: 'Smaha',
|
|
224
|
+
userType: '',
|
|
225
|
+
mtlIdentityId: '100-qwerty-azerty-dvorak',
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const jwtSigned: string = jwt.sign(jwtPayload, nockPrivateKey, {
|
|
229
|
+
algorithm: 'RS256',
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
return jwtSigned;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Deletes all mocks and also clears the cache
|
|
237
|
+
*/
|
|
238
|
+
public cleanAll(): void {
|
|
239
|
+
nock.cleanAll();
|
|
240
|
+
cachedPublicKeyRepository.clearCache();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
export const jwtMock: JwtMock = new JwtMock();
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ILogger,
|
|
3
|
+
initLogger,
|
|
4
|
+
LazyLogger,
|
|
5
|
+
Logger,
|
|
6
|
+
LoggerConfigs,
|
|
7
|
+
LogLevel,
|
|
8
|
+
} from '@villedemontreal/logger';
|
|
9
|
+
import { configs } from '../config/configs';
|
|
10
|
+
|
|
11
|
+
let testingLoggerLibInitialised = false;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Logger.
|
|
15
|
+
*/
|
|
16
|
+
export function createLogger(name: string): ILogger {
|
|
17
|
+
// ==========================================
|
|
18
|
+
// We use a LazyLogger so the real Logger
|
|
19
|
+
// is only created when the first
|
|
20
|
+
// log is actually performed... At that point,
|
|
21
|
+
// our "configs.loggerCreator" configuration
|
|
22
|
+
// must have been set by the code using our library!
|
|
23
|
+
//
|
|
24
|
+
// This pattern allows calling code to import
|
|
25
|
+
// modules from us in which a logger is
|
|
26
|
+
// created in the global scope :
|
|
27
|
+
//
|
|
28
|
+
// let logger = createLogger('someName');
|
|
29
|
+
//
|
|
30
|
+
// Without a Lazy Logger, the library configurations
|
|
31
|
+
// would at that moment *not* have been set yet
|
|
32
|
+
// (by the calling code) and an Error would be thrown
|
|
33
|
+
// because the "configs.loggerCreator" is required.
|
|
34
|
+
// ==========================================
|
|
35
|
+
return new LazyLogger(name, (nameArg: string) => {
|
|
36
|
+
return configs.loggerCreator(nameArg);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function initTestingLoggerConfigs() {
|
|
41
|
+
const loggerConfig: LoggerConfigs = new LoggerConfigs(() => 'test-cid');
|
|
42
|
+
loggerConfig.setLogLevel(LogLevel.DEBUG);
|
|
43
|
+
initLogger(loggerConfig);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A Logger that uses a dummy cid provider.
|
|
48
|
+
*
|
|
49
|
+
* Only use this when running the tests!
|
|
50
|
+
*/
|
|
51
|
+
export function getTestingLoggerCreator(): (name: string) => ILogger {
|
|
52
|
+
return (name: string): ILogger => {
|
|
53
|
+
if (!testingLoggerLibInitialised) {
|
|
54
|
+
initTestingLoggerConfigs();
|
|
55
|
+
testingLoggerLibInitialised = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return new Logger(name);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { init } from '../config/init';
|
|
2
|
+
import { getTestingLoggerCreator } from '../utils/logger';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Call this when your need to set
|
|
6
|
+
* *Testing* configurations to the current
|
|
7
|
+
* library, without the need for a calling code
|
|
8
|
+
* to do so.
|
|
9
|
+
*/
|
|
10
|
+
export function setTestingConfigurations(): void {
|
|
11
|
+
init(getTestingLoggerCreator(), () => 'test-cid', 'https://api.dev.interne.montreal.ca');
|
|
12
|
+
}
|