구성 사례 — React + Node + Nginx(+OAuth2-Proxy)로 RBAC 붙이기
개요 — “프론트(React)는 로그인/토큰 획득”, “백엔드(Node)는 토큰 검증”, “프록시(Nginx/OAuth2-Proxy)는 경로 단위 접근제어”로 역할을 나누면 운영이 편해진다.
1) 아키텍처
Browser React Portal Nginx TLS / Routing auth_request 가능 OAuth2-Proxy (선택) 헤더로 사용자/권한 전달 Keycloak OIDC Provider Node API (JWT Verify + RBAC) API 호출 1) 로그인 필요 2) 토큰 발급 3) 토큰 검증 + 역할 기반 인가2) React(Portal)에서의 권장 패턴
- 일반적으로 SPA는 Authorization Code Flow + PKCE를 사용
- 로그인/로그아웃/토큰 갱신은 JS 어댑터(keycloak-js) 또는 표준 OIDC 클라이언트로 처리
운영 팁: SPA에서 토큰을 “어디에 저장하냐(localStorage 등)”는 보안/정책과 직결이다.
조직 정책에 맞춰 저장 전략(메모리/세션/쿠키 기반)을 먼저 합의해두는 게 좋다.
3) Node(API)에서의 권장 패턴
Node API는 결국 “JWT 검증”을 하고, claim(roles)을 보고 인가한다.
- 토큰 서명 검증(JWKS)
- iss/aud/exp 체크
- roles claim을 읽어서 라우트별 권한 체크
// 의사코드(개념)
// 1) Authorization 헤더에서 Bearer 토큰 추출
// 2) JWKS로 서명 검증
// 3) roles 확인 후 RBAC
function requireRole(role) {
return (req, res, next) => {
const roles = req.user?.realm_access?.roles || [];
if (!roles.includes(role)) return res.status(403).send("Forbidden");
next();
};
}
// 예: /admin 은 infra-admin만
app.get("/admin", requireRole("infra-admin"), handler);
4) Nginx(+OAuth2-Proxy)로 “경로 단위 RBAC”
운영자 입장에서 편한 방식은 “프록시에서 1차 차단”을 거는 것이다.
- /admin → infra-admin만
- /ops → infra-operator 이상
- /view → readonly 이상
OAuth2-Proxy를 붙이면 Nginx auth_request로 인증을 외주화하고, upstream으로 X-Auth-Request-User 같은 헤더를 내려서 앱이 쉽게 쓸 수 있다.
✔️ 운영 포인트: “앱에서 RBAC”은 필수고, “프록시 RBAC”은 사고를 줄이는 안전벨트다.
(특히 내부 포털은 URL 하나 잘못 열리면 사고가 커진다.)
5) 프록시 뒤에 둘 때 자주 터지는 문제
- redirect URI 꼬임 (hostname/proxy 설정 미흡)
- 쿠키 Secure/SameSite 정책 충돌
- 혼합 콘텐츠(HTTP/HTTPS 섞임)
다음 단계
- 운영 백업/복구(Realm export/import, DB 백업, 키 관리)
- 업그레이드 전략(메이저 점프 주의, 사전 마이그레이션)
- 로그/모니터링(health/metrics, 알람 설계)
- 트러블슈팅 모음(무한 로딩, redirect loop, 프록시 헤더)