오늘은 Keycloak이라는 오픈소스 IAM(Identity and Access Management) 솔루션을 이용해 SSO(Single Sign-On)를 구현하는 방법을 간단한 예제와 함께 알아보겠습니다.
Keycloak을 통해 “한 번만 로그인하면, 연결된 다른 서비스에도 자동 로그인이 된다”라는 SSO 환경을 쉽고 빠르게 구축할 수 있습니다.
1. Keycloak SSO란? 🤔
Keycloak을 활용한 SSO를 간단히 설명하자면, Keycloak이 인증 서버(Identity Provider) 역할을 맡아서 모든 애플리케이션의 로그인을 중앙에서 처리하는 방식입니다.
- 개념 요약
사용자는 한 번만 Keycloak에 로그인하면, 같은 Realm(인증 도메인) 안에 속한 다른 애플리케이션들도 별도의 로그인 과정 없이 이용할 수 있습니다. - 실생활 예시
회사에서 메일, 사내 게시판, 메신저 등 여러 서비스가 각각 로그인 화면이 있다면 매우 불편하겠죠? Keycloak을 쓰면 한 번의 로그인으로 모든 서비스에 동시에 로그인되어 편리합니다. - 어떤 문제를 해결하는지?
1) 여러 개의 서비스를 쓰는 사용자에게 단일 로그인 경험 제공
2) 계정 정책, 보안 정책을 한 곳에서 관리 가능
3) 탈퇴, 비밀번호 변경, MFA 등 통합 적용으로 관리 편의성 및 보안 강화
2. 어떻게 동작하나요? 🎬
Keycloak은 OIDC(OpenID Connect), OAuth2, SAML 등 표준 프로토콜을 지원합니다. 보통은 OIDC 또는 OAuth2 방식을 주로 사용합니다.
SSO 과정은 대략 다음과 같은 순서를 따릅니다:
- 사용자가 애플리케이션(웹/모바일 등)에 접근
- 애플리케이션은 “인증이 필요하다”고 판단하면 Keycloak으로 이동시켜 로그인 요청
- 사용자가 Keycloak 로그인 화면에서 아이디/비밀번호(또는 MFA) 등을 입력해 인증
- Keycloak이 성공적으로 인증되었다는 표시(토큰)를 애플리케이션에 전달
- 애플리케이션은 해당 토큰을 이용해 사용자 정보를 확인하고, 이후 자동 로그인 상태 유지
한 번 로그인에 성공하면 같은 Keycloak Realm에 소속된 다른 애플리케이션도 별도 로그인 없이 접속 가능해집니다.
3. Keycloak 환경 구성하기 🌟
Keycloak을 설치하고 실행하는 가장 쉬운 방법은 Docker를 이용하는 것입니다.
1) Keycloak 컨테이너 실행
docker run -p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest start-dev
- KEYCLOAK_ADMIN, KEYCLOAK_ADMIN_PASSWORD: Keycloak 관리자 계정(초기 관리자)
- start-dev: 개발 모드(테스트 용), 실무 환경에서는 별도 DB 연결 등 설정 필요
이제 브라우저에서 http://localhost:8080 에 접속하면 Keycloak Admin 콘솔을 볼 수 있습니다.
2) Keycloak 관리자 콘솔 접속 및 Realm 생성
- http://localhost:8080 → “Administration Console” 클릭
admin
/admin
(방금 설정한 관리자 계정)으로 로그인- 왼쪽 상단에서 Master Realm 대신 Create Realm 클릭
- Realm 이름 지정 (예: myrealm) → Create
이렇게 하면 myrealm이라는 인증 도메인이 만들어집니다.
4. Keycloak에 클라이언트 애플리케이션 등록 ⚙️
클라이언트(Client)는 Keycloak에 의존해 인증을 받는 애플리케이션을 의미합니다. 보통은 “SSO를 적용하고 싶은 애플리케이션”을 클라이언트로 등록합니다.
- Realm 선택: “myrealm” 선택
- Clients → “Create client”
- Client Type: “OpenID Connect”
- Client ID: 예)
myapp
- “Client Protocol”:
openid-connect
- “Root URL” 또는 “Valid Redirect URIs”에 클라이언트 애플리케이션의 URL을 입력
- 예:
http://localhost:8081/*
- 예:
여기서 설정한 client_id
, client_secret
(Credentials 탭에서 확인 가능)은 나중에 애플리케이션 측 설정에 필요합니다.
5. Spring Boot 애플리케이션과 연동하기 🎯
1) Spring Boot 프로젝트 설정
build.gradle
또는 pom.xml
에 Keycloak Starter를 추가합니다.
build.gradle 예시
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
// Keycloak Spring Boot Starter
implementation 'org.keycloak:keycloak-spring-boot-starter:21.1.1'
}
(버전은 실제 사용 시점에 맞춰 최신 버전을 확인하세요.)
2) application.yml 예시
server:
port: 8081
keycloak:
realm: myrealm
auth-server-url: http://localhost:8080
ssl-required: external
resource: myapp # Client ID
credentials:
secret: 12345678-XXXX-XXXX-XXXX-XXXXXXXXXXXX # client_secret
bearer-only: false # 로그인 처리
# 'public' or 'confidential' / 'bearer-only' 등 모드에 따라 설정
3) Spring Security 설정 (KeycloakWebSecurityConfigurerAdapter)
Spring Boot 3.x 이후에는 Security 설정 방식이 약간 달라졌으며, KeycloakWebSecurityConfigurerAdapter를 직접 상속하는 대신 SecurityFilterChain을 Bean으로 등록하는 방법을 사용합니다. 아래는 예시 코드입니다.
import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Bean
KeycloakAuthenticationProvider keycloakAuthenticationProvider() {
KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
// 권한 매핑
SimpleAuthorityMapper authorityMapper = new SimpleAuthorityMapper();
authorityMapper.setPrefix("ROLE_");
provider.setGrantedAuthoritiesMapper(authorityMapper);
return provider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// Keycloak SecurityFilterChain 설정
http
.authorizeHttpRequests()
.antMatchers("/public/**").permitAll() // 공개된 URL
.anyRequest().authenticated() // 나머지는 인증 필요
.and()
.oauth2Login(Customizer.withDefaults()) // 혹은 keycloakLogin 처리를 위한 설정
.logout()
.logoutSuccessUrl("/");
// 세션 정책
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Keycloak 인증 필터 적용
return http.build();
}
// Keycloak에서 토큰 교환 등을 위한 RestTemplate
@Bean
public KeycloakRestTemplate keycloakRestTemplate() {
return new KeycloakRestTemplate();
}
}
🚀 동작 원리 정리
- 사용자가 http://localhost:8081/ 로 접근**
- Spring Security가 “로그인이 필요하다”고 판단하면 Keycloak 로그인 페이지로 리디렉션
- 사용자가 Keycloak 로그인 폼에서 로그인
- 성공 시, Keycloak이 사용자의 Access Token/ID Token 등을 발급해 Spring Boot에 전달
- Spring Boot가 이 토큰을 확인 후 사용자 정보를 세션(또는 Security Context)에 저장
- 사용자는 이제 myrealm에 속한 다른 애플리케이션도 재인증 없이 접속 가능(SSO)
6. 실제 동작 예시 📱
Keycloak 서버 실행
docker run -p 8080:8080 \ -e KEYCLOAK_ADMIN=admin \ -e KEYCLOAK_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:latest start-dev
myrealm 생성 및 Client(myapp) 등록
- Realm 이름:
myrealm
- Client ID:
myapp
- Redirect URI:
http://localhost:8081/*
- Realm 이름:
Spring Boot 애플리케이션 실행
- application.yml에 Keycloak 설정(client_secret, realm, auth-server-url 등) 입력
./gradlew bootRun
(또는mvn spring-boot:run
)
테스트
- 브라우저에서
http://localhost:8081/
접속 - 자동으로
http://localhost:8080/realms/myrealm/protocol/openid-connect/auth?...
로 리디렉션 → Keycloak 로그인 페이지 노출 - Keycloak에 등록된 계정(Realm User)로 로그인
- 로그인 성공 시, 다시 내 애플리케이션으로 돌아오며 로그인된 사용자로 동작
- 이후 동일 Realm에 등록된 다른 애플리케이션도 별도 로그인 없이 이용 가능
- 브라우저에서
7. 주요 장점 및 주의할 점 ⚠️
✨ 장점
- 중앙 집중형 보안 관리: 비밀번호 정책, MFA, 계정 잠금 등의 설정이 한 곳에서 통합적으로 적용
- 사용자 경험 개선: 여러 애플리케이션을 사용할 때마다 ID/PW를 반복 입력할 필요가 없음
- 확장성: OAuth2, OIDC, SAML 등 다양한 프로토콜 지원으로 다른 서비스와 연동이 쉬움
⚠️ 주의할 점
- 고가용성(HA) 고려: Keycloak 서버가 다운되면 모든 인증이 불가능해지는 단일 장애점이 될 수 있음
- 버전 호환성: Spring Boot, Keycloak, Keycloak Adapter 버전을 신중히 맞춰야 함
- 보안 설정: HTTPS 적용, 토큰 만료 시간 관리, CORS 설정, MFA 적용 등을 꼼꼼히 진행해야 안전함
8. 마치며 🎁
Keycloak을 이용한 SSO는 “한 번 로그인으로 다양한 서비스에 접근 가능한 통합 인증 환경”을 구현하는 데 아주 효율적인 솔루션입니다. 특히 오픈소스인 만큼 커뮤니티 자료와 공식 문서가 풍부하며, 다양한 기업 환경에서 실무 적용이 가능하다는 점이 장점이죠.
만약 사내 서비스가 여러 개라면, Keycloak과 같은 중앙 집중형 인증 서버를 통해 사용자 편의성을 높이고, 보안 및 계정 관리를 효율적으로 운영해보세요!
참고 자료 및 출처
SSO를 통해 “로그인은 한 번이면 충분”한 편리한 환경을 만들어보시길 바랍니다.
'100===Dev Ops > SSO' 카테고리의 다른 글
Keycloak 인증 후 어떤 정보가 반환되나요? 😋 (0) | 2025.02.03 |
---|---|
SSO(Single Sign-On) 구축 😋 (0) | 2025.02.03 |