@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.
@@ -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 _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
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 decodedToken = request[decodedTokenKey];
105
- if (decodedToken) {
106
- const publicClaimForProjectKey = `${decodedToken.iss}/claims/project_key`;
107
- const publicClaimForUserPermissionsKey = `${decodedToken.iss}/claims/user_permissions`;
108
- request.session = {
109
- userId: decodedToken.sub,
110
- projectKey: decodedToken[publicClaimForProjectKey]
111
- };
112
- const userPermissions = decodedToken[publicClaimForUserPermissionsKey];
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 (request, response) => {
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
- return new _Promise__default["default"]((resolve, reject) => {
225
- expressJwt.expressjwt({
226
- // Dynamically provide a signing key based on the kid in the header
227
- // and the singing keys provided by the JWKS endpoint
228
- secret: jwksRsa__default["default"].expressJwtSecret(_objectSpread(_objectSpread({
229
- // Default options
230
- cache: true,
231
- rateLimit: true,
232
- jwksRequestsPerMinute: 5
233
- }, options.jwks || {}), {}, {
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, response, next) => {
224
+ return async (request, _response, next) => {
260
225
  try {
261
- await sessionAuthVerifier(request, response);
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 _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
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 decodedToken = request[decodedTokenKey];
105
- if (decodedToken) {
106
- const publicClaimForProjectKey = `${decodedToken.iss}/claims/project_key`;
107
- const publicClaimForUserPermissionsKey = `${decodedToken.iss}/claims/user_permissions`;
108
- request.session = {
109
- userId: decodedToken.sub,
110
- projectKey: decodedToken[publicClaimForProjectKey]
111
- };
112
- const userPermissions = decodedToken[publicClaimForUserPermissionsKey];
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 (request, response) => {
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
- return new _Promise__default["default"]((resolve, reject) => {
225
- expressJwt.expressjwt({
226
- // Dynamically provide a signing key based on the kid in the header
227
- // and the singing keys provided by the JWKS endpoint
228
- secret: jwksRsa__default["default"].expressJwtSecret(_objectSpread(_objectSpread({
229
- // Default options
230
- cache: true,
231
- rateLimit: true,
232
- jwksRequestsPerMinute: 5
233
- }, options.jwks || {}), {}, {
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, response, next) => {
224
+ return async (request, _response, next) => {
260
225
  try {
261
- await sessionAuthVerifier(request, response);
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 _Promise from '@babel/runtime-corejs3/core-js-stable/promise';
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 decodedToken = request[decodedTokenKey];
83
- if (decodedToken) {
84
- const publicClaimForProjectKey = `${decodedToken.iss}/claims/project_key`;
85
- const publicClaimForUserPermissionsKey = `${decodedToken.iss}/claims/user_permissions`;
86
- request.session = {
87
- userId: decodedToken.sub,
88
- projectKey: decodedToken[publicClaimForProjectKey]
89
- };
90
- const userPermissions = decodedToken[publicClaimForUserPermissionsKey];
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 (request, response) => {
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
- return new _Promise((resolve, reject) => {
203
- expressjwt({
204
- // Dynamically provide a signing key based on the kid in the header
205
- // and the singing keys provided by the JWKS endpoint
206
- secret: jwksRsa.expressJwtSecret(_objectSpread(_objectSpread({
207
- // Default options
208
- cache: true,
209
- rateLimit: true,
210
- jwksRequestsPerMinute: 5
211
- }, options.jwks || {}), {}, {
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, response, next) => {
211
+ return async (request, _response, next) => {
238
212
  try {
239
- await sessionAuthVerifier(request, response);
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: <Request_1 extends TBaseRequest>(request: Request_1 & {
8
- decoded_token?: TDecodedJWT | undefined;
9
- session?: TSession | undefined;
10
- }) => void;
11
- export declare const getConfiguredAudience: <Request_1 extends TBaseRequest>(options: TSessionMiddlewareOptions<Request_1>, requestPath: string) => string;
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, response: Response, next: NextFunction) => Promise<void>;
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?: Omit<ExpressJwtOptions, 'jwksUri'>;
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.0",
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.20.0",
38
- "express-jwt": "8.4.1",
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
- "@types/jsonwebtoken": "^9.0.2",
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
  }