'use strict'; var chunkSXKQ7CSX_cjs = require('./chunk-SXKQ7CSX.cjs'); // src/server/auth/defaults.ts var defaultAuthConfig = { protected: ["/api/*"], public: ["/api", "/api/auth/*"], // Simple rule system rules: [ // Admin users can do anything { condition: (user) => { if (typeof user === "object" && user !== null) { if ("isAdmin" in user) { return !!user.isAdmin; } if ("role" in user) { return user.role === "admin"; } } return false; }, allow: true } ] }; // src/server/auth/path-pattern.ts function parse(input, loose) { if (input instanceof RegExp) return { keys: false, pattern: input }; let c; let o; let tmp; let ext; const keys = []; let pattern = ""; const arr = input.split("/"); arr[0] || arr.shift(); while (tmp = arr.shift()) { c = tmp[0]; if (c === "*") { keys.push(c); pattern += tmp[1] === "?" ? "(?:/(.*))?" : "/(.*)"; } else if (c === ":") { o = tmp.indexOf("?", 1); ext = tmp.indexOf(".", 1); keys.push(tmp.substring(1, !!~o ? o : !!~ext ? ext : tmp.length)); pattern += !!~o && !~ext ? "(?:/([^/]+?))?" : "/([^/]+?)"; if (!!~ext) pattern += (!!~o ? "?" : "") + "\\" + tmp.substring(ext); } else { pattern += "/" + tmp; } } return { keys, pattern: new RegExp("^" + pattern + ("/?$"), "i") }; } // src/server/auth/helpers.ts var isProtectedCustomRoute = (path, method, customRouteAuthConfig) => { if (!customRouteAuthConfig) { return false; } const exactRouteKey = `${method}:${path}`; if (customRouteAuthConfig.has(exactRouteKey)) { return customRouteAuthConfig.get(exactRouteKey) === true; } const allRouteKey = `ALL:${path}`; if (customRouteAuthConfig.has(allRouteKey)) { return customRouteAuthConfig.get(allRouteKey) === true; } for (const [routeKey, requiresAuth] of customRouteAuthConfig.entries()) { const colonIndex = routeKey.indexOf(":"); if (colonIndex === -1) { continue; } const routeMethod = routeKey.substring(0, colonIndex); const routePattern = routeKey.substring(colonIndex + 1); if (routeMethod !== method && routeMethod !== "ALL") { continue; } if (pathMatchesPattern(path, routePattern)) { return requiresAuth === true; } } return false; }; var findMatchingCustomRoute = (path, method, apiRoutes) => { if (!apiRoutes) return void 0; for (const route of apiRoutes) { if (route.method !== method && route.method !== "ALL") continue; const { keys, pattern: regex } = parse(route.path); const match = regex.exec(path); if (!match) continue; const params = {}; if (keys && keys.length > 0) { for (let i = 0; i < keys.length; i++) { if (match[i + 1] !== void 0) { params[keys[i]] = match[i + 1]; } } } return { route, params }; } return void 0; }; var isDevPlaygroundRequest = (path, method, getHeader, authConfig, customRouteAuthConfig) => { const protectedAccess = [...defaultAuthConfig.protected || [], ...authConfig.protected || []]; return process.env.MASTRA_DEV === "true" && // Allow if path doesn't match protected patterns AND is not a protected custom route (!isAnyMatch(path, method, protectedAccess) && !isProtectedCustomRoute(path, method, customRouteAuthConfig) || // Or if has playground header getHeader("x-mastra-dev-playground") === "true"); }; var isCustomRoutePublic = (path, method, customRouteAuthConfig) => { if (!customRouteAuthConfig) { return false; } const exactRouteKey = `${method}:${path}`; if (customRouteAuthConfig.has(exactRouteKey)) { return !customRouteAuthConfig.get(exactRouteKey); } const allRouteKey = `ALL:${path}`; if (customRouteAuthConfig.has(allRouteKey)) { return !customRouteAuthConfig.get(allRouteKey); } for (const [routeKey, requiresAuth] of customRouteAuthConfig.entries()) { const colonIndex = routeKey.indexOf(":"); if (colonIndex === -1) { continue; } const routeMethod = routeKey.substring(0, colonIndex); const routePattern = routeKey.substring(colonIndex + 1); if (routeMethod !== method && routeMethod !== "ALL") { continue; } if (pathMatchesPattern(path, routePattern)) { return !requiresAuth; } } return false; }; var isProtectedPath = (path, method, authConfig, customRouteAuthConfig) => { const protectedAccess = [...defaultAuthConfig.protected || [], ...authConfig.protected || []]; return isAnyMatch(path, method, protectedAccess) || isProtectedCustomRoute(path, method, customRouteAuthConfig); }; var canAccessPublicly = (path, method, authConfig) => { const publicAccess = [...defaultAuthConfig.public || [], ...authConfig.public || []]; return isAnyMatch(path, method, publicAccess); }; var isAnyMatch = (path, method, patterns) => { if (!patterns) { return false; } for (const patternPathOrMethod of patterns) { if (patternPathOrMethod instanceof RegExp) { if (patternPathOrMethod.test(path)) { return true; } } if (typeof patternPathOrMethod === "string" && pathMatchesPattern(path, patternPathOrMethod)) { return true; } if (Array.isArray(patternPathOrMethod) && patternPathOrMethod.length === 2) { const [pattern, methodOrMethods] = patternPathOrMethod; if (pathMatchesPattern(path, pattern) && matchesOrIncludes(methodOrMethods, method)) { return true; } } } return false; }; var pathMatchesPattern = (path, pattern) => { const { pattern: regex } = parse(pattern); return regex.test(path); }; var pathMatchesRule = (path, rulePath) => { if (!rulePath) return true; if (typeof rulePath === "string") { return pathMatchesPattern(path, rulePath); } if (rulePath instanceof RegExp) { return rulePath.test(path); } if (Array.isArray(rulePath)) { return rulePath.some((p) => pathMatchesPattern(path, p)); } return false; }; var matchesOrIncludes = (values, value) => { if (typeof values === "string") { return values === value; } if (Array.isArray(values)) { return values.includes(value); } return false; }; var pass = { action: "next" }; var adaptToMastraAuthRequest = (request) => { if (!(request instanceof Request)) { return request; } return { raw: request, headers: request.headers, header: (name) => request.headers.get(name) ?? void 0 }; }; var getAuthenticatedUser = async ({ mastra, token, request }) => { const normalizedToken = token.replace(/^Bearer\s+/i, "").trim(); if (!normalizedToken) { return null; } const authConfig = mastra.getServer()?.auth; if (!authConfig || typeof authConfig.authenticateToken !== "function") { return null; } return await authConfig.authenticateToken(normalizedToken, request); }; function supportsSessionRefresh(authConfig) { return typeof authConfig.getSessionIdFromRequest === "function" && typeof authConfig.refreshSession === "function" && typeof authConfig.getSessionHeaders === "function"; } var coreAuthMiddleware = async (ctx) => { const { path, method, getHeader, mastra, authConfig, customRouteAuthConfig, requestContext, rawRequest, token, requiresAuth } = ctx; const hasAuthProvider = typeof authConfig.authenticateToken === "function"; if (!hasAuthProvider && isDevPlaygroundRequest(path, method, getHeader, authConfig, customRouteAuthConfig)) { return pass; } if (!isProtectedPath(path, method, authConfig, customRouteAuthConfig)) { return pass; } if (!requiresAuth && canAccessPublicly(path, method, authConfig)) { return pass; } let user; let refreshHeaders; const authRequest = adaptToMastraAuthRequest(rawRequest); try { if (typeof authConfig.authenticateToken === "function") { user = await authConfig.authenticateToken(token ?? "", authRequest); } else { throw new Error("No token verification method configured"); } if (!user && supportsSessionRefresh(authConfig) && rawRequest instanceof Request) { try { const sessionId = authConfig.getSessionIdFromRequest(rawRequest); if (sessionId) { const newSession = await authConfig.refreshSession(sessionId); if (newSession) { refreshHeaders = authConfig.getSessionHeaders(newSession); const refreshedCookie = Object.entries(refreshHeaders).filter(([k]) => k.toLowerCase() === "set-cookie").map(([, v]) => v.split(";")[0]).join("; "); if (refreshedCookie) { const refreshedRequest = new Request(rawRequest.url, { method: rawRequest.method, headers: new Headers(rawRequest.headers) }); refreshedRequest.headers.set("Cookie", refreshedCookie); const cookieValue = refreshedCookie.includes("=") ? refreshedCookie.split("=").slice(1).join("=") : refreshedCookie; user = await authConfig.authenticateToken(cookieValue, adaptToMastraAuthRequest(refreshedRequest)); } if (!user) { refreshHeaders = void 0; } } } } catch (refreshErr) { refreshHeaders = void 0; mastra.getLogger()?.debug("Session refresh failed, falling back to 401", { error: refreshErr instanceof Error ? { message: refreshErr.message } : refreshErr }); } } if (!user) { return { action: "error", status: 401, body: { error: "Invalid or expired token" }, headers: refreshHeaders }; } requestContext.set(chunkSXKQ7CSX_cjs.MASTRA_USER_KEY, user); requestContext.set("user", user); let effectiveToken = token; if (!effectiveToken && rawRequest instanceof Request) { const cookieHeader = rawRequest.headers.get("cookie"); if (cookieHeader) { const match = cookieHeader.match(/mastra-token=([^;]+)/); if (match?.[1]) effectiveToken = match[1]; } } if (effectiveToken) { requestContext.set(chunkSXKQ7CSX_cjs.MASTRA_AUTH_TOKEN_KEY, effectiveToken); } if (typeof authConfig.mapUserToResourceId === "function") { try { const resourceId = authConfig.mapUserToResourceId(user); if (resourceId) { requestContext.set(chunkSXKQ7CSX_cjs.MASTRA_RESOURCE_ID_KEY, resourceId); } } catch (mapError) { mastra.getLogger()?.error("mapUserToResourceId failed", { error: mapError instanceof Error ? { message: mapError.message, stack: mapError.stack } : mapError }); return { action: "error", status: 500, body: { error: "Failed to map authenticated user to a resource ID" }, headers: refreshHeaders }; } } try { const authMode = requestContext.get(chunkSXKQ7CSX_cjs.MASTRA_AUTH_MODE_KEY); const serverConfig = mastra.getServer(); const studioConfig = mastra.getStudio?.(); const rbacProvider = authMode === "studio" ? studioConfig?.rbac ?? serverConfig?.rbac : serverConfig?.rbac; if (rbacProvider) { if (!user || typeof user !== "object" || !("id" in user)) { mastra.getLogger()?.warn('RBAC: authenticated user missing required "id" field, skipping permission loading'); } else { const permissions = await rbacProvider.getPermissions(user); requestContext.set(chunkSXKQ7CSX_cjs.MASTRA_USER_PERMISSIONS_KEY, permissions); requestContext.set("userPermissions", permissions); const roles = await rbacProvider.getRoles(user); requestContext.set(chunkSXKQ7CSX_cjs.MASTRA_USER_ROLES_KEY, roles); requestContext.set("userRoles", roles); } } } catch (rbacError) { mastra.getLogger()?.error("RBAC: failed to load user permissions/roles", { error: rbacError instanceof Error ? { message: rbacError.message, stack: rbacError.stack } : rbacError }); } } catch (err) { mastra.getLogger()?.error("Authentication error", { error: err instanceof Error ? { message: err.message, stack: err.stack } : err }); return { action: "error", status: 401, body: { error: "Invalid or expired token" }, headers: refreshHeaders }; } if ("authorizeUser" in authConfig && typeof authConfig.authorizeUser === "function") { try { const isAuthorized = await authConfig.authorizeUser(user, authRequest); if (!isAuthorized) { return { action: "error", status: 403, body: { error: "Access denied" }, headers: refreshHeaders }; } } catch (err) { mastra.getLogger()?.error("Authorization error in authorizeUser", { error: err instanceof Error ? { message: err.message, stack: err.stack } : err }); return { action: "error", status: 500, body: { error: "Authorization error" }, headers: refreshHeaders }; } } else if ("authorize" in authConfig && typeof authConfig.authorize === "function") { try { const authorizeCtx = ctx.buildAuthorizeContext(); const isAuthorized = await authConfig.authorize(path, method, user, authorizeCtx); if (!isAuthorized) { return { action: "error", status: 403, body: { error: "Access denied" }, headers: refreshHeaders }; } } catch (err) { mastra.getLogger()?.error("Authorization error in authorize", { error: err instanceof Error ? { message: err.message, stack: err.stack } : err, path, method }); return { action: "error", status: 500, body: { error: "Authorization error" }, headers: refreshHeaders }; } } else if ("rules" in authConfig && authConfig.rules && authConfig.rules.length > 0) { const isAuthorized = await checkRules(authConfig.rules, path, method, user); if (!isAuthorized) { return { action: "error", status: 403, body: { error: "Access denied" }, headers: refreshHeaders }; } } else { const rbacProvider = mastra.getServer()?.rbac; if (rbacProvider) { if (defaultAuthConfig.rules && defaultAuthConfig.rules.length > 0) { const isAuthorized = await checkRules(defaultAuthConfig.rules, path, method, user); if (!isAuthorized) { return { action: "error", status: 403, body: { error: "Access denied" }, headers: refreshHeaders }; } } else { return { action: "error", status: 403, body: { error: "Access denied" }, headers: refreshHeaders }; } } } return refreshHeaders ? { action: "next", headers: refreshHeaders } : pass; }; var checkRules = async (rules, path, method, user) => { for (const i in rules || []) { const rule = rules?.[i]; if (!pathMatchesRule(path, rule.path)) { continue; } if (rule.methods && !matchesOrIncludes(rule.methods, method)) { continue; } const condition = rule.condition; if (typeof condition === "function") { const allowed = await Promise.resolve().then(() => condition(user)).catch(() => false); if (allowed) { return true; } } else if (rule.allow) { return true; } } return false; }; exports.canAccessPublicly = canAccessPublicly; exports.checkRules = checkRules; exports.coreAuthMiddleware = coreAuthMiddleware; exports.defaultAuthConfig = defaultAuthConfig; exports.findMatchingCustomRoute = findMatchingCustomRoute; exports.getAuthenticatedUser = getAuthenticatedUser; exports.isCustomRoutePublic = isCustomRoutePublic; exports.isDevPlaygroundRequest = isDevPlaygroundRequest; exports.isProtectedCustomRoute = isProtectedCustomRoute; exports.isProtectedPath = isProtectedPath; exports.matchesOrIncludes = matchesOrIncludes; exports.pathMatchesPattern = pathMatchesPattern; exports.pathMatchesRule = pathMatchesRule; exports.supportsSessionRefresh = supportsSessionRefresh; //# sourceMappingURL=chunk-4PQR3D5Y.cjs.map //# sourceMappingURL=chunk-4PQR3D5Y.cjs.map