Programming-[Backend]/Keycloak

Keycloak - 2. 프로젝트, 클라이언트, 인증 프로토콜

컴퓨터 탐험가 찰리 2024. 7. 27. 17:43
728x90
반응형

KeyCIoak - 모던 애플리케이션을 위한 ID 및 접근관리 | 에이콘출판(주) | 스티안 토르거센, 페드로 이고르 실바 지음, 최만균 옮김

서적을 참고하여 요약한 시리즈 글이다.

 


 

1. 프로젝트 실행 및 구조 이해

 

1.1 프로젝트 다운로드 및 실행

프론트엔드, 백엔드용의 애플리케이션을 샘플로 사용하기 위해 교재에서 제공하는 node 프로젝트를 다운로드 받는다.

 

1. node 및 yarn을 설치한다.

brew install node
node -v
brew install yarn --ignore-dependencies (이미 설치된 node는 무시하기 위함)

 

 

2. git code를 clone한다.

git clone https://github.com/PacktPublishing/Keycloak-Identity-and-Access-Management-for-Modern-Applications.git

 

이후 각 챕터에 맞게 frontend와 backend 디렉토리에 있는 Dockerfile을 실행하면 된다. 백엔드는 3000, 프론트엔드는 8000번 포트를 사용한다.

 

 

1.2 프로젝트 동작 방식 이해

 

KeyCloak이 OpenID Connect 또는 OAuth2.0 처럼 작동한다. 마치 KeyCloak이 Google 로그인을 위한 Google처럼 작동한다고 생각하면 된다.

 

그리고 각 애플리케이션은 KeyCloak에 3가지 종류의 토큰을 요청하고, 토큰을 이용하여 사용자의 정보들을 확인한다.

  • ID Token: 인증된 사용자와 관련된 애플리케이션 정보 제공
  • Access Token: 애플리케이션이 요청을 하는 경우 이 토큰을 포함
  • Refresh Token: Access Token을 갱신

 

토큰은 JWS(JSON Web Signature)를 사용한다. 토큰 내용이 보이는 non-opaque 방식이며 따라서 토큰의 내용들을 직접 확인할 수 있다. 백엔드에서 토큰의 내용을 조회할 수 있으므로 keycloak과의 통신 요청을 줄이고 지연을 줄인다. 그리고 토큰이 실제로 keycloak에서 발행됐는지를 검증하는 디지털 시그니처를 포함한다.

 

 

 

2. 클라이언트 등록

 

2.1 등록하기

이전에 만든 myRealm으로 admin으로 접속한다. 이후 Clients > Create Client에 접근하여 아래 내용들을 입력한다.

 

 

  • Valid Redirect URIs: 검증된 클라이언트 URI를 등록한다. 혹시 OpenID Connect 흐름에서 악의적인 애플리케이션이 실제 애플리케이션으로 속이는 행위를 방지하기 위해서 이 URI 목록에 애플리케이션을 등록해야한다.
  • Web Origins: CORS(Cross-Origin Resource Sharing) 요청에 대한 유효한 웹 출처를 등록한다. 여기 등록된 애플리케이션에 한해서 KeyCloak에게 AJAX 요청 후 토큰을 받아갈 수 있다.

 

 

2.2 토큰 확인

토큰 확인을 위해서 로그인을 해야한다. 앞서의 내용들을 잘 지켜야하지만, 책에서의 내용도 조금 달라진 부분들이 있어서 메모해둔다.

 

1. git clone한 코드를 바탕으로 backend, frontend 코드를 실행하되, frontend/app.js의 KC_URL 부분을 수정해줘야한다. 기본 URL에 /auth가 붙은 형태였는데, 버전업이 되면서 /auth 부분이 빠진 것 같다.

//var KC_URL = process.env.KC_URL || "http://localhost:8080/auth";

// /auth 제거
var KC_URL = process.env.KC_URL || "http://localhost:8080";

 

2. 정확히 realm과 client 이름을 입력해야한다. 코드상 책에 나온 이름대로 realm 및 client가 생성되어있기 때문이다. myrealm을 생성하고, myrealm에서 myclient를 생성해야하며, 위 내용대로 Root URL, Valid Redirect URLs, Web Origins 값을 확인한다.

 

3. 로그인 버튼을 누르고 아까 생성해둔 user로 로그인하면 아래 화면이 뜬다. 여기서 Show ID Token 버튼을 누르면 된다.

 

  • exp: 토큰 만료 시간(epoch time)
  • iss: 토큰 발급 주체. Keycloak realm의 URL이 표시된다
  • sub: 인증된 사용자의 고유 ID값. UUID라서 사용자 키값으로 사용할 수 있다.
  • preferred_username: 인증된 사용자의 사용자 이름. 변경될 수 있기 때문에 사용자의 키 값으로 사용하면 안된다.

 

Access Token의 내용은 다음과 같다.

  • allowed-origins: 애플리케이션에서 CORS를 위해 허용된 웹 출처 리스트
  • realm_access: 글로벌 역할 리스트
  • resource_access: 클라이언트 역할 리스트
  • scope: 토큰에 포함할 필드를 결정하고, 백엔드에서 토큰이 접근할 수 있는 API를 결정함

 

 

3. 인증 프로토콜

 

인증 프로토콜에 대해서 간략하게만 살펴본다. 중요한 내용들은 뒷 부분의 각 장에서 하나씩 다룰 것이다.

 

3.1 OAuth 2.0

 

3.1.1 역할 및 기본 플로우

인증용이 아닌 인가용으로 사용되는 프로토콜이다. 4가지 역할이 있다.

  • Resource Owner: 애플리케이션이 접근하고자 하는 리소소를 소유한 최종 사용자
  • Resource Server: 보호된 자원을 소유한 서비스
  • Client: 리소스에 접근하는 애플리케이션
  • Authorization server: 클라이언트에게 접근 권한을 발급하는 서버, Keycloak이 수행

 

가장 기본적인 OAuth 2.0의 인가 코드흐름은 다음 다이어그램으로 설명된다.

 

보통 구글 로그인 등을 생각해보면 어렵지 않다. 애플리케이션은 프론트엔드처럼 KeyCloak에 로그인 등의 페이지를 요청하는 역할을 하고, 서비스는 백엔드처럼 KeyCloak에서 받아온 인가 코드를 접근 토큰(Access Token)으로 교환하는 형태라고 이해하면 된다.

 

 

3.1.2 Token 핵심 사양

OAuth 2.0에서 정의하는 기본적인 사양에 대해 알아본다.

 

  1. Bearer Tokens(RFC 6750): HTTP 인가 헤더를 통해 리소스 서버로 전송된다. 인코딩된 페이로드 또는 쿼리 파라미터로 전달된다. 다만 쿼리 파라미터 방식은 보안 취약점이기 때문에 사용하면 안된다.
  2. Token Introspection(RFC 7662): 토큰의 내용을 애플리케이션에 노출하지 않는다. 토큰의 정보를 얻어야한다면, token introspection endpoint로 요청을 보내 확인할 수 있다.
  3. Token Revocation(REF 7009): 발급하는 방법은 있지만 취소하지는 않는다. 다만 만료시킬 수 있는 엔드포인트를 제공한다.'

 

 

3.2 OpenID Connect

 

3.2.1 역할 및 기본 플로우

OpenID Connect는 인증을 수행하기 위해 OAuth 2.0과 함께 사용된다. 여기에도 3가지 롤이 정의돼 있다.

 

  • End User: OAuth 2.0의 리소스 오너에 해당되며 사용자를 인증한다.
  • Relying Party: 최종 사용자를 인증하고자 하는 애플리케이션. 사용자의 ID를 인증하는 OpenID Connect Provider를 신뢰하기 때문에 신뢰자(Relying Party, PR)라고 부른다.
  • OpenID Provider: 사용자를 인증하는 ID 제공자. Keycloak이 해당 역할을 수행

 

기본 인가 흐름은 다음과 같다.

 

서비스가 없다는 점을 빼고는 OAuth 2.0의 인가 코드와 거의 유사하다.

 

3.2.2 추가 명세

알아둘 추가 명세이다. 한 번 읽어보고 넘어간다.

 

  • Discovery: 클라이언트가 OpenID 제공자에 대한 정보를 동적으로 검색한다.
  • Dynamic Registration: 클라이언트가 OpenID 제공자에 동적으로 자신을 등록한다.
  • Session Management: 클라이언트가 OpenID 제공자와 최종 사용자의 인증 세션을 모니터링하는 방법과 로그아웃하는 방법을 정의한다.
  • Front-Channel Logout: 임베디드 iframe을 사용하여 여러 애플리케이션의 싱글 사인 아웃 메커니즘을 정의한다.
  • Back-Channel Logout: back-channel 요청 메커니즘을 사용하여 여러 애플리케이션에 대한 단일 로그아웃 메커니즘을 정의한다.

 

3.2.3 JWT 활용

OpenID Connect는 JWT를 활용한다. 여러 프로그래밍 언어에서 쉽게 활용할 수 있는 JSON 형식이며, 리소스 서버가 토큰을 직접 읽을 수 있는 형태이므로 토큰의 정보 확인을 위해 따로 제공되는 엔드포인트에 항상 요청을 전송할 필요가 없기 때문에 성능에 유리하기 때문이다. 주의할 점은 아래와 같다.

  • alg=none: 알고리듬을 none으로 설정할 수도 있다. 이것은 JWS가 서명되지 않았음을 의미하는데 이 때에도 JWT 라이브러리가 해당 값을 유효하다고 인식하므로 alg=none으로 처리해서는 안된다.
  • RSA to HMAC: 공용 RSA 키를 사용하지만 알고리듬을 HMAC으로 사용하는 경우. 일부 라이브러리에서 검증없이 사용될 수 있다.

 

 

- 추가: SAML 2.0

SAML 2.0은 여전히 중요하며, 많이 사용된다. keycloak은 SAML 2.0 프로토콜도 지원한다.

728x90
반응형