fix: toAuthUser 对 realm_access.roles/groups 做运行时数组校验(防字符串子串匹配越权)
This commit is contained in:
@@ -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'];
|
||||
|
||||
Reference in New Issue
Block a user