{"version":3,"file":"authMiddleware-DkRImzMr.mjs","names":["createMiddleware","axios","AxiosError","https","serverEnv","scopes","definedScopes","getAppToken","getTokenOnBehalfOf","getAccessToken","ApiMiddlewareOptions","baseURL","scopeKey","httpsAgent","Agent","rejectUnauthorized","apiMiddleware","server","next","request","resolvedBaseURL","process","env","Error","authHeader","headers","get","accessToken","startsWith","substring","length","api","create","Authorization","context","error","response","data","message","createMiddleware","jose","permissions","serverEnv","getSessionUser","buildUser","hasPermission","TokenPayload","User","resolveUser","request","Request","Promise","authHeader","headers","get","startsWith","payload","verifyToken","substring","length","error","Response","json","message","Error","status","requiredAuthenticationMiddleware","server","user","next","context","publicAuthenticationMiddleware","authenticationMiddleware","options","optional","authorizationMiddleware","permissionKey","middleware","name","token","jwtVerify","getJWKS","issuer","ENTRA_TENANT_ID","audience","ENTRA_CLIENT_ID","jwksCache","ReturnType","createRemoteJWKSet","URL"],"sources":["../src/middleware/apiMiddleware.ts","../src/middleware/authMiddleware.ts"],"sourcesContent":["import { createMiddleware } from \"@tanstack/react-start\";\nimport axios, { AxiosError } from \"axios\";\nimport https from \"node:https\";\nimport type { serverEnv } from \"virtual:wcz-layout\";\nimport { scopes as definedScopes } from \"virtual:wcz-layout\";\nimport { getAppToken, getTokenOnBehalfOf } from \"~/lib/auth/msalServer\";\nimport { getAccessToken } from \"~/lib/auth/user\";\n\ninterface ApiMiddlewareOptions {\n  baseURL: keyof typeof serverEnv & `${string}BASE_URL${string}`;\n  scopeKey: keyof typeof definedScopes;\n}\n\nconst httpsAgent = new https.Agent({\n  rejectUnauthorized: false,\n});\n\nexport const apiMiddleware = ({ baseURL, scopeKey }: ApiMiddlewareOptions) =>\n  createMiddleware().server(async ({ next, request }) => {\n    const resolvedBaseURL = process.env[baseURL];\n    if (!resolvedBaseURL) throw new Error(`\"${baseURL}\" env variable is not set.`);\n\n    const authHeader = request.headers.get(\"Authorization\");\n    let accessToken: string;\n    if (authHeader?.startsWith(\"Bearer \")) {\n      accessToken = await getTokenOnBehalfOf(authHeader.substring(\"Bearer \".length), scopeKey);\n    } else {\n      try {\n        accessToken = await getAccessToken(scopeKey);\n      } catch {\n        accessToken = await getAppToken(scopeKey);\n      }\n    }\n\n    const api = axios.create({\n      baseURL: resolvedBaseURL,\n      httpsAgent,\n      headers: { Authorization: `Bearer ${accessToken}` },\n    });\n\n    try {\n      return await next({ context: { api } });\n    } catch (error) {\n      if (error instanceof AxiosError)\n        throw new Error(error.response?.data?.message ?? error.message);\n      throw error;\n    }\n  });\n","import { createMiddleware } from \"@tanstack/react-start\";\nimport * as jose from \"jose\";\nimport type { permissions } from \"virtual:wcz-layout\";\nimport { serverEnv } from \"~/env\";\nimport { getSessionUser } from \"~/lib/auth/user\";\nimport { buildUser, hasPermission } from \"~/lib/utils\";\nimport type { TokenPayload } from \"~/models/TokenPayload\";\nimport type { User } from \"~/models/User\";\n\nasync function resolveUser(request: Request): Promise<User | null> {\n  const authHeader = request.headers.get(\"Authorization\");\n\n  if (authHeader?.startsWith(\"Bearer \")) {\n    let payload: TokenPayload;\n    try {\n      payload = await verifyToken(authHeader.substring(\"Bearer \".length));\n    } catch (error) {\n      throw Response.json(\n        { message: error instanceof Error ? error.message : \"Unauthorized: Invalid access token\" },\n        { status: 401 },\n      );\n    }\n    return buildUser(payload);\n  }\n\n  return getSessionUser();\n}\n\nconst requiredAuthenticationMiddleware = createMiddleware().server<{ user: User }>(\n  async ({ next, request }) => {\n    const user = await resolveUser(request);\n\n    if (!user)\n      throw Response.json({ message: \"Unauthorized: User not signed in\" }, { status: 401 });\n\n    return next({ context: { user } });\n  },\n);\n\nconst publicAuthenticationMiddleware = createMiddleware().server<{ user: User | null }>(\n  async ({ next, request }) => {\n    const user = await resolveUser(request);\n    return next({ context: { user } });\n  },\n);\n\nexport function authenticationMiddleware(options?: {\n  optional?: false;\n}): typeof requiredAuthenticationMiddleware;\n\nexport function authenticationMiddleware(options: {\n  optional: true;\n}): typeof publicAuthenticationMiddleware;\n\nexport function authenticationMiddleware(options: {\n  optional: boolean;\n}): typeof requiredAuthenticationMiddleware | typeof publicAuthenticationMiddleware;\n\nexport function authenticationMiddleware(options?: { optional?: boolean }) {\n  return options?.optional ? publicAuthenticationMiddleware : requiredAuthenticationMiddleware;\n}\n\nexport const authorizationMiddleware = (permissionKey: keyof typeof permissions) =>\n  createMiddleware()\n    .middleware([authenticationMiddleware()])\n    .server(async ({ next, context }) => {\n      if (hasPermission(context.user, permissionKey)) return next();\n      throw Response.json(\n        {\n          message: `Forbidden: User ${context.user.name} is not authorized to access this resource`,\n        },\n        { status: 403 },\n      );\n    });\n\nasync function verifyToken(token: string): Promise<TokenPayload> {\n  const { payload } = await jose.jwtVerify(token, getJWKS(), {\n    issuer: `https://login.microsoftonline.com/${serverEnv.ENTRA_TENANT_ID}/v2.0`,\n    audience: serverEnv.ENTRA_CLIENT_ID,\n  });\n  return payload as unknown as TokenPayload;\n}\n\nlet jwksCache: ReturnType<typeof jose.createRemoteJWKSet> | null = null;\n\nfunction getJWKS() {\n  jwksCache ??= jose.createRemoteJWKSet(\n    new URL(`https://login.microsoftonline.com/${serverEnv.ENTRA_TENANT_ID}/discovery/v2.0/keys`),\n  );\n  return jwksCache;\n}\n"],"mappings":"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"}