@axinom/mosaic-id-guard 0.20.8-rc.3 → 0.21.0-rc.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/common/get-authenticated-subject.d.ts.map +1 -1
- package/dist/common/get-authenticated-subject.js +2 -13
- package/dist/common/get-authenticated-subject.js.map +1 -1
- package/dist/common/jwks-client.d.ts +9 -0
- package/dist/common/jwks-client.d.ts.map +1 -0
- package/dist/common/jwks-client.js +30 -0
- package/dist/common/jwks-client.js.map +1 -0
- package/dist/common/parse-jwt-token.d.ts +8 -0
- package/dist/common/parse-jwt-token.d.ts.map +1 -1
- package/dist/common/parse-jwt-token.js +35 -1
- package/dist/common/parse-jwt-token.js.map +1 -1
- package/package.json +5 -5
- package/src/common/get-authenticated-subject.ts +2 -14
- package/src/common/jwks-client.ts +25 -0
- package/src/common/parse-jwt-token.spec.ts +79 -2
- package/src/common/parse-jwt-token.ts +44 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-authenticated-subject.d.ts","sourceRoot":"","sources":["../../src/common/get-authenticated-subject.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,8BAA8B,EAC9B,oBAAoB,EACrB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"get-authenticated-subject.d.ts","sourceRoot":"","sources":["../../src/common/get-authenticated-subject.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,oBAAoB,EACpB,+BAA+B,EAC/B,8BAA8B,EAC9B,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,2BAA2B,gCAAgC,CAAC;AAEzE;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,UACrC,MAAM,cACD,MAAM,GAAG,oBAAoB,KACxC,QAAQ,8BAA8B,CAsDxC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,UAC3B,MAAM,cACD,MAAM,GAAG,oBAAoB,KACxC,QAAQ,oBAAoB,GAAG,+BAA+B,CAqEhE,CAAC"}
|
|
@@ -6,15 +6,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.getAuthenticatedEndUser = exports.getAuthenticatedManagementSubject = exports.EMBEDDED_END_USER_TOKEN_KEY = void 0;
|
|
7
7
|
const mosaic_service_common_1 = require("@axinom/mosaic-service-common");
|
|
8
8
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
9
|
-
const jwks_rsa_1 = __importDefault(require("jwks-rsa"));
|
|
10
|
-
const lru_cache_1 = __importDefault(require("lru-cache"));
|
|
11
9
|
const id_guard_error_1 = require("./id-guard-error");
|
|
12
10
|
const id_guard_errors_1 = require("./id-guard-errors");
|
|
11
|
+
const jwks_client_1 = require("./jwks-client");
|
|
13
12
|
const jwt_verify_options_1 = require("./jwt-verify-options");
|
|
14
13
|
const subject_type_1 = require("./subject-type");
|
|
15
|
-
const jwksClientCache = new lru_cache_1.default({
|
|
16
|
-
max: 1000,
|
|
17
|
-
});
|
|
18
14
|
exports.EMBEDDED_END_USER_TOKEN_KEY = 'mosaic.end-user.accessToken';
|
|
19
15
|
/**
|
|
20
16
|
* Parses a JWT token to produce an `AuthenticatedManagementSubject`.
|
|
@@ -126,14 +122,7 @@ const getAuthenticatedEndUser = async (token, authParams) => {
|
|
|
126
122
|
exports.getAuthenticatedEndUser = getAuthenticatedEndUser;
|
|
127
123
|
const verifyTokenAndGetAuthenticatedSubject = async (token, jwksUri, authType) => {
|
|
128
124
|
return new Promise((resolve, reject) => {
|
|
129
|
-
|
|
130
|
-
const jwksClient = (_a = jwksClientCache.get(jwksUri)) !== null && _a !== void 0 ? _a : (0, jwks_rsa_1.default)({
|
|
131
|
-
jwksUri,
|
|
132
|
-
cache: true,
|
|
133
|
-
cacheMaxAge: 1000 * 60 * 10,
|
|
134
|
-
cacheMaxEntries: 100,
|
|
135
|
-
});
|
|
136
|
-
jwksClientCache.set(jwksUri, jwksClient);
|
|
125
|
+
const jwksClient = (0, jwks_client_1.getJwksClient)(jwksUri);
|
|
137
126
|
const getPublicKey = (header, callback) => {
|
|
138
127
|
var _a;
|
|
139
128
|
jwksClient.getSigningKey((_a = header.kid) !== null && _a !== void 0 ? _a : 'MISSING_KEY_ID_IN_JWT_HEADER', (error, key) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-authenticated-subject.js","sourceRoot":"","sources":["../../src/common/get-authenticated-subject.ts"],"names":[],"mappings":";;;;;;AAAA,yEAAmE;AACnE,gEAA+B;
|
|
1
|
+
{"version":3,"file":"get-authenticated-subject.js","sourceRoot":"","sources":["../../src/common/get-authenticated-subject.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwks-client.d.ts","sourceRoot":"","sources":["../../src/common/jwks-client.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,UAAU,CAAC;AAO5B;;;;;GAKG;AACH,eAAO,MAAM,aAAa,YAAa,MAAM,KAAG,KAAK,UAWpD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getJwksClient = void 0;
|
|
7
|
+
const jwks_rsa_1 = __importDefault(require("jwks-rsa"));
|
|
8
|
+
const lru_cache_1 = __importDefault(require("lru-cache"));
|
|
9
|
+
const jwksClientCache = new lru_cache_1.default({
|
|
10
|
+
max: 1000,
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Returns a cached JWKS Client for a given jwks URI.
|
|
14
|
+
*
|
|
15
|
+
* @param jwksUri
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
const getJwksClient = (jwksUri) => {
|
|
19
|
+
var _a;
|
|
20
|
+
const jwksClient = (_a = jwksClientCache.get(jwksUri)) !== null && _a !== void 0 ? _a : (0, jwks_rsa_1.default)({
|
|
21
|
+
jwksUri,
|
|
22
|
+
cache: true,
|
|
23
|
+
cacheMaxAge: 1000 * 60 * 10,
|
|
24
|
+
cacheMaxEntries: 100,
|
|
25
|
+
});
|
|
26
|
+
jwksClientCache.set(jwksUri, jwksClient);
|
|
27
|
+
return jwksClient;
|
|
28
|
+
};
|
|
29
|
+
exports.getJwksClient = getJwksClient;
|
|
30
|
+
//# sourceMappingURL=jwks-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwks-client.js","sourceRoot":"","sources":["../../src/common/jwks-client.ts"],"names":[],"mappings":";;;;;;AAAA,wDAA4B;AAC5B,0DAAiC;AAEjC,MAAM,eAAe,GAAG,IAAI,mBAAQ,CAA0B;IAC5D,GAAG,EAAE,IAAI;CACV,CAAC,CAAC;AAEH;;;;;GAKG;AACI,MAAM,aAAa,GAAG,CAAC,OAAe,EAAmB,EAAE;;IAChE,MAAM,UAAU,GACd,MAAA,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,mCAC5B,IAAA,kBAAI,EAAC;QACH,OAAO;QACP,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE;QAC3B,eAAe,EAAE,GAAG;KACrB,CAAC,CAAC;IACL,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACzC,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AAXW,QAAA,aAAa,iBAWxB"}
|
|
@@ -18,4 +18,12 @@ export declare const decodeManagementAccessToken: (token: string) => Authenticat
|
|
|
18
18
|
* @returns An object of type `AuthenticatedEndUser`
|
|
19
19
|
*/
|
|
20
20
|
export declare const decodeEndUserAccessToken: (token: string) => AuthenticatedEndUser;
|
|
21
|
+
/**
|
|
22
|
+
* Returns if the KID used to sign a JWT is available in the active JWKS.
|
|
23
|
+
*
|
|
24
|
+
* @param token
|
|
25
|
+
* @param authConfig
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
export declare const checkSigningKeyExists: (token: string, idServiceAuthBaseUrl: string) => Promise<boolean>;
|
|
21
29
|
//# sourceMappingURL=parse-jwt-token.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-jwt-token.d.ts","sourceRoot":"","sources":["../../src/common/parse-jwt-token.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-jwt-token.d.ts","sourceRoot":"","sources":["../../src/common/parse-jwt-token.ts"],"names":[],"mappings":"AAgBA,OAAO,EACL,oBAAoB,EAEpB,8BAA8B,EAC9B,oBAAoB,EACpB,4BAA4B,EAC5B,+BAA+B,EAChC,MAAM,SAAS,CAAC;AAEjB;;;;;GAKG;AACH,eAAO,MAAM,aAAa,UACjB,MAAM,GAAG,SAAS,cACb,MAAM,GAAG,oBAAoB,aAC9B,YAAY,GAAG,UAAU,KACnC,QAAQ,+BAA+B,GAAG,4BAA4B,CAiFxE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,UAC/B,MAAM,KACZ,8BAEF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,UAC5B,MAAM,KACZ,oBAEF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,UACzB,MAAM,wBACS,MAAM,KAC3B,QAAQ,OAAO,CA8BjB,CAAC"}
|
|
@@ -26,13 +26,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.decodeEndUserAccessToken = exports.decodeManagementAccessToken = exports.parseJwtToken = void 0;
|
|
29
|
+
exports.checkSigningKeyExists = exports.decodeEndUserAccessToken = exports.decodeManagementAccessToken = exports.parseJwtToken = void 0;
|
|
30
30
|
const mosaic_service_common_1 = require("@axinom/mosaic-service-common");
|
|
31
31
|
const fs = __importStar(require("fs"));
|
|
32
32
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
33
33
|
const get_authenticated_subject_1 = require("./get-authenticated-subject");
|
|
34
34
|
const helpers_1 = require("./helpers");
|
|
35
35
|
const id_guard_errors_1 = require("./id-guard-errors");
|
|
36
|
+
const jwks_client_1 = require("./jwks-client");
|
|
36
37
|
const jwt_verify_options_1 = require("./jwt-verify-options");
|
|
37
38
|
const subject_type_1 = require("./subject-type");
|
|
38
39
|
/**
|
|
@@ -137,4 +138,37 @@ const decodeEndUserAccessToken = (token) => {
|
|
|
137
138
|
return jsonwebtoken_1.default.decode(token);
|
|
138
139
|
};
|
|
139
140
|
exports.decodeEndUserAccessToken = decodeEndUserAccessToken;
|
|
141
|
+
/**
|
|
142
|
+
* Returns if the KID used to sign a JWT is available in the active JWKS.
|
|
143
|
+
*
|
|
144
|
+
* @param token
|
|
145
|
+
* @param authConfig
|
|
146
|
+
* @returns
|
|
147
|
+
*/
|
|
148
|
+
const checkSigningKeyExists = async (token, idServiceAuthBaseUrl) => {
|
|
149
|
+
return new Promise((resolve, reject) => {
|
|
150
|
+
const decodedJwt = jsonwebtoken_1.default.decode(token, { complete: true });
|
|
151
|
+
if (decodedJwt === null) {
|
|
152
|
+
reject('Invalid JWT received');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const subject = decodedJwt === null || decodedJwt === void 0 ? void 0 : decodedJwt.payload;
|
|
156
|
+
const jwksUri = new URL(`/${subject.tenantId}/${subject.environmentId}/.well-known/jwks.json`, idServiceAuthBaseUrl);
|
|
157
|
+
const jwksClient = (0, jwks_client_1.getJwksClient)(jwksUri.toString());
|
|
158
|
+
jwksClient.getKeys((error, keys) => {
|
|
159
|
+
if (error) {
|
|
160
|
+
reject(error);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const signingKeys = keys;
|
|
164
|
+
for (const idx in signingKeys) {
|
|
165
|
+
if (signingKeys[idx]['kid'] === (decodedJwt === null || decodedJwt === void 0 ? void 0 : decodedJwt.header.kid)) {
|
|
166
|
+
return resolve(true);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return resolve(false);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
exports.checkSigningKeyExists = checkSigningKeyExists;
|
|
140
174
|
//# sourceMappingURL=parse-jwt-token.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-jwt-token.js","sourceRoot":"","sources":["../../src/common/parse-jwt-token.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yEAGuC;AACvC,uCAAyB;AACzB,gEAA+B;
|
|
1
|
+
{"version":3,"file":"parse-jwt-token.js","sourceRoot":"","sources":["../../src/common/parse-jwt-token.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axinom/mosaic-id-guard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0-rc.0",
|
|
4
4
|
"description": "Authentication and authorization helpers for Axinom Mosaic services",
|
|
5
5
|
"author": "Axinom",
|
|
6
6
|
"license": "PROPRIETARY",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"lint": "eslint . --ext .ts,.tsx,.js --color --cache"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@axinom/mosaic-id-utils": "^0.15.6-rc.
|
|
32
|
-
"@axinom/mosaic-message-bus": "^0.16.0-rc.
|
|
33
|
-
"@axinom/mosaic-service-common": "^0.37.0-rc.
|
|
31
|
+
"@axinom/mosaic-id-utils": "^0.15.6-rc.5",
|
|
32
|
+
"@axinom/mosaic-message-bus": "^0.16.0-rc.5",
|
|
33
|
+
"@axinom/mosaic-service-common": "^0.37.0-rc.5",
|
|
34
34
|
"amqplib": "^0.10.3",
|
|
35
35
|
"express": "^4.17.1",
|
|
36
36
|
"express-bearer-token": "^2.4.0",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"publishConfig": {
|
|
63
63
|
"access": "public"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "ba8df1bbe8a5a3035f95527d31264491c53f3d33"
|
|
66
66
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isNullOrWhitespace } from '@axinom/mosaic-service-common';
|
|
2
2
|
import jwt from 'jsonwebtoken';
|
|
3
3
|
import jwks from 'jwks-rsa';
|
|
4
|
-
import LRUCache from 'lru-cache';
|
|
5
4
|
import { IdGuardError } from './id-guard-error';
|
|
6
5
|
import { IdGuardErrors } from './id-guard-errors';
|
|
6
|
+
import { getJwksClient } from './jwks-client';
|
|
7
7
|
import {
|
|
8
8
|
getJwtVerifyOptions,
|
|
9
9
|
TOKEN_ISSUER_ID_SERVICE,
|
|
@@ -17,10 +17,6 @@ import {
|
|
|
17
17
|
AuthenticationConfig,
|
|
18
18
|
} from './types';
|
|
19
19
|
|
|
20
|
-
const jwksClientCache = new LRUCache<string, jwks.JwksClient>({
|
|
21
|
-
max: 1000,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
20
|
export const EMBEDDED_END_USER_TOKEN_KEY = 'mosaic.end-user.accessToken';
|
|
25
21
|
|
|
26
22
|
/**
|
|
@@ -186,15 +182,7 @@ const verifyTokenAndGetAuthenticatedSubject = async (
|
|
|
186
182
|
| AuthenticatedEndUser
|
|
187
183
|
| AuthenticatedEndUserApplication
|
|
188
184
|
>((resolve, reject) => {
|
|
189
|
-
const jwksClient =
|
|
190
|
-
jwksClientCache.get(jwksUri) ??
|
|
191
|
-
jwks({
|
|
192
|
-
jwksUri,
|
|
193
|
-
cache: true,
|
|
194
|
-
cacheMaxAge: 1000 * 60 * 10, // 10 Minutes (same as access token lifetime)
|
|
195
|
-
cacheMaxEntries: 100,
|
|
196
|
-
});
|
|
197
|
-
jwksClientCache.set(jwksUri, jwksClient);
|
|
185
|
+
const jwksClient = getJwksClient(jwksUri);
|
|
198
186
|
|
|
199
187
|
const getPublicKey: jwt.GetPublicKeyOrSecret = (
|
|
200
188
|
header: jwt.JwtHeader,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import jwks from 'jwks-rsa';
|
|
2
|
+
import LRUCache from 'lru-cache';
|
|
3
|
+
|
|
4
|
+
const jwksClientCache = new LRUCache<string, jwks.JwksClient>({
|
|
5
|
+
max: 1000,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns a cached JWKS Client for a given jwks URI.
|
|
10
|
+
*
|
|
11
|
+
* @param jwksUri
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
14
|
+
export const getJwksClient = (jwksUri: string): jwks.JwksClient => {
|
|
15
|
+
const jwksClient =
|
|
16
|
+
jwksClientCache.get(jwksUri) ??
|
|
17
|
+
jwks({
|
|
18
|
+
jwksUri,
|
|
19
|
+
cache: true,
|
|
20
|
+
cacheMaxAge: 1000 * 60 * 10, // 10 Minutes (same as access token lifetime)
|
|
21
|
+
cacheMaxEntries: 100,
|
|
22
|
+
});
|
|
23
|
+
jwksClientCache.set(jwksUri, jwksClient);
|
|
24
|
+
return jwksClient;
|
|
25
|
+
};
|
|
@@ -2,8 +2,10 @@ import * as fs from 'fs';
|
|
|
2
2
|
import jwt, { TokenExpiredError } from 'jsonwebtoken';
|
|
3
3
|
import { JwksError, SigningKeyNotFoundError } from 'jwks-rsa';
|
|
4
4
|
import * as getAuthenticatedSubject from './get-authenticated-subject';
|
|
5
|
-
import
|
|
5
|
+
import * as jwksClient from './jwks-client';
|
|
6
|
+
import { checkSigningKeyExists, parseJwtToken } from './parse-jwt-token';
|
|
6
7
|
import { AuthenticatedEndUser, AuthenticatedManagementSubject } from './types';
|
|
8
|
+
|
|
7
9
|
/*
|
|
8
10
|
{
|
|
9
11
|
"tenantId": "00000000-0000-0000-0000-000000000000",
|
|
@@ -44,7 +46,7 @@ const RS256EnvAdminToken =
|
|
|
44
46
|
}
|
|
45
47
|
*/
|
|
46
48
|
const RS256ManagementUserToken =
|
|
47
|
-
'
|
|
49
|
+
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IklKY1Zqb2ZWRzA0YTVKbVN2cnNGNndfSmVaX21iTDB0OF8zOUNUd3pvdzAifQ.eyJ0ZW5hbnRJZCI6IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIsImVudmlyb25tZW50SWQiOiIyOGViMWQ2NS00OTc4LTRjZWUtODQ5Ni1hMTk2Y2M5OTU0ODUiLCJuYW1lIjoiSm9uYXMgS2hhbndhbGQiLCJlbWFpbCI6ImpvbmFzQHNpY211bmR1cy50aW1lIiwicGVybWlzc2lvbnMiOnsiYXgtaWQtc2VydmljZSI6WyJBRE1JTiJdfSwic3ViamVjdFR5cGUiOiJVc2VyQWNjb3VudCIsImlhdCI6MTY0MzExMDEwMiwiZXhwIjoxNzQzMTEwNzAyLCJhdWQiOiIqIiwiaXNzIjoiYXgtaWQtc2VydmljZSIsInN1YiI6ImQ5YzgzMDA1LTg2MTEtNDFhNC05NWQzLTEzYTQ2ODBhMzAzYSJ9.x04ohwe_xxKNwqLOXL_hZmWvCUYVt71xWyyKcA2WXmkvV3BTdneALrO1B9SxsEX8zSfJ5MMCmj_VRMuQjHv7RXIMNFi_cGuH-nQLG7IcgElDYMpRoc5XDAMPt2CJ67p5MNEAya_defQ9yyO_POcBwt6zdwF9QtIo2_rZRltLqOwlYYKlcgy-3lNHIilCGLDr0BmhcY5JYtNa1xDoFXsvaDVgaRuEg-Ajt9u1ZYyXCk68GW4WrMf9wvCJK0DmzY3offqv9nYLz3pXp_PPO0CvV0yRihAypjL_piCQcnHMwmteFh3w2X5IO6NMKZrnvfjluCuHxR84UQP4_i32BeDYig';
|
|
48
50
|
|
|
49
51
|
/*
|
|
50
52
|
{
|
|
@@ -807,4 +809,79 @@ describe('parse-jwt-token', () => {
|
|
|
807
809
|
message: 'Malformed access token received',
|
|
808
810
|
});
|
|
809
811
|
});
|
|
812
|
+
|
|
813
|
+
describe('checkSigningKeyExists', () => {
|
|
814
|
+
afterEach(() => {
|
|
815
|
+
jest.clearAllMocks();
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
it.each([
|
|
819
|
+
[
|
|
820
|
+
'Signing keys has correct KID',
|
|
821
|
+
[
|
|
822
|
+
{
|
|
823
|
+
e: 'AQAB',
|
|
824
|
+
n: 'sSSFWvUSXPcN8xB2PmF75nPKWp9DHLvnT4lmZcEmaPozW3Y9PDs6gePtzCLEe6qFHpe_8kJJKfr97wFMqov9KmK6y75NdrQqPLOveiHa4vvzOLAg7K_qfVAMR4XcovsOONm2fA3-vyjKI72SX7J3uhMaR4RuZ12MC9LUo5czM-gLhKgHP-TrKXoDlA4MtpeUOX--E78fSs1zVhH_n7HfY1a21r49HdQDHKFApba2iofdDifov9oVFVcccZ8SyY_I_scD_wPbIaQ6TuzgRa2ngeGTbJQZrTUcnE0Aqb5MoOEwMDhEIL1twS7qDK7Ab6Y4_8EvoJyR_dzPe5qQa333WMfNGhk3RBGdv9jZ6Jl_Er7r93S6AMKLC-5Kz9_RrAjJRLKv0_390NKZ_KmHKM9HYujbKOnZa2x5WJnOdMvDR44BWCjDsmpmhtBGWq1chChWS7Ro5XHFhgdNzTZkvZQ9tDE-x-Z-NSKfz26RkDe7L4i1sAmr14yNiidhyGopGFdcP7IQJy9Vd3SadRh-oxAL6C7DvKAEgYwgxZThh40c-xt_EQBbxtw9YTl3YvLCno9Ob6nNr2QJ5AqkQzNHOuRKwF7xD0YriRLxu7_xNxYoztGT56KbxJFAufMulDbaV9sVJ0QKuZy0pCU94YjxvoufVjBnKgA9wzjZLcqysZ6k-VE',
|
|
825
|
+
kty: 'RSA',
|
|
826
|
+
kid: 'IJcVjofVG04a5JmSvrsF6w_JeZ_mbL0t8_39CTwzow0',
|
|
827
|
+
},
|
|
828
|
+
],
|
|
829
|
+
true,
|
|
830
|
+
],
|
|
831
|
+
[
|
|
832
|
+
'Signing keys has no correct KIDs',
|
|
833
|
+
[
|
|
834
|
+
{
|
|
835
|
+
e: 'AQAB',
|
|
836
|
+
n: 'sSSFWvUSXPcN8xB2PmF75nPKWp9DHLvnT4lmZcEmaPozW3Y9PDs6gePtzCLEe6qFHpe_8kJJKfr97wFMqov9KmK6y75NdrQqPLOveiHa4vvzOLAg7K_qfVAMR4XcovsOONm2fA3-vyjKI72SX7J3uhMaR4RuZ12MC9LUo5czM-gLhKgHP-TrKXoDlA4MtpeUOX--E78fSs1zVhH_n7HfY1a21r49HdQDHKFApba2iofdDifov9oVFVcccZ8SyY_I_scD_wPbIaQ6TuzgRa2ngeGTbJQZrTUcnE0Aqb5MoOEwMDhEIL1twS7qDK7Ab6Y4_8EvoJyR_dzPe5qQa333WMfNGhk3RBGdv9jZ6Jl_Er7r93S6AMKLC-5Kz9_RrAjJRLKv0_390NKZ_KmHKM9HYujbKOnZa2x5WJnOdMvDR44BWCjDsmpmhtBGWq1chChWS7Ro5XHFhgdNzTZkvZQ9tDE-x-Z-NSKfz26RkDe7L4i1sAmr14yNiidhyGopGFdcP7IQJy9Vd3SadRh-oxAL6C7DvKAEgYwgxZThh40c-xt_EQBbxtw9YTl3YvLCno9Ob6nNr2QJ5AqkQzNHOuRKwF7xD0YriRLxu7_xNxYoztGT56KbxJFAufMulDbaV9sVJ0QKuZy0pCU94YjxvoufVjBnKgA9wzjZLcqysZ6k-VE',
|
|
837
|
+
kty: 'RSA',
|
|
838
|
+
kid: 'IJcVjofVG04a5JmSvrsF6w_JeZ_xmV9c2_39CTwzow0',
|
|
839
|
+
},
|
|
840
|
+
],
|
|
841
|
+
false,
|
|
842
|
+
],
|
|
843
|
+
[
|
|
844
|
+
'Signing keys has one correct KID and one incorrect KID',
|
|
845
|
+
[
|
|
846
|
+
{
|
|
847
|
+
e: 'AQAB',
|
|
848
|
+
n: 'sSSFWvUSXPcN8xB2PmF75nPKWp9DHLvnT4lmZcEmaPozW3Y9PDs6gePtzCLEe6qFHpe_8kJJKfr97wFMqov9KmK6y75NdrQqPLOveiHa4vvzOLAg7K_qfVAMR4XcovsOONm2fA3-vyjKI72SX7J3uhMaR4RuZ12MC9LUo5czM-gLhKgHP-TrKXoDlA4MtpeUOX--E78fSs1zVhH_n7HfY1a21r49HdQDHKFApba2iofdDifov9oVFVcccZ8SyY_I_scD_wPbIaQ6TuzgRa2ngeGTbJQZrTUcnE0Aqb5MoOEwMDhEIL1twS7qDK7Ab6Y4_8EvoJyR_dzPe5qQa333WMfNGhk3RBGdv9jZ6Jl_Er7r93S6AMKLC-5Kz9_RrAjJRLKv0_390NKZ_KmHKM9HYujbKOnZa2x5WJnOdMvDR44BWCjDsmpmhtBGWq1chChWS7Ro5XHFhgdNzTZkvZQ9tDE-x-Z-NSKfz26RkDe7L4i1sAmr14yNiidhyGopGFdcP7IQJy9Vd3SadRh-oxAL6C7DvKAEgYwgxZThh40c-xt_EQBbxtw9YTl3YvLCno9Ob6nNr2QJ5AqkQzNHOuRKwF7xD0YriRLxu7_xNxYoztGT56KbxJFAufMulDbaV9sVJ0QKuZy0pCU94YjxvoufVjBnKgA9wzjZLcqysZ6k-VE',
|
|
849
|
+
kty: 'RSA',
|
|
850
|
+
kid: 'IJcVjofVG04a5JmSvrsF6w_JeZ_xmV9c2_39CTwzow0',
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
e: 'AQAB',
|
|
854
|
+
n: 'sSSFWvUSXPcN8xB2PmF75nPKWp9DHLvnT4lmZcEmaPozW3Y9PDs6gePtzCLEe6qFHpe_8kJJKfr97wFMqov9KmK6y75NdrQqPLOveiHa4vvzOLAg7K_qfVAMR4XcovsOONm2fA3-vyjKI72SX7J3uhMaR4RuZ12MC9LUo5czM-gLhKgHP-TrKXoDlA4MtpeUOX--E78fSs1zVhH_n7HfY1a21r49HdQDHKFApba2iofdDifov9oVFVcccZ8SyY_I_scD_wPbIaQ6TuzgRa2ngeGTbJQZrTUcnE0Aqb5MoOEwMDhEIL1twS7qDK7Ab6Y4_8EvoJyR_dzPe5qQa333WMfNGhk3RBGdv9jZ6Jl_Er7r93S6AMKLC-5Kz9_RrAjJRLKv0_390NKZ_KmHKM9HYujbKOnZa2x5WJnOdMvDR44BWCjDsmpmhtBGWq1chChWS7Ro5XHFhgdNzTZkvZQ9tDE-x-Z-NSKfz26RkDe7L4i1sAmr14yNiidhyGopGFdcP7IQJy9Vd3SadRh-oxAL6C7DvKAEgYwgxZThh40c-xt_EQBbxtw9YTl3YvLCno9Ob6nNr2QJ5AqkQzNHOuRKwF7xD0YriRLxu7_xNxYoztGT56KbxJFAufMulDbaV9sVJ0QKuZy0pCU94YjxvoufVjBnKgA9wzjZLcqysZ6k-VE',
|
|
855
|
+
kty: 'RSA',
|
|
856
|
+
kid: 'IJcVjofVG04a5JmSvrsF6w_JeZ_mbL0t8_39CTwzow0',
|
|
857
|
+
},
|
|
858
|
+
],
|
|
859
|
+
true,
|
|
860
|
+
],
|
|
861
|
+
])(
|
|
862
|
+
'When %s the correct value is returned',
|
|
863
|
+
async (_testCase, keys, existsValue) => {
|
|
864
|
+
jest
|
|
865
|
+
.spyOn(jwksClient, 'getJwksClient')
|
|
866
|
+
.mockImplementation((_jwksUri: string) => {
|
|
867
|
+
return {
|
|
868
|
+
getKeys: jest.fn().mockImplementation((cb) => {
|
|
869
|
+
cb(null, keys);
|
|
870
|
+
}),
|
|
871
|
+
getKeysAsync: jest.fn(),
|
|
872
|
+
getSigningKey: jest.fn(),
|
|
873
|
+
getSigningKeyAsync: jest.fn(),
|
|
874
|
+
getSigningKeys: jest.fn(),
|
|
875
|
+
getSigningKeysAsync: jest.fn(),
|
|
876
|
+
};
|
|
877
|
+
});
|
|
878
|
+
const signingKeyExists = await checkSigningKeyExists(
|
|
879
|
+
RS256ManagementUserToken,
|
|
880
|
+
'https://id.mosaic.axinom.net',
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
expect(signingKeyExists).toBe(existsValue);
|
|
884
|
+
},
|
|
885
|
+
);
|
|
886
|
+
});
|
|
810
887
|
});
|
|
@@ -4,12 +4,14 @@ import {
|
|
|
4
4
|
} from '@axinom/mosaic-service-common';
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import jwt from 'jsonwebtoken';
|
|
7
|
+
import { SigningKey } from 'jwks-rsa';
|
|
7
8
|
import {
|
|
8
9
|
getAuthenticatedEndUser,
|
|
9
10
|
getAuthenticatedManagementSubject,
|
|
10
11
|
} from './get-authenticated-subject';
|
|
11
12
|
import { handleJwtParseError } from './helpers';
|
|
12
13
|
import { IdGuardErrors } from './id-guard-errors';
|
|
14
|
+
import { getJwksClient } from './jwks-client';
|
|
13
15
|
import { getJwtVerifyOptions } from './jwt-verify-options';
|
|
14
16
|
import { SubjectType } from './subject-type';
|
|
15
17
|
import {
|
|
@@ -135,3 +137,45 @@ export const decodeEndUserAccessToken = (
|
|
|
135
137
|
): AuthenticatedEndUser => {
|
|
136
138
|
return jwt.decode(token) as AuthenticatedEndUser;
|
|
137
139
|
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Returns if the KID used to sign a JWT is available in the active JWKS.
|
|
143
|
+
*
|
|
144
|
+
* @param token
|
|
145
|
+
* @param authConfig
|
|
146
|
+
* @returns
|
|
147
|
+
*/
|
|
148
|
+
export const checkSigningKeyExists = async (
|
|
149
|
+
token: string,
|
|
150
|
+
idServiceAuthBaseUrl: string,
|
|
151
|
+
): Promise<boolean> => {
|
|
152
|
+
return new Promise<boolean>((resolve, reject) => {
|
|
153
|
+
const decodedJwt = jwt.decode(token, { complete: true });
|
|
154
|
+
if (decodedJwt === null) {
|
|
155
|
+
reject('Invalid JWT received');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const subject = decodedJwt?.payload as AuthenticatedManagementSubject;
|
|
159
|
+
|
|
160
|
+
const jwksUri = new URL(
|
|
161
|
+
`/${subject.tenantId}/${subject.environmentId}/.well-known/jwks.json`,
|
|
162
|
+
idServiceAuthBaseUrl,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const jwksClient = getJwksClient(jwksUri.toString());
|
|
166
|
+
jwksClient.getKeys((error, keys) => {
|
|
167
|
+
if (error) {
|
|
168
|
+
reject(error);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const signingKeys = keys as SigningKey[];
|
|
173
|
+
for (const idx in signingKeys) {
|
|
174
|
+
if (signingKeys[idx]['kid'] === decodedJwt?.header.kid) {
|
|
175
|
+
return resolve(true);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return resolve(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
};
|