@commercetools-backend/express
Advanced tools
Comparing version 16.6.2-canary.5 to 16.6.2-canary.6
@@ -1,2 +0,3 @@ | ||
export * from './constants'; | ||
export { CLOUD_IDENTIFIERS, MC_API_URLS } from './constants'; | ||
export { createSessionAuthVerifier } from './auth'; | ||
export { default as createSessionMiddleware } from './middlewares/session-middleware'; |
"use strict"; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./constants")); | ||
var constants_1 = require("./constants"); | ||
exports.CLOUD_IDENTIFIERS = constants_1.CLOUD_IDENTIFIERS; | ||
exports.MC_API_URLS = constants_1.MC_API_URLS; | ||
var auth_1 = require("./auth"); | ||
exports.createSessionAuthVerifier = auth_1.createSessionAuthVerifier; | ||
var session_middleware_1 = require("./middlewares/session-middleware"); | ||
exports.createSessionMiddleware = session_middleware_1.default; |
@@ -0,4 +1,4 @@ | ||
import type { Request, Response, NextFunction } from 'express'; | ||
import type { TSessionMiddlewareOptions } from '../types'; | ||
import type { Request, Response, NextFunction } from 'express'; | ||
declare function createSessionMiddleware(options: TSessionMiddlewareOptions): (request: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("express-serve-static-core").Query>, response: Response<any>, next: NextFunction) => any; | ||
declare function createSessionMiddleware(options: TSessionMiddlewareOptions): (request: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("express-serve-static-core").Query>, response: Response<any>, next: NextFunction) => Promise<void>; | ||
export default createSessionMiddleware; |
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const constants_1 = require("../constants"); | ||
const express_jwt_1 = __importDefault(require("express-jwt")); | ||
const jwks_rsa_1 = __importDefault(require("jwks-rsa")); | ||
const decodedTokenKey = 'decoded_token'; | ||
const mapCloudIdentifierToUrl = (issuer) => { | ||
switch (issuer) { | ||
case constants_1.CLOUD_IDENTIFIERS.GCP_AU: | ||
return constants_1.MC_API_URLS.GCP_AU; | ||
case constants_1.CLOUD_IDENTIFIERS.GCP_EU: { | ||
return constants_1.MC_API_URLS.GCP_EU; | ||
const auth_1 = require("../auth"); | ||
function createSessionMiddleware(options) { | ||
const sessionAuthVerifier = auth_1.createSessionAuthVerifier(options); | ||
return async (request, response, next) => { | ||
try { | ||
await sessionAuthVerifier(request, response); | ||
next(); | ||
} | ||
case constants_1.CLOUD_IDENTIFIERS.GCP_US: { | ||
return constants_1.MC_API_URLS.GCP_US; | ||
catch (error) { | ||
next(error); | ||
} | ||
case constants_1.CLOUD_IDENTIFIERS.AWS_FRA: | ||
return constants_1.MC_API_URLS.AWS_FRA; | ||
case constants_1.CLOUD_IDENTIFIERS.AWS_OHIO: | ||
return constants_1.MC_API_URLS.AWS_OHIO; | ||
default: | ||
return undefined; | ||
} | ||
}; | ||
const throwIfIssuerIsNotAValidUrl = (issuer) => { | ||
try { | ||
new URL(issuer); | ||
} | ||
catch (error) { | ||
throw new Error(`Invalid issuer URL "${issuer}". Expected a valid URL to the Merchant Center API Gateway, or a cloud identifier to one of the available cloud regions. See https://docs.commercetools.com/custom-applications/main-concepts/api-gateway#hostnames.`); | ||
} | ||
}; | ||
const writeSessionContext = (request) => { | ||
const decodedToken = request[decodedTokenKey]; | ||
const publicClaimForProjectKey = `${decodedToken.iss}/claims/project_key`; | ||
// @ts-ignore | ||
request.session = { | ||
userId: decodedToken.sub, | ||
projectKey: decodedToken[publicClaimForProjectKey], | ||
}; | ||
delete request.decoded_token; | ||
}; | ||
function createSessionMiddleware(options) { | ||
let configuredDefaultIssuer = mapCloudIdentifierToUrl(options.issuer); | ||
if (!configuredDefaultIssuer) { | ||
throwIfIssuerIsNotAValidUrl(options.issuer); | ||
configuredDefaultIssuer = options.issuer; | ||
} | ||
// Return the middleware | ||
return (request, response, next) => { | ||
var _a; | ||
const cloudIdentifierHeader = request.header('x-mc-api-cloud-identifier'); | ||
const issuer = options.inferIssuer && cloudIdentifierHeader | ||
? (_a = mapCloudIdentifierToUrl(cloudIdentifierHeader)) !== null && _a !== void 0 ? _a : configuredDefaultIssuer : configuredDefaultIssuer; | ||
const audience = `${request.hostname}${request.originalUrl}`; | ||
return express_jwt_1.default({ | ||
// Dynamically provide a signing key based on the kid in the header | ||
// and the singing keys provided by the JWKS endpoint | ||
secret: jwks_rsa_1.default.expressJwtSecret({ | ||
// Default options | ||
cache: true, | ||
rateLimit: true, | ||
jwksRequestsPerMinute: 5, | ||
// Pass custom options | ||
...(options.jwks || {}), | ||
// This should be set by the middleware, no matter what. | ||
jwksUri: `${issuer}/.well-known/jwks.json`, | ||
}), | ||
requestProperty: decodedTokenKey, | ||
// Validate the audience and the issuer. | ||
audience, | ||
issuer, | ||
algorithms: ['RS256'], | ||
})(request, response, (error) => { | ||
if (error) { | ||
return next(error); | ||
} | ||
// @ts-ignore | ||
writeSessionContext(request); | ||
next(); | ||
}); | ||
}; | ||
} | ||
exports.default = createSessionMiddleware; |
@@ -1,2 +0,1 @@ | ||
import type { Request } from 'express'; | ||
import type { ExpressJwtOptions } from 'jwks-rsa'; | ||
@@ -6,2 +5,3 @@ import { CLOUD_IDENTIFIERS } from './constants'; | ||
export declare type TSessionMiddlewareOptions = { | ||
audience: string; | ||
issuer: TCloudIdentifier | string; | ||
@@ -15,4 +15,1 @@ inferIssuer?: boolean; | ||
}; | ||
export declare type TRequestWithSession = Request & { | ||
session: TSession; | ||
}; |
{ | ||
"name": "@commercetools-backend/express", | ||
"version": "16.6.2-canary.5+19f8216", | ||
"version": "16.6.2-canary.6+74cc9f2", | ||
"description": "Zero-config HTTP server as Express.js to facilitate development", | ||
@@ -48,3 +48,3 @@ "bugs": "https://github.com/commercetools/merchant-center-application-kit/issues", | ||
}, | ||
"gitHead": "19f8216a871efd42ab0797c9710b08c26376f0ee" | ||
"gitHead": "74cc9f2248621dddf563692197c8e348d4100eb2" | ||
} |
@@ -19,3 +19,3 @@ # @commercetools-backend/express | ||
This middleware should be used to handle the authentication exchange between the server and the `/proxy/forward-to` endpoint of the Merchant Center API Gateway. | ||
This Express.js middleware should be used to handle the authentication exchange between the server and the `/proxy/forward-to` endpoint of the Merchant Center API Gateway. | ||
@@ -30,3 +30,8 @@ > You can read more about the "Proxy to External API" concepts [here](https://docs.commercetools.com/custom-applications/main-concepts/proxy-to-external-api). | ||
app.use(createSessionMiddleware({ mcApiUrl: CLOUD_IDENTIFIERS.GCP_EU })); | ||
app.use( | ||
createSessionMiddleware({ | ||
audience: 'https://my-api-server.com', | ||
issuer: CLOUD_IDENTIFIERS.GCP_EU, | ||
}) | ||
); | ||
app.use((request, response, next) => { | ||
@@ -39,4 +44,6 @@ // `request.session` contains the useful information | ||
- `issuer` (_string_): either a cloud identifier or a valid URL to the Merchant Center API Gateway. The cloud identifier maps to the Merchant Center API URL of the related [cloud region](https://docs.commercetools.com/custom-applications/main-concepts/api-gateway#cloud-regions). | ||
- `audience` (_string_): The public-facing URL of your API server. The value should only contain the origin URL (protocol, hostname, port), the request path is inferred from the incoming request. | ||
- `issuer` (_string_): Either a cloud identifier or a valid URL to the Merchant Center API Gateway. The cloud identifier maps to the Merchant Center API URL of the related [cloud region](https://docs.commercetools.com/custom-applications/main-concepts/api-gateway#cloud-regions). | ||
- `gcp-au`: `https://mc-api.australia-southeast1.gcp.commercetools.com` | ||
@@ -48,2 +55,33 @@ - `gcp-eu`: `https://mc-api.europe-west1.gcp.commercetools.com` | ||
- `inferIssuer` (_boolean_): determines whether the issuer should be inferred from the custom request HTTP header `x-mc-api-cloud-identifier` which is sent by the Merchant Center API Gateway when forwarding the request. This might be useful in case the server is used in multiple regions. | ||
- `inferIssuer` (_boolean_): Determines whether the issuer should be inferred from the custom request HTTP header `x-mc-api-cloud-identifier` which is sent by the Merchant Center API Gateway when forwarding the request. This might be useful in case the server is used in multiple regions. | ||
### Usage in Serverless Functions | ||
If your HTTP server runs as a Serverless Function, the Express.js middleware should not be needed. Instead you can use the underlying function that does not require the `next` callback. | ||
**Example for Google Cloud Functions** | ||
```js | ||
const { | ||
createSessionAuthVerifier, | ||
CLOUD_IDENTIFIERS, | ||
} = require('@commercetools-backend/express'); | ||
const sessionAuthVerifier = createSessionAuthVerifier({ | ||
audience: 'https://my-api-server.com', | ||
issuer: CLOUD_IDENTIFIERS.GCP_EU, | ||
}); | ||
exports.handler = async function (request, response) { | ||
try { | ||
await sessionAuthVerifier(request, response); | ||
} catch (error) { | ||
response.status(401).send(JSON.stringify({ message: 'Unauthorized' })); | ||
return; | ||
} | ||
// `request.session` contains the useful information | ||
}; | ||
``` | ||
> The same concept applies for serverless functions in other cloud providers. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
14071
13
176
84
2