feat(auth): 관리자 판별을 Keycloak 역할(role)에서 그룹(group) 기반으로 변경
- auth.js: realm_access.roles/resource_access 대신 ID 토큰 claims.groups 사용 (group-membership 매퍼, full.path=false 대비 앞 슬래시 제거 후 비교) - config.js: adminRole(ADMIN_ROLE, "admin") → adminGroup(ADMIN_GROUP, "DevOps") - server.js: 세션 user 주석 roles → groups - CLAUDE.md: 인증 모델·Kubero Env 문서 갱신 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
15
src/auth.js
15
src/auth.js
@@ -42,20 +42,15 @@ export async function handleCallback(req) {
|
||||
nonce,
|
||||
});
|
||||
const claims = tokenSet.claims();
|
||||
// Keycloak realm 역할: realm_access.roles. (클라이언트 역할은 resource_access[client].roles)
|
||||
const realmRoles = (claims.realm_access && claims.realm_access.roles) || [];
|
||||
const clientRoles =
|
||||
(claims.resource_access &&
|
||||
claims.resource_access[config.oidc.clientId] &&
|
||||
claims.resource_access[config.oidc.clientId].roles) ||
|
||||
[];
|
||||
const roles = [...new Set([...realmRoles, ...clientRoles])];
|
||||
// 그룹 기반 관리자 판별. Keycloak group-membership 매퍼가 ID 토큰에 groups 를 넣는다.
|
||||
// full.path=false 라 보통 "DevOps" 형태지만, 설정에 따라 "/DevOps" 일 수 있어 앞 슬래시는 떼고 비교.
|
||||
const groups = (Array.isArray(claims.groups) ? claims.groups : []).map((g) => g.replace(/^\//, ""));
|
||||
return {
|
||||
sabun: claims.preferred_username, // 사번
|
||||
name: claims.name || claims.given_name || claims.preferred_username,
|
||||
email: claims.email,
|
||||
roles,
|
||||
isAdmin: roles.includes(config.adminRole),
|
||||
groups,
|
||||
isAdmin: groups.includes(config.adminGroup),
|
||||
// SSO 로그아웃(end-session) 시 id_token_hint 로 사용
|
||||
id_token: tokenSet.id_token,
|
||||
};
|
||||
|
||||
@@ -13,8 +13,9 @@ export const config = {
|
||||
// redirect 는 baseUrl + /auth/callback 로 구성
|
||||
},
|
||||
|
||||
// 관리자 판별용 Keycloak 역할 이름. 이 role 을 가진 사용자에게만 인프라 도구 노출.
|
||||
adminRole: process.env.ADMIN_ROLE || "admin",
|
||||
// 관리자 판별용 Keycloak 그룹 이름. 이 그룹에 속한 사용자에게만 인프라 도구 노출.
|
||||
// (groups 클레임은 portal 클라이언트의 group-membership 매퍼가 ID 토큰에 넣어줌)
|
||||
adminGroup: process.env.ADMIN_GROUP || "DevOps",
|
||||
|
||||
// 프로젝트 등록 시 Gitea 언어 통계 API 로 메인 언어 자동 판별용 토큰(선택).
|
||||
// 공개 레포는 없어도 되고, 비공개 레포 조회에만 필요.
|
||||
|
||||
@@ -65,7 +65,7 @@ app.get("/auth/callback", async (req, res) => {
|
||||
const { id_token, ...user } = u;
|
||||
req.session.idToken = id_token;
|
||||
await db.upsertUser(user);
|
||||
req.session.user = user; // { sabun, name, email, roles, isAdmin }
|
||||
req.session.user = user; // { sabun, name, email, groups, isAdmin }
|
||||
res.redirect("/");
|
||||
} catch (e) {
|
||||
console.error("oidc callback error", e);
|
||||
|
||||
Reference in New Issue
Block a user