UNPKG

wcz-layout

Version:

78 lines (77 loc) 3.42 kB
import { t as serverEnv } from "./env-CGwonXSv.mjs"; import { i as buildUser, l as getAccessToken, o as hasPermission, u as getSessionUser } from "./utils-CnwPC4sC.mjs"; import { n as getTokenOnBehalfOf, t as getAppToken } from "./msalServer-VQVVDgat.mjs"; import { createMiddleware } from "@tanstack/react-start"; import axios, { AxiosError } from "axios"; import https from "node:https"; import * as jose from "jose"; //#region src/middleware/apiMiddleware.ts const httpsAgent = new https.Agent({ rejectUnauthorized: false }); const apiMiddleware = ({ baseURL, scopeKey }) => createMiddleware().server(async ({ next, request }) => { const resolvedBaseURL = process.env[baseURL]; if (!resolvedBaseURL) throw new Error(`"${baseURL}" env variable is not set.`); const authHeader = request.headers.get("Authorization"); let accessToken; if (authHeader?.startsWith("Bearer ")) accessToken = await getTokenOnBehalfOf(authHeader.substring(7), scopeKey); else try { accessToken = await getAccessToken(scopeKey); } catch { accessToken = await getAppToken(scopeKey); } const api = axios.create({ baseURL: resolvedBaseURL, httpsAgent, headers: { Authorization: `Bearer ${accessToken}` } }); try { return await next({ context: { api } }); } catch (error) { if (error instanceof AxiosError) throw new Error(error.response?.data?.message ?? error.message); throw error; } }); //#endregion //#region src/middleware/authMiddleware.ts async function resolveUser(request) { const authHeader = request.headers.get("Authorization"); if (authHeader?.startsWith("Bearer ")) { let payload; try { payload = await verifyToken(authHeader.substring(7)); } catch (error) { throw Response.json({ message: error instanceof Error ? error.message : "Unauthorized: Invalid access token" }, { status: 401 }); } return buildUser(payload); } return getSessionUser(); } const requiredAuthenticationMiddleware = createMiddleware().server(async ({ next, request }) => { const user = await resolveUser(request); if (!user) throw Response.json({ message: "Unauthorized: User not signed in" }, { status: 401 }); return next({ context: { user } }); }); const publicAuthenticationMiddleware = createMiddleware().server(async ({ next, request }) => { return next({ context: { user: await resolveUser(request) } }); }); function authenticationMiddleware(options) { return options?.optional ? publicAuthenticationMiddleware : requiredAuthenticationMiddleware; } const authorizationMiddleware = (permissionKey) => createMiddleware().middleware([authenticationMiddleware()]).server(async ({ next, context }) => { if (hasPermission(context.user, permissionKey)) return next(); throw Response.json({ message: `Forbidden: User ${context.user.name} is not authorized to access this resource` }, { status: 403 }); }); async function verifyToken(token) { const { payload } = await jose.jwtVerify(token, getJWKS(), { issuer: `https://login.microsoftonline.com/${serverEnv.ENTRA_TENANT_ID}/v2.0`, audience: serverEnv.ENTRA_CLIENT_ID }); return payload; } let jwksCache = null; function getJWKS() { jwksCache ??= jose.createRemoteJWKSet(new URL(`https://login.microsoftonline.com/${serverEnv.ENTRA_TENANT_ID}/discovery/v2.0/keys`)); return jwksCache; } //#endregion export { authorizationMiddleware as n, apiMiddleware as r, authenticationMiddleware as t }; //# sourceMappingURL=authMiddleware-DkRImzMr.mjs.map