You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

41 lines
1.2 KiB

import type { Permission } from "@/lib/constants/auth";
import { forbidden } from "@/modules/auth/errors";
import type { AuthContext } from "@/modules/auth/rbac";
export type ServiceAuthContext = Extract<AuthContext, { type: "service" }>;
/** 从 middleware 注入的请求头解析宿主鉴权上下文 */
export function parseServiceAuth(request: Request): ServiceAuthContext {
const authType = request.headers.get("x-auth-type");
if (authType !== "service") {
throw forbidden("需要宿主 Service Token");
}
const customerId = request.headers.get("x-customer-id");
if (!customerId) {
throw forbidden("缺少客户标识");
}
const permissionsRaw = request.headers.get("x-permissions") ?? "";
const permissions = permissionsRaw
.split(",")
.map((p) => p.trim())
.filter(Boolean) as Permission[];
return {
type: "service",
customerId,
permissions,
};
}
/** 校验请求体 customer_id 与 token 租户一致 */
export function assertCustomerMatch(
auth: ServiceAuthContext,
bodyCustomerId: string,
): void {
if (auth.customerId !== bodyCustomerId) {
throw forbidden("customer_id 与令牌租户不匹配");
}
}