wcz-layout
Version:
73 lines (72 loc) • 3.43 kB
JavaScript
import { n as serverEnv } from "./env-Bm6rrgwT.mjs";
import { n as getSessionUser } from "./user-BQiWoQk1.mjs";
import { i as buildUser, o as hasPermission } from "./utils-DpcYsXTK.mjs";
import { t as apiMiddleware } from "./apiMiddleware-DRhawg5S.mjs";
import { z } from "zod";
import { createCsrfMiddleware, createMiddleware } from "@tanstack/react-start";
import * as jose from "jose";
//#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
//#region src/middleware/validationMiddleware.ts
const validationMiddleware = (schema) => createMiddleware().server(async ({ next, request }) => {
const json = await request.json();
const result = schema.safeParse(json);
if (!result.success) {
const { fieldErrors } = z.flattenError(result.error);
const firstFieldName = Object.keys(fieldErrors)[0];
const firstErrorMessage = fieldErrors[firstFieldName]?.[0];
if (firstFieldName && firstErrorMessage) {
const name = firstFieldName.charAt(0).toUpperCase() + firstFieldName.slice(1);
const message = firstErrorMessage.replace(/^Invalid input:\s*/i, "").toLowerCase();
return Response.json({ message: `${name} - ${message}` }, { status: 400 });
}
return Response.json({ message: "Validation failed" }, { status: 400 });
}
return await next({ context: { data: result.data } });
});
//#endregion
//#region src/middleware/csrfMiddleware.ts
const csrfMiddleware = createCsrfMiddleware({ filter: (ctx) => ctx.handlerType === "serverFn" });
//#endregion
export { apiMiddleware, authenticationMiddleware, authorizationMiddleware, csrfMiddleware, validationMiddleware };
//# sourceMappingURL=middleware.mjs.map