💡 Keycloak - Red Hat에서 개발한 오픈소스 Identity and Access Management(IAM) 솔루션입니다. 현대적인 애플리케이션과 서비스를 위한 인증 및 권한 부여 기능을 제공하는 인증 서버(Authentication Server)의 기능을 수행합니다.
- Keycloack에서는 여러 플랫폼에서 중앙 집중식 인증 서버로 동작을 합니다. 주요한 기능은 서로 다른 도메인에서 실행되는 애플리케이션 간의 SSO를 지원하거나 REST API 기반에 접근제어 토큰에 대한 인증 제공 및 세션 타임아웃, 동시 로그인 제한과 같은 다양한 세션 기능을 담당합니다.
- OAuth 2.0 프로토콜을 확장하여 만든 사용자 인증을 위한 표준화된 인증(Authentication) 프로토콜입니다. - 기존 OAuth 2.0은 인가(Authorization)에 중점을 두고 있어 사용자 인증에 대한 표준이 부족했습니다. 이러한 한계를 해결하기 위해 OIDC에서는 OAuth 2.0 위에 '표준화된 인증 계층'을 추가한 프로토콜입니다.
1. OIDC 인증 흐름(OpenID Connect Authentication flow)
💡 OIDC 인증 흐름(OpenID Connect Authentication flow)
- OIDC(OpenID Connect) 인증 프로토콜을 이용하여 구현하는 구체적인 인증 방법들을 의미합니다. 즉, 애플리케이션(Client)을 기준으로 OIDC 프로토콜을 통해서 Keycloak과 통신하고 인증하는 방법들을 의미합니다.
-이러한 OIDC 인증 흐름은 한 가지 방법으로 인증 과정을 수행할 수 있고, 여러 가지 다양한 방법으로 인증과정을 구현할 수 있습니다.
2. 인증 흐름(Authentication flow) 종류
인증 흐름 종류
설명
사용처
Standard Flow
- OAuth 2.0의 Authorization Code Flow 기반으로 인증을 수행하며, 사용자는 Keycloak 로그인 페이지로 리다이렉트 되어서 인증을 수행하는 인증방식을 의미합니다.
웹 애플리케이션
Direct Access Grants
- 직접 REST API를 통해 자격 증명(아이디/비밀번호)을 담아서 통신하며 별도의 리다이렉션 없이 즉시 토큰을 받을 수 있는 인증방식을 의미합니다.
신뢰할 수 있는 애플리케이션(모바일 애플리케이션, 백엔드 시스템에서 직접 인증이 필요한 경우)
Implicit Flow
- 간소화된 인증흐름으로 인가 코드(Auth Code) 없이 직접 액세스 토큰을 받아서 인증을 수행하는 방식을 의미합니다.
모바일 앱, 단일 페이지 애플리케이션(SPA)
Service Accounts Roles
- 애플리케이션 시스템 간에 인증 기반의 통신을 위한 방법으로, 클라이언트 자체적으로 API를 호출하여 다른 서비스와의 통신을 할 때 사용하는 인증방식입니다.
마이크로서비스 간 통신(서버-서버간 통신), 자동화된 프로세스
OAuth 2.0 Device Authorization Grant
- 스마트 TV나 IoT 기기와 같이 제한된 입력 기능을 가진 디바이스를 위한 인증 방식입니다.
스마트 TV 애플리케이션, IoT 디바이스, 게임 콘솔, 프린터 및 스캐너
OIDC CIBA Grant
- 클라이언트가 사용자의 직접적인 상호작용 없이 인증을 시작하는 인증 방식입니다.- 사용자가 인증을 요청한 디바이스와 실제 인증을 수행하는 디바이스가 물리적으로 분리된 방식입니다.
금융 서비스, 공유 디바이스, 스마트홈 시스템
3) 사전 구성
💡 사전 구성
- Keycloak의 구현 방식을 구현하고자 할때, 기본적으로 Keyclaok 인증 서버와 Realm, Client, User에 대한 구성을 진행합니다.
1. Keycloak 인증 서버 구축
💡 Keycloak 인증 서버 구축
- Spring Boot App 내에서 접근이 가능한 Keycloak 인증 서버 구축은 Docker를 기반으로 컨테이너로 구성하였습니다. 아래의 글을 참고하시면 이를 확인할 수 있습니다.
- REST API를 통해 직접 토큰을 요청하는 방식으로 사용자의 자격 증명(아이디/비밀번호)를 담아서 요청하며, 별도의 리다이렉션 없이 즉시 토큰을 받을 수 있는 인증 방식을 의미합니다. - 사용자의 자격 증명이 클라이언트 애플리케이션에 직접 노출되므로 신뢰할 수 있는 애플리케이션에서만 사용해야 합니다.
1. Direct Access Grants 처리방식
💡 Direct Access Grants 처리방식
1. 사용자 자격증명 수집
- 클라이언트 애플리케이션은 사용자로부터 아이디와 비밀번호를 직접 수집합니다. - 일반적으로 애플리케이션의 로그인 폼(application/x-www-form-urlencoded Content-Type)을 통해 입력받습니다
2. 토큰 요청
- 클라이언트는 수집한 자격증명을 Keycloak 토큰 엔드포인트로 직접 전송합니다. - 예를 들어, 로컬 9001 포트에 구성한 Keycloak의 Realm에 [POST] http://localhost:9001/realms/dev-realm/protocol/openid-connect/token 엔드포인트로 요청합니다. - 요청 로그인 폼으로는 grant_type, client_id, client_secret, username, password을 포함시켜서 전송합니다. - [참고] 해당 URL을 참고하시면 해당 API 엔드포인트 정보를 확인할 수 있습니다. https://www.keycloak.org/securing-apps/oidc-layers
3. 자격증명 검증 - Keycloak 서버는 전달받은 사용자 자격증명의 유효성을 검증합니다 - 클라이언트 인증정보(client_id, client_secret)도 함께 확인합니다
4. 토큰 발급 - 검증이 성공하면 Keycloak은 즉시 액세스 토큰을 발급합니다 - 응답으로 access_token, refresh_token, token_type 등이 포함된 JSON을 반환합니다
5. 토큰 사용 - 클라이언트는 발급받은 액세스 토큰을 사용하여 보호된 리소스에 접근할 수 있습니다 - Authorization 헤더에 Bearer 토큰을 포함시켜 API 요청을 수행합니다
- http://localhost:9001/realms/dev-realm/protocol/openid-connect/token 와 같은 특정 Realm로 토큰을 요청합니다. - 파라미터로 grant_type, client_id, client_secret, username, password 값을 실제 전송하여서 토큰을 받아오는 방식입니다.
5) Direct Access Grants 기반 Spring Boot 처리 과정 : 접근 토큰(Access Token) 즉시 발급
💡 Direct Access Grants 기반 Spring Boot 처리 과정 : 접근 토큰(Access Token) 즉시 발급
- Direct Access Grants 방식에서는 자격증명(아이디/비밀번호)를 전송 값에 포함하여서 전송합니다. 이를 통해서 즉시, 접근 토큰을 즉시 발급하는 과정을 알아봅니다.
1. DirectAccessTokenDto
💡 DirectAccessTokenDto
- Authentication Flow 방식 중 Direct Access Grants 방식을 통해서 직접 전달할 데이터를 구성한 DTO입니다.
- Spring Boot Cloud OpenFeign 방식을 통해서 Keycloak 서버가 통신을 하여서 값을 반환해 옵니다. - http://localhost:9001/realms/dev-realm//protocol/openid-connect/token 엔드포인트로 “application/x-www-form-urlencoded" 데이터 형태로 전달합니다.
package com.blog.springbootkeycloak.service;
import com.blog.springbootkeycloak.dto.TokenRequestDto;
import com.blog.springbootkeycloak.dto.StandardFlowDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
/**
* Keycloak 서버와 통신하여서 데이터를 수신합니다.
*
* @author : jonghoon
* @fileName : AuthFlowService
* @since : 25. 1. 28.
*/@FeignClient(
name = "keycloak-auth-service",
url = "<http://localhost:9001/realms/dev-realm>"
)publicinterfaceAuthFlowService{
/**
* Direct Access Flow : 토큰을 즉시 요청하는 방법
*
* @param tokenRequestDto 전송 객체 값 (form 데이터 형태로 전송)
* @return 토큰 값 반환
*/@PostMapping(
value = "/protocol/openid-connect/token",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE
)Object getAccessToken(@ModelAttribute TokenRequestDto tokenRequestDto);
}
4. 결과 확인
💡 결과 확인
- 구성한 엔드포인트로 값을 구성하여서 호출하여 access_token 값을 반환받음을 확인하였습니다.
6) [참고] Implicit Flow 기반 SPA React App 처리 과정 : 접근 토큰 발급
💡 [참고] Implicit Flow 기반 SPA React App 처리 과정 : 접근 토큰 발급
- OAuth 2.0의 인증 방식 중 하나로, 클라이언트 사이드 애플리케이션에서 사용되는 단순화된 인증 흐름입니다. - Standard flow 방식과 다르게 인가 코드 없이 바로 액세스 토큰을 받는 방식입니다. - OAuth 2.0 최신 권장사항에서는 Implicit Flow 대신 PKCE를 사용한 Authorization Code Flow를 권장합니다.
[ 더 알아보기 ] 💡 Spring Boot 환경에서는 Implicit Flow 구현이 어려운 이유는 뭘까? - Implicit Flow는 액세스 토큰이 URL 프래그먼트(파라미터)로 전달되기 때문에, 서버 사이드에서 이를 직접 처리하기 어렵습니다. - Spring Boot와 같은 서버 사이드 애플리케이션의 경우 Authorization Code Flow나 Direct Access Grants가 더 적합합니다.
1. Implicit Flow 처리 과정
💡 Implicit Flow 처리 과정
1. 사용자 로그인 시도 - 사용자가 로그인을 시도할 때, Keycloak의 로그인 페이지로 리다이렉트 되어 자격증명(아이디/패스워드)을 입력 요청을 합니다.
2. 로그인 성공 - 사용자가 로그인을 성공하면, 바로 액세스 토큰을 리다이렉트 URL로 전달이 됩니다.