Keycloak 토큰 교환으로 인증 시스템 구축

Keycloak 토큰 교환으로 인증 시스템 구축

1. 토큰 교환(Token Exchange)의 기본 개념

마이크로서비스 아키텍처(MSA) 환경에서 여러 서비스 간에 권한을 위임하거나 토큰을 재발급해야 할 때, Keycloak이 제공하는 토큰 교환(Token Exchange) 기능은 매우 유용한 솔루션입니다. 이는 인증된 클라이언트가 기존의 토큰을 제출하면, Keycloak이 이를 검증한 후 목적지에 맞는 새로운 권한과 대상을 가진 토큰으로 맞교환해 주는 기술입니다. 서비스 간의 신뢰 관계를 명시적으로 정의하고 권한 범위를 제어할 수 있어 엔터프라이즈 보안의 핵심 기반이 됩니다.

2. 연동 요구사항과 Impersonation 채택

최근 프로젝트 진행 중, 이미 타사 플랫폼에서 인증을 마친 사용자가 당사 서비스로 진입할 때 로그인 창이나 별도의 추가 로그인 처리 없이 접근할 수 있도록 해달라는 요구사항이 있었습니다. 사용자가 로그인을 두 번 하지 않도록 심리스한 UX를 구현해야 하는 과제였습니다.

정석적인 Keycloak V2 표준 엔진을 적용하려 하였으나 기술적 제약에 부딪혔습니다. 표준 사양은 외부 서비스의 실제 로그인 증명서(원본 토큰)를 필수로 요구하지만, 파트너사는 보안 정책상 자사 토큰을 공유할 수 없었고 오직 '유저 고유 ID(식별자)'만 넘겨줄 수 있는 상황이었습니다.

실제 토큰 없이 식별 정보만으로 추가 로그인 없이 통과시켜야 했기에 표준 엔진 도입은 불가능하였습니다. 이에 따라 추가적인 커스텀 모듈 개발 없이 요구사항을 충족하고자, 백엔드 자격 증명과 유저 ID 문자열만으로 토큰을 발급할 수 있는 구형 규격(V1 Direct Naked Impersonation)의 대행 메커니즘을 선택하게 되었습니다. 내부 인프라 보호를 위해 전면에 '보안 프록시(Bridge Gateway)'를 두고 백채널로 토큰을 발급받아 화면에 전달하는 구조를 확립하였습니다.

3. 키클락 설정: 클라이언트 연결하기

안전한 토큰 대행 발급을 위해 Keycloak 콘솔에서 요청자(Requester)와 수신자(Target) 클라이언트 간의 명시적인 신뢰 관계를 정의해야 합니다.

  • 외부 서비스용 클라이언트 (Requester): Client Authentication을 On (Confidential)으로 설정하여 마스터 시크릿 키를 내부에 은닉합니다. 구형 V1 메커니즘을 적용하기 위해 서버 레이어에서 구형 세부 관리 권한(FGAP:v1) 사양을 활성화합니다.

  • 내부 MSA용 클라이언트 (Target): 인가 및 화면을 담당하는 클라이언트의 Permissions 메뉴에서 token-exchange를 활성화합니다. 정책(Policy)을 생성하여 오직 외부 프록시 클라이언트만 토큰을 대행하여 교환할 수 있도록 매핑합니다.

4. 백엔드 구현: 토큰 요청 규격

프록시 서버(Spring Boot)는 외부 시스템의 요청을 검증한 후, 안전하게 Keycloak 엔드포인트를 호출하는 브릿지 코드를 수행합니다. 구형 V1 규격에 따른 API 페이로드 명세는 다음과 같습니다.

  • 엔드포인트 URL: POST /realms/{realm-name}/protocol/openid-connect/token

  • 헤더 스펙: Content-Type: application/x-www-form-urlencoded, Authorization: Basic [Base64(ID:Secret)]

토큰 발급 필수 파라미터 명세

파라미터 명

설정 값 및 예시

설명

grant_type

urn:ietf:params:oauth:grant-type:token-exchange

프로토콜 규격 명시

requested_subject

user_internal_idx_01

대행 발급받을 내부 유저 고유 ID

requested_token_type

urn:ietf:params:oauth:token-type:access_token

액세스 토큰 요구 명시

audience

internal-msa-core

불필요한 권한을 깎아내는 다운스코핑 유발

Keycloak 검증이 성공하면 응답 데이터에서 access_token을 추출합니다. 이 토큰에는 사용자의 비즈니스 내부 롤(ROLE_USER 등)만 주입되며, 프록시는 이를 외부 서비스를 거쳐 유저 브라우저에 탑재한 뒤 리다이렉트를 수행합니다.

5. 자주 발생하는 에러와 해결법

실전 운영 및 배포 단계에서 마주치는 3대 런타임 에러 대응 핸드북입니다.

  • HTTP 404 Not Found 에러: 구형 문서를 참고하여 엔드포인트 주소에 /auth 경로를 포함했을 때 발생합니다. 최신 버전은 기본 컨텍스트 경로에서 /auth가 제거되었으므로 이를 생략해야 합니다.

  • invalid_client 에러: 요청을 보내는 프록시 클라이언트 자체 설정에서 토큰 교환 스펙 관련 옵션이 활성화되지 않았을 때 발생하므로, 콘솔에서 해당 토글 스위치를 다시 확인해야 합니다.

  • 403 Forbidden / not_allowed 에러: 클라이언트 간 신뢰 권한 정책이 유실되었을 때 발생합니다. 최종 목적지가 되는 Target 클라이언트의 Permissions 메뉴에서 요청자 클라이언트가 정책 서브셋으로 등록되었는지 검증해야 합니다.

6. 레거시(V1) 방식의 한계와 실무적 타협점

본 프로젝트에서 최신 V2 표준 엔진 대신 구형 규격(V1 Direct Naked Impersonation)을 채택한 것은 외부 연동 환경의 제약을 극복하기 위한 의도적인 아키텍처적 선택이었습니다.

Keycloak V2 표준 엔진은 교환의 대상이 되는 원본 토큰 제출을 필수 규격으로 요구합니다. 그러나 연동 대상인 외부 파트너사는 자사 보안 정책상 유저 세션 토큰을 공유할 수 없었으며, 오직 '유저 고유 ID'만 제공할 수 있는 기술적 한계가 존재하였습니다. 원본 토큰이 없는 상황에서 프록시 서버에 별도의 암호화 토큰 생성 시스템을 추가 구축하지 않고, "추가 로그인 처리 배제"라는 고객사의 요건을 적시에 충족하기 위해서는 유저 ID만으로 토큰을 발급할 수 있는 구형 V1 규격이 유일한 실무적 대안이었습니다.

구형 규격이 가진 잠재적 리스크는 인프라 레이어의 다층 방어 체계로 상쇄하였습니다. 서버 망(M2M)과 화면 망(UI)의 권한을 엄격히 이중 격리하였고, 브라우저에 노출되는 토큰의 유효 기간을 3~5분의 단명 토큰으로 제한하여 탈취 위협을 통제하였습니다. 비록 향후 Keycloak 엔진 업데이트에 따른 표준 V2 체계로의 마이그레이션 과제가 존재하나, 한정된 자원 내에서 외부사와의 연동 규격을 건드리지 않고 비즈니스 목표를 달성하기 위한 가장 현실적인 엔지니어링적 타협점이었습니다.

7. 마치며

이번 프로젝트는 B2B 연동 시 보안성과 사용자 편의성을 동시에 확보하는 것이 얼마나 까다로운 작업인지 재확인하는 계기가 되었습니다. 외부 인프라 제약 속에서 실무적인 최선의 아키텍처를 검토하고 찾아가는 과정 자체가 큰 자산이 되었습니다. 본 연동 사례가 마이크로서비스 환경에서 Keycloak 기반의 인증 인프라를 고민하는 분들에게 조금이나마 실무적인 참고 자료가 되기를 바랍니다.

참고자료

https://www.keycloak.org/securing-apps/token-exchange

oshua

Site footer