@commercetools-backend/express 23.2.0 → 23.2.2
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/commercetools-backend-express.cjs.dev.js +38 -73
- package/dist/commercetools-backend-express.cjs.prod.js +38 -73
- package/dist/commercetools-backend-express.esm.js +37 -63
- package/dist/declarations/src/auth.d.ts +6 -7
- package/dist/declarations/src/middlewares/session-middleware.d.ts +1 -1
- package/dist/declarations/src/types.d.ts +3 -2
- package/package.json +7 -6
|
@@ -2,20 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
|
|
6
5
|
var _URL = require('@babel/runtime-corejs3/core-js-stable/url');
|
|
6
|
+
var _Map = require('@babel/runtime-corejs3/core-js-stable/map');
|
|
7
7
|
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
8
|
-
var
|
|
9
|
-
var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys');
|
|
10
|
-
var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
|
|
11
|
-
var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter');
|
|
12
|
-
var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor');
|
|
13
|
-
var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
|
|
14
|
-
var _Object$getOwnPropertyDescriptors = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors');
|
|
15
|
-
var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/object/define-properties');
|
|
16
|
-
var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
|
|
17
|
-
var expressJwt = require('express-jwt');
|
|
18
|
-
var jwksRsa = require('jwks-rsa');
|
|
8
|
+
var jose = require('jose');
|
|
19
9
|
var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
|
|
20
10
|
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
|
|
21
11
|
var _Object$entries = require('@babel/runtime-corejs3/core-js-stable/object/entries');
|
|
@@ -24,17 +14,8 @@ var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-arr
|
|
|
24
14
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
25
15
|
|
|
26
16
|
var _URL__default = /*#__PURE__*/_interopDefault(_URL);
|
|
17
|
+
var _Map__default = /*#__PURE__*/_interopDefault(_Map);
|
|
27
18
|
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
28
|
-
var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
|
|
29
|
-
var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys);
|
|
30
|
-
var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols);
|
|
31
|
-
var _filterInstanceProperty__default = /*#__PURE__*/_interopDefault(_filterInstanceProperty);
|
|
32
|
-
var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor);
|
|
33
|
-
var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
|
|
34
|
-
var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors);
|
|
35
|
-
var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
|
|
36
|
-
var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
|
|
37
|
-
var jwksRsa__default = /*#__PURE__*/_interopDefault(jwksRsa);
|
|
38
19
|
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
|
|
39
20
|
var _Object$entries__default = /*#__PURE__*/_interopDefault(_Object$entries);
|
|
40
21
|
var _Array$isArray__default = /*#__PURE__*/_interopDefault(_Array$isArray);
|
|
@@ -96,27 +77,18 @@ const getFirstHeaderValueOrThrow = (headers, headerKey, errorMessage) => {
|
|
|
96
77
|
return headerValue;
|
|
97
78
|
};
|
|
98
79
|
|
|
99
|
-
function ownKeys(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
100
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
101
|
-
const decodedTokenKey = 'decoded_token';
|
|
102
80
|
// Assign a session object to the request object.
|
|
103
|
-
const writeSessionContext = request => {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (Boolean(userPermissions?.length)) {
|
|
114
|
-
request.session.userPermissions = userPermissions;
|
|
115
|
-
}
|
|
81
|
+
const writeSessionContext = (request, verifiedToken) => {
|
|
82
|
+
const publicClaimForProjectKey = `${verifiedToken.iss}/claims/project_key`;
|
|
83
|
+
const publicClaimForUserPermissionsKey = `${verifiedToken.iss}/claims/user_permissions`;
|
|
84
|
+
request.session = {
|
|
85
|
+
userId: verifiedToken.sub,
|
|
86
|
+
projectKey: verifiedToken[publicClaimForProjectKey]
|
|
87
|
+
};
|
|
88
|
+
const userPermissions = verifiedToken[publicClaimForUserPermissionsKey];
|
|
89
|
+
if (Boolean(userPermissions?.length)) {
|
|
90
|
+
request.session.userPermissions = userPermissions;
|
|
116
91
|
}
|
|
117
|
-
|
|
118
|
-
// Remove the field used by the JWT middleware.
|
|
119
|
-
delete request.decoded_token;
|
|
120
92
|
};
|
|
121
93
|
|
|
122
94
|
// Given a cloud identifier, try to map it to one of the supported
|
|
@@ -199,12 +171,22 @@ const getConfiguredAudience = (options, requestPath) => {
|
|
|
199
171
|
}
|
|
200
172
|
}
|
|
201
173
|
};
|
|
174
|
+
const jwksClientByIssuer = new _Map__default["default"]();
|
|
175
|
+
function getJwksClientByIssuer(issuer) {
|
|
176
|
+
const client = jwksClientByIssuer.get(issuer);
|
|
177
|
+
if (client) {
|
|
178
|
+
return client;
|
|
179
|
+
}
|
|
180
|
+
const newClient = jose.createRemoteJWKSet(new _URL__default["default"](`/.well-known/jwks.json`, issuer));
|
|
181
|
+
jwksClientByIssuer.set(issuer, newClient);
|
|
182
|
+
return newClient;
|
|
183
|
+
}
|
|
202
184
|
function createSessionAuthVerifier(options) {
|
|
203
185
|
validateRequiredValues(options);
|
|
204
186
|
const configuredDefaultIssuer = getConfiguredDefaultIssuer(options);
|
|
205
187
|
|
|
206
188
|
// Returns an async HTTP handler.
|
|
207
|
-
return async
|
|
189
|
+
return async request => {
|
|
208
190
|
// Get the cloud identifier header, forwarded by the `/proxy/forward-to` endpoint.
|
|
209
191
|
const cloudIdentifierHeader = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.CLOUD_IDENTIFIER, `Missing "X-MC-API-Cloud-Identifier" header.`);
|
|
210
192
|
let issuer = options.inferIssuer && cloudIdentifierHeader ? mapCloudIdentifierToIssuer(cloudIdentifierHeader) ?? configuredDefaultIssuer : configuredDefaultIssuer;
|
|
@@ -221,44 +203,27 @@ function createSessionAuthVerifier(options) {
|
|
|
221
203
|
throw new Error(`Invalid request URI path "${requestUrlPath}". Please make sure that the "request" object has either a property "originalUrl" or "url". If not, you should implement the "getRequestUrl" function and make sure to return a valid URI path value starting with "/". More info at https://docs.commercetools.com/merchant-center-customizations/concepts/integrate-with-your-own-api#validating-the-json-web-token`);
|
|
222
204
|
}
|
|
223
205
|
const audience = getConfiguredAudience(options, requestUrlPath);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
// This should be set by the middleware, no matter what.
|
|
235
|
-
jwksUri: `${issuer}/.well-known/jwks.json`
|
|
236
|
-
})),
|
|
237
|
-
requestProperty: decodedTokenKey,
|
|
238
|
-
// Validate the audience and the issuer.
|
|
239
|
-
audience,
|
|
240
|
-
issuer,
|
|
241
|
-
algorithms: ['RS256']
|
|
242
|
-
// @ts-ignore: the middleware expects an Express.js Request/Response objects
|
|
243
|
-
})(request, response ?? {}, error => {
|
|
244
|
-
if (error) {
|
|
245
|
-
reject(error);
|
|
246
|
-
} else {
|
|
247
|
-
// @ts-ignore: the Request object does not know about some additional fields
|
|
248
|
-
// like `decoded_token` and `session`
|
|
249
|
-
writeSessionContext(request);
|
|
250
|
-
resolve();
|
|
251
|
-
}
|
|
252
|
-
});
|
|
206
|
+
const authorizationHeader = request.headers['authorization'];
|
|
207
|
+
if (typeof authorizationHeader !== 'string') {
|
|
208
|
+
throw new Error(`Missing "authorization" header`);
|
|
209
|
+
}
|
|
210
|
+
const exchangeToken = authorizationHeader.replace(/^Bearer (.*)$/, '$1');
|
|
211
|
+
const jwksClient = getJwksClientByIssuer(issuer);
|
|
212
|
+
const verifiedToken = await jose.jwtVerify(exchangeToken, jwksClient, {
|
|
213
|
+
algorithms: ['RS256'],
|
|
214
|
+
audience,
|
|
215
|
+
issuer
|
|
253
216
|
});
|
|
217
|
+
writeSessionContext(request, verifiedToken.payload);
|
|
218
|
+
return;
|
|
254
219
|
};
|
|
255
220
|
}
|
|
256
221
|
|
|
257
222
|
function createSessionMiddleware(options) {
|
|
258
223
|
const sessionAuthVerifier = createSessionAuthVerifier(options);
|
|
259
|
-
return async (request,
|
|
224
|
+
return async (request, _response, next) => {
|
|
260
225
|
try {
|
|
261
|
-
await sessionAuthVerifier(request
|
|
226
|
+
await sessionAuthVerifier(request);
|
|
262
227
|
next();
|
|
263
228
|
} catch (error) {
|
|
264
229
|
next(error);
|
|
@@ -2,20 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
|
|
6
5
|
var _URL = require('@babel/runtime-corejs3/core-js-stable/url');
|
|
6
|
+
var _Map = require('@babel/runtime-corejs3/core-js-stable/map');
|
|
7
7
|
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
8
|
-
var
|
|
9
|
-
var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys');
|
|
10
|
-
var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
|
|
11
|
-
var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter');
|
|
12
|
-
var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor');
|
|
13
|
-
var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
|
|
14
|
-
var _Object$getOwnPropertyDescriptors = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors');
|
|
15
|
-
var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/object/define-properties');
|
|
16
|
-
var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
|
|
17
|
-
var expressJwt = require('express-jwt');
|
|
18
|
-
var jwksRsa = require('jwks-rsa');
|
|
8
|
+
var jose = require('jose');
|
|
19
9
|
var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
|
|
20
10
|
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
|
|
21
11
|
var _Object$entries = require('@babel/runtime-corejs3/core-js-stable/object/entries');
|
|
@@ -24,17 +14,8 @@ var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-arr
|
|
|
24
14
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
25
15
|
|
|
26
16
|
var _URL__default = /*#__PURE__*/_interopDefault(_URL);
|
|
17
|
+
var _Map__default = /*#__PURE__*/_interopDefault(_Map);
|
|
27
18
|
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
28
|
-
var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
|
|
29
|
-
var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys);
|
|
30
|
-
var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols);
|
|
31
|
-
var _filterInstanceProperty__default = /*#__PURE__*/_interopDefault(_filterInstanceProperty);
|
|
32
|
-
var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor);
|
|
33
|
-
var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
|
|
34
|
-
var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors);
|
|
35
|
-
var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
|
|
36
|
-
var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
|
|
37
|
-
var jwksRsa__default = /*#__PURE__*/_interopDefault(jwksRsa);
|
|
38
19
|
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
|
|
39
20
|
var _Object$entries__default = /*#__PURE__*/_interopDefault(_Object$entries);
|
|
40
21
|
var _Array$isArray__default = /*#__PURE__*/_interopDefault(_Array$isArray);
|
|
@@ -96,27 +77,18 @@ const getFirstHeaderValueOrThrow = (headers, headerKey, errorMessage) => {
|
|
|
96
77
|
return headerValue;
|
|
97
78
|
};
|
|
98
79
|
|
|
99
|
-
function ownKeys(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
100
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
|
|
101
|
-
const decodedTokenKey = 'decoded_token';
|
|
102
80
|
// Assign a session object to the request object.
|
|
103
|
-
const writeSessionContext = request => {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (Boolean(userPermissions?.length)) {
|
|
114
|
-
request.session.userPermissions = userPermissions;
|
|
115
|
-
}
|
|
81
|
+
const writeSessionContext = (request, verifiedToken) => {
|
|
82
|
+
const publicClaimForProjectKey = `${verifiedToken.iss}/claims/project_key`;
|
|
83
|
+
const publicClaimForUserPermissionsKey = `${verifiedToken.iss}/claims/user_permissions`;
|
|
84
|
+
request.session = {
|
|
85
|
+
userId: verifiedToken.sub,
|
|
86
|
+
projectKey: verifiedToken[publicClaimForProjectKey]
|
|
87
|
+
};
|
|
88
|
+
const userPermissions = verifiedToken[publicClaimForUserPermissionsKey];
|
|
89
|
+
if (Boolean(userPermissions?.length)) {
|
|
90
|
+
request.session.userPermissions = userPermissions;
|
|
116
91
|
}
|
|
117
|
-
|
|
118
|
-
// Remove the field used by the JWT middleware.
|
|
119
|
-
delete request.decoded_token;
|
|
120
92
|
};
|
|
121
93
|
|
|
122
94
|
// Given a cloud identifier, try to map it to one of the supported
|
|
@@ -199,12 +171,22 @@ const getConfiguredAudience = (options, requestPath) => {
|
|
|
199
171
|
}
|
|
200
172
|
}
|
|
201
173
|
};
|
|
174
|
+
const jwksClientByIssuer = new _Map__default["default"]();
|
|
175
|
+
function getJwksClientByIssuer(issuer) {
|
|
176
|
+
const client = jwksClientByIssuer.get(issuer);
|
|
177
|
+
if (client) {
|
|
178
|
+
return client;
|
|
179
|
+
}
|
|
180
|
+
const newClient = jose.createRemoteJWKSet(new _URL__default["default"](`/.well-known/jwks.json`, issuer));
|
|
181
|
+
jwksClientByIssuer.set(issuer, newClient);
|
|
182
|
+
return newClient;
|
|
183
|
+
}
|
|
202
184
|
function createSessionAuthVerifier(options) {
|
|
203
185
|
validateRequiredValues(options);
|
|
204
186
|
const configuredDefaultIssuer = getConfiguredDefaultIssuer(options);
|
|
205
187
|
|
|
206
188
|
// Returns an async HTTP handler.
|
|
207
|
-
return async
|
|
189
|
+
return async request => {
|
|
208
190
|
// Get the cloud identifier header, forwarded by the `/proxy/forward-to` endpoint.
|
|
209
191
|
const cloudIdentifierHeader = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.CLOUD_IDENTIFIER, `Missing "X-MC-API-Cloud-Identifier" header.`);
|
|
210
192
|
let issuer = options.inferIssuer && cloudIdentifierHeader ? mapCloudIdentifierToIssuer(cloudIdentifierHeader) ?? configuredDefaultIssuer : configuredDefaultIssuer;
|
|
@@ -221,44 +203,27 @@ function createSessionAuthVerifier(options) {
|
|
|
221
203
|
throw new Error(`Invalid request URI path "${requestUrlPath}". Please make sure that the "request" object has either a property "originalUrl" or "url". If not, you should implement the "getRequestUrl" function and make sure to return a valid URI path value starting with "/". More info at https://docs.commercetools.com/merchant-center-customizations/concepts/integrate-with-your-own-api#validating-the-json-web-token`);
|
|
222
204
|
}
|
|
223
205
|
const audience = getConfiguredAudience(options, requestUrlPath);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
// This should be set by the middleware, no matter what.
|
|
235
|
-
jwksUri: `${issuer}/.well-known/jwks.json`
|
|
236
|
-
})),
|
|
237
|
-
requestProperty: decodedTokenKey,
|
|
238
|
-
// Validate the audience and the issuer.
|
|
239
|
-
audience,
|
|
240
|
-
issuer,
|
|
241
|
-
algorithms: ['RS256']
|
|
242
|
-
// @ts-ignore: the middleware expects an Express.js Request/Response objects
|
|
243
|
-
})(request, response ?? {}, error => {
|
|
244
|
-
if (error) {
|
|
245
|
-
reject(error);
|
|
246
|
-
} else {
|
|
247
|
-
// @ts-ignore: the Request object does not know about some additional fields
|
|
248
|
-
// like `decoded_token` and `session`
|
|
249
|
-
writeSessionContext(request);
|
|
250
|
-
resolve();
|
|
251
|
-
}
|
|
252
|
-
});
|
|
206
|
+
const authorizationHeader = request.headers['authorization'];
|
|
207
|
+
if (typeof authorizationHeader !== 'string') {
|
|
208
|
+
throw new Error(`Missing "authorization" header`);
|
|
209
|
+
}
|
|
210
|
+
const exchangeToken = authorizationHeader.replace(/^Bearer (.*)$/, '$1');
|
|
211
|
+
const jwksClient = getJwksClientByIssuer(issuer);
|
|
212
|
+
const verifiedToken = await jose.jwtVerify(exchangeToken, jwksClient, {
|
|
213
|
+
algorithms: ['RS256'],
|
|
214
|
+
audience,
|
|
215
|
+
issuer
|
|
253
216
|
});
|
|
217
|
+
writeSessionContext(request, verifiedToken.payload);
|
|
218
|
+
return;
|
|
254
219
|
};
|
|
255
220
|
}
|
|
256
221
|
|
|
257
222
|
function createSessionMiddleware(options) {
|
|
258
223
|
const sessionAuthVerifier = createSessionAuthVerifier(options);
|
|
259
|
-
return async (request,
|
|
224
|
+
return async (request, _response, next) => {
|
|
260
225
|
try {
|
|
261
|
-
await sessionAuthVerifier(request
|
|
226
|
+
await sessionAuthVerifier(request);
|
|
262
227
|
next();
|
|
263
228
|
} catch (error) {
|
|
264
229
|
next(error);
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
import _defineProperty from '@babel/runtime-corejs3/helpers/esm/defineProperty';
|
|
2
1
|
import _URL from '@babel/runtime-corejs3/core-js-stable/url';
|
|
2
|
+
import _Map from '@babel/runtime-corejs3/core-js-stable/map';
|
|
3
3
|
import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with';
|
|
4
|
-
import
|
|
5
|
-
import _Object$keys from '@babel/runtime-corejs3/core-js-stable/object/keys';
|
|
6
|
-
import _Object$getOwnPropertySymbols from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols';
|
|
7
|
-
import _filterInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/filter';
|
|
8
|
-
import _Object$getOwnPropertyDescriptor from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor';
|
|
9
|
-
import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each';
|
|
10
|
-
import _Object$getOwnPropertyDescriptors from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors';
|
|
11
|
-
import _Object$defineProperties from '@babel/runtime-corejs3/core-js-stable/object/define-properties';
|
|
12
|
-
import _Object$defineProperty from '@babel/runtime-corejs3/core-js-stable/object/define-property';
|
|
13
|
-
import { expressjwt } from 'express-jwt';
|
|
14
|
-
import jwksRsa from 'jwks-rsa';
|
|
4
|
+
import { jwtVerify, createRemoteJWKSet } from 'jose';
|
|
15
5
|
import _slicedToArray from '@babel/runtime-corejs3/helpers/esm/slicedToArray';
|
|
16
6
|
import _findInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/find';
|
|
17
7
|
import _Object$entries from '@babel/runtime-corejs3/core-js-stable/object/entries';
|
|
@@ -74,27 +64,18 @@ const getFirstHeaderValueOrThrow = (headers, headerKey, errorMessage) => {
|
|
|
74
64
|
return headerValue;
|
|
75
65
|
};
|
|
76
66
|
|
|
77
|
-
function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
78
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
79
|
-
const decodedTokenKey = 'decoded_token';
|
|
80
67
|
// Assign a session object to the request object.
|
|
81
|
-
const writeSessionContext = request => {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (Boolean(userPermissions?.length)) {
|
|
92
|
-
request.session.userPermissions = userPermissions;
|
|
93
|
-
}
|
|
68
|
+
const writeSessionContext = (request, verifiedToken) => {
|
|
69
|
+
const publicClaimForProjectKey = `${verifiedToken.iss}/claims/project_key`;
|
|
70
|
+
const publicClaimForUserPermissionsKey = `${verifiedToken.iss}/claims/user_permissions`;
|
|
71
|
+
request.session = {
|
|
72
|
+
userId: verifiedToken.sub,
|
|
73
|
+
projectKey: verifiedToken[publicClaimForProjectKey]
|
|
74
|
+
};
|
|
75
|
+
const userPermissions = verifiedToken[publicClaimForUserPermissionsKey];
|
|
76
|
+
if (Boolean(userPermissions?.length)) {
|
|
77
|
+
request.session.userPermissions = userPermissions;
|
|
94
78
|
}
|
|
95
|
-
|
|
96
|
-
// Remove the field used by the JWT middleware.
|
|
97
|
-
delete request.decoded_token;
|
|
98
79
|
};
|
|
99
80
|
|
|
100
81
|
// Given a cloud identifier, try to map it to one of the supported
|
|
@@ -177,12 +158,22 @@ const getConfiguredAudience = (options, requestPath) => {
|
|
|
177
158
|
}
|
|
178
159
|
}
|
|
179
160
|
};
|
|
161
|
+
const jwksClientByIssuer = new _Map();
|
|
162
|
+
function getJwksClientByIssuer(issuer) {
|
|
163
|
+
const client = jwksClientByIssuer.get(issuer);
|
|
164
|
+
if (client) {
|
|
165
|
+
return client;
|
|
166
|
+
}
|
|
167
|
+
const newClient = createRemoteJWKSet(new _URL(`/.well-known/jwks.json`, issuer));
|
|
168
|
+
jwksClientByIssuer.set(issuer, newClient);
|
|
169
|
+
return newClient;
|
|
170
|
+
}
|
|
180
171
|
function createSessionAuthVerifier(options) {
|
|
181
172
|
validateRequiredValues(options);
|
|
182
173
|
const configuredDefaultIssuer = getConfiguredDefaultIssuer(options);
|
|
183
174
|
|
|
184
175
|
// Returns an async HTTP handler.
|
|
185
|
-
return async
|
|
176
|
+
return async request => {
|
|
186
177
|
// Get the cloud identifier header, forwarded by the `/proxy/forward-to` endpoint.
|
|
187
178
|
const cloudIdentifierHeader = getFirstHeaderValueOrThrow(request.headers, MC_API_PROXY_HEADERS.CLOUD_IDENTIFIER, `Missing "X-MC-API-Cloud-Identifier" header.`);
|
|
188
179
|
let issuer = options.inferIssuer && cloudIdentifierHeader ? mapCloudIdentifierToIssuer(cloudIdentifierHeader) ?? configuredDefaultIssuer : configuredDefaultIssuer;
|
|
@@ -199,44 +190,27 @@ function createSessionAuthVerifier(options) {
|
|
|
199
190
|
throw new Error(`Invalid request URI path "${requestUrlPath}". Please make sure that the "request" object has either a property "originalUrl" or "url". If not, you should implement the "getRequestUrl" function and make sure to return a valid URI path value starting with "/". More info at https://docs.commercetools.com/merchant-center-customizations/concepts/integrate-with-your-own-api#validating-the-json-web-token`);
|
|
200
191
|
}
|
|
201
192
|
const audience = getConfiguredAudience(options, requestUrlPath);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// This should be set by the middleware, no matter what.
|
|
213
|
-
jwksUri: `${issuer}/.well-known/jwks.json`
|
|
214
|
-
})),
|
|
215
|
-
requestProperty: decodedTokenKey,
|
|
216
|
-
// Validate the audience and the issuer.
|
|
217
|
-
audience,
|
|
218
|
-
issuer,
|
|
219
|
-
algorithms: ['RS256']
|
|
220
|
-
// @ts-ignore: the middleware expects an Express.js Request/Response objects
|
|
221
|
-
})(request, response ?? {}, error => {
|
|
222
|
-
if (error) {
|
|
223
|
-
reject(error);
|
|
224
|
-
} else {
|
|
225
|
-
// @ts-ignore: the Request object does not know about some additional fields
|
|
226
|
-
// like `decoded_token` and `session`
|
|
227
|
-
writeSessionContext(request);
|
|
228
|
-
resolve();
|
|
229
|
-
}
|
|
230
|
-
});
|
|
193
|
+
const authorizationHeader = request.headers['authorization'];
|
|
194
|
+
if (typeof authorizationHeader !== 'string') {
|
|
195
|
+
throw new Error(`Missing "authorization" header`);
|
|
196
|
+
}
|
|
197
|
+
const exchangeToken = authorizationHeader.replace(/^Bearer (.*)$/, '$1');
|
|
198
|
+
const jwksClient = getJwksClientByIssuer(issuer);
|
|
199
|
+
const verifiedToken = await jwtVerify(exchangeToken, jwksClient, {
|
|
200
|
+
algorithms: ['RS256'],
|
|
201
|
+
audience,
|
|
202
|
+
issuer
|
|
231
203
|
});
|
|
204
|
+
writeSessionContext(request, verifiedToken.payload);
|
|
205
|
+
return;
|
|
232
206
|
};
|
|
233
207
|
}
|
|
234
208
|
|
|
235
209
|
function createSessionMiddleware(options) {
|
|
236
210
|
const sessionAuthVerifier = createSessionAuthVerifier(options);
|
|
237
|
-
return async (request,
|
|
211
|
+
return async (request, _response, next) => {
|
|
238
212
|
try {
|
|
239
|
-
await sessionAuthVerifier(request
|
|
213
|
+
await sessionAuthVerifier(request);
|
|
240
214
|
next();
|
|
241
215
|
} catch (error) {
|
|
242
216
|
next(error);
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { TSessionMiddlewareOptions, TSession, TBaseRequest } from './types';
|
|
2
|
-
type TDecodedJWT = {
|
|
2
|
+
export type TDecodedJWT = {
|
|
3
3
|
sub: string;
|
|
4
4
|
iss: string;
|
|
5
5
|
[property: string]: string | string[];
|
|
6
6
|
};
|
|
7
|
-
declare const writeSessionContext: <
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
declare function createSessionAuthVerifier<Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>): (request: Request, response?: unknown) => Promise<void>;
|
|
7
|
+
declare const writeSessionContext: <Request extends TBaseRequest>(request: Request & {
|
|
8
|
+
session?: TSession;
|
|
9
|
+
}, verifiedToken: TDecodedJWT) => void;
|
|
10
|
+
export declare const getConfiguredAudience: <Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>, requestPath: string) => string;
|
|
11
|
+
declare function createSessionAuthVerifier<Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>): (request: Request) => Promise<void>;
|
|
13
12
|
export { createSessionAuthVerifier, writeSessionContext };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Response, NextFunction } from 'express';
|
|
2
2
|
import type { TBaseRequest, TSessionMiddlewareOptions } from '../types';
|
|
3
|
-
declare function createSessionMiddleware<Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>): (request: Request,
|
|
3
|
+
declare function createSessionMiddleware<Request extends TBaseRequest>(options: TSessionMiddlewareOptions<Request>): (request: Request, _response: Response, next: NextFunction) => Promise<void>;
|
|
4
4
|
export default createSessionMiddleware;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ExpressJwtOptions } from 'jwks-rsa';
|
|
2
1
|
import { CLOUD_IDENTIFIERS } from './constants';
|
|
3
2
|
export type TAudience = string;
|
|
4
3
|
export type TIssuer = string;
|
|
@@ -35,8 +34,10 @@ export type TSessionMiddlewareOptions<Request extends TBaseRequest> = {
|
|
|
35
34
|
inferIssuer?: boolean;
|
|
36
35
|
/**
|
|
37
36
|
* Options for the `jwksRsa.expressJwtSecret`
|
|
37
|
+
*
|
|
38
|
+
* @deprecated
|
|
38
39
|
*/
|
|
39
|
-
jwks?:
|
|
40
|
+
jwks?: unknown;
|
|
40
41
|
/**
|
|
41
42
|
* By default we assume that the `request` is a Node.js-like object having either
|
|
42
43
|
* an `originalUrl` or `url` properties.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commercetools-backend/express",
|
|
3
|
-
"version": "23.2.
|
|
3
|
+
"version": "23.2.2",
|
|
4
4
|
"description": "Zero-config HTTP server as Express.js to facilitate development",
|
|
5
5
|
"bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
|
|
6
6
|
"repository": {
|
|
@@ -34,14 +34,15 @@
|
|
|
34
34
|
"@babel/runtime-corejs3": "^7.22.15",
|
|
35
35
|
"@types/express": "^4.17.17",
|
|
36
36
|
"@types/node": "^22.13.2",
|
|
37
|
-
"express": "4.
|
|
38
|
-
"
|
|
39
|
-
"jwks-rsa": "2.1.5"
|
|
37
|
+
"express": "^4.21.2",
|
|
38
|
+
"jose": "^5.10.0"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
41
|
"@tsconfig/node22": "^22.0.0",
|
|
43
|
-
"
|
|
44
|
-
"jose": "2.0.7",
|
|
42
|
+
"typescript": "^5.2.2",
|
|
45
43
|
"msw": "0.49.3"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": "18.x || 20.x || >=22.0.0"
|
|
46
47
|
}
|
|
47
48
|
}
|