UNPKG

@clerk/express

Version:

Clerk server SDK for usage with Express

204 lines (193 loc) • 6.6 kB
import { incomingMessageToRequest, loadApiEnv, loadClientEnv, requestHasAuthObject } from "./chunk-T3MW5TRG.mjs"; // src/index.ts export * from "@clerk/backend"; // src/clerkClient.ts import { createClerkClient } from "@clerk/backend"; var clerkClientSingleton = {}; var clerkClient = new Proxy(clerkClientSingleton, { get(_target, property) { if (property in clerkClientSingleton) { return clerkClientSingleton[property]; } const env = { ...loadApiEnv(), ...loadClientEnv() }; const client = createClerkClient({ ...env, userAgent: `${"@clerk/express"}@${"1.7.15"}` }); if (env.secretKey) { clerkClientSingleton = client; } return client[property]; }, set() { return false; } }); // src/authenticateRequest.ts import { AuthStatus, createClerkRequest } from "@clerk/backend/internal"; import { deprecated } from "@clerk/shared/deprecated"; import { isDevelopmentFromSecretKey } from "@clerk/shared/keys"; import { isHttpOrHttps, isProxyUrlRelative, isValidProxyUrl } from "@clerk/shared/proxy"; import { handleValueOrFn } from "@clerk/shared/utils"; // src/errors.ts var createErrorMessage = (msg) => { return `\u{1F512} Clerk: ${msg.trim()} For more info, check out the docs: https://clerk.com/docs, or come say hi in our discord server: https://clerk.com/discord `; }; var middlewareRequired = (fnName) => createErrorMessage(`The "clerkMiddleware" should be registered before using "${fnName}". Example: import express from 'express'; import { clerkMiddleware } from '@clerk/express'; const app = express(); app.use(clerkMiddleware()); `); var satelliteAndMissingProxyUrlAndDomain = "Missing domain and proxyUrl. A satellite application needs to specify a domain or a proxyUrl"; var satelliteAndMissingSignInUrl = ` Invalid signInUrl. A satellite application requires a signInUrl for development instances. Check if signInUrl is missing from your configuration or if it is not an absolute URL.`; // src/authenticateRequest.ts var authenticateRequest = (opts) => { const { clerkClient: clerkClient2, request, options } = opts; const { jwtKey, authorizedParties, audience, acceptsToken } = options || {}; const clerkRequest = createClerkRequest(incomingMessageToRequest(request)); const env = { ...loadApiEnv(), ...loadClientEnv() }; const secretKey = options?.secretKey || env.secretKey; const publishableKey = options?.publishableKey || env.publishableKey; const isSatellite = handleValueOrFn(options?.isSatellite, clerkRequest.clerkUrl, env.isSatellite); const domain = handleValueOrFn(options?.domain, clerkRequest.clerkUrl) || env.domain; const signInUrl = options?.signInUrl || env.signInUrl; const proxyUrl = absoluteProxyUrl( handleValueOrFn(options?.proxyUrl, clerkRequest.clerkUrl, env.proxyUrl), clerkRequest.clerkUrl.toString() ); if (isSatellite && !proxyUrl && !domain) { throw new Error(satelliteAndMissingProxyUrlAndDomain); } if (isSatellite && !isHttpOrHttps(signInUrl) && isDevelopmentFromSecretKey(secretKey || "")) { throw new Error(satelliteAndMissingSignInUrl); } return clerkClient2.authenticateRequest(clerkRequest, { audience, secretKey, publishableKey, jwtKey, authorizedParties, proxyUrl, isSatellite, domain, signInUrl, acceptsToken }); }; var setResponseHeaders = (requestState, res) => { if (requestState.headers) { requestState.headers.forEach((value, key) => res.appendHeader(key, value)); } return setResponseForHandshake(requestState, res); }; var setResponseForHandshake = (requestState, res) => { const hasLocationHeader = requestState.headers.get("location"); if (hasLocationHeader) { res.status(307).end(); return; } if (requestState.status === AuthStatus.Handshake) { return new Error("Clerk: unexpected handshake without redirect"); } return; }; var absoluteProxyUrl = (relativeOrAbsoluteUrl, baseUrl) => { if (!relativeOrAbsoluteUrl || !isValidProxyUrl(relativeOrAbsoluteUrl) || !isProxyUrlRelative(relativeOrAbsoluteUrl)) { return relativeOrAbsoluteUrl; } return new URL(relativeOrAbsoluteUrl, baseUrl).toString(); }; var authenticateAndDecorateRequest = (options = {}) => { const clerkClient2 = options.clerkClient || clerkClient; const enableHandshake = options.enableHandshake ?? true; const middleware = async (request, response, next) => { if (request.auth) { return next(); } try { const requestState = await authenticateRequest({ clerkClient: clerkClient2, request, options }); if (enableHandshake) { const err = setResponseHeaders(requestState, response); if (err) { return next(err); } if (response.writableEnded) { return; } } const authHandler = (opts) => requestState.toAuth(opts); const authObject = requestState.toAuth(); const auth = new Proxy(authHandler, { get(target, prop, receiver) { deprecated("req.auth", "Use `req.auth()` as a function instead."); if (prop in target) return Reflect.get(target, prop, receiver); return authObject?.[prop]; } }); Object.assign(request, { auth }); next(); } catch (err) { next(err); } }; return middleware; }; // src/clerkMiddleware.ts var clerkMiddleware = (options = {}) => { const authMiddleware = authenticateAndDecorateRequest({ ...options, acceptsToken: "any" }); return (request, response, next) => { authMiddleware(request, response, next); }; }; // src/getAuth.ts import { getAuthObjectForAcceptedToken } from "@clerk/backend/internal"; var getAuth = (req, options) => { if (!requestHasAuthObject(req)) { throw new Error(middlewareRequired("getAuth")); } const authObject = req.auth(options); return getAuthObjectForAcceptedToken({ authObject, acceptsToken: options?.acceptsToken }); }; // src/requireAuth.ts var requireAuth = (options = {}) => { const authMiddleware = authenticateAndDecorateRequest({ ...options, acceptsToken: "any" }); return (request, response, next) => { authMiddleware(request, response, (err) => { if (err) { return next(err); } const signInUrl = options.signInUrl || process.env.CLERK_SIGN_IN_URL || "/"; if (!request.auth()?.userId) { return response.redirect(signInUrl); } next(); }); }; }; export { authenticateRequest, clerkClient, clerkMiddleware, getAuth, requireAuth }; //# sourceMappingURL=index.mjs.map