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
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 与令牌租户不匹配");
|
|
}
|
|
}
|