fix: toAuthUser 对 realm_access.roles/groups 做运行时数组校验(防字符串子串匹配越权)

This commit is contained in:
lovefyf
2026-08-13 01:11:33 +08:00
parent 3070cbe52f
commit 76296b1623
+16 -2
View File
@@ -50,13 +50,27 @@ export async function verifyAccessToken(token: string): Promise<JWTPayload> {
return payload;
}
/**
* 运行时数组守卫:非数组(例如 Keycloak 把 realm_access.roles 误配成单值 String claim)
* 一律降为空数组——失败关闭。否则 `roles.includes('admin')` 会退化成
* String.prototype.includes,"superadmin" 将子串命中 "admin" 造成越权。
*/
function stringArray(v: unknown): string[] {
return Array.isArray(v) ? v.filter((x): x is string => typeof x === 'string') : [];
}
export function toAuthUser(p: JWTPayload): AuthUser {
const username = (p['preferred_username'] as string | undefined) ?? '';
const realmAccess = p['realm_access'];
const user: AuthUser = {
id: p.sub ?? '',
username,
roles: (p['realm_access'] as { roles?: string[] } | undefined)?.roles ?? [],
groups: (p['groups'] as string[] | undefined) ?? [],
roles: stringArray(
typeof realmAccess === 'object' && realmAccess !== null
? (realmAccess as { roles?: unknown }).roles
: undefined,
),
groups: stringArray(p['groups']),
isService: username.startsWith('service-account-'),
};
const azp = p['azp'];