Spring/Spring Security

[Spring Authorization Server] 1. Configuration Model

noahkim_ 2025. 7. 20. 15:52

1. Introducing Spring Authorization Server

  • Spring Authorization Server는 OAuth2.1과 OpenID Connection 1.0 명세의 구현을 제공하는 프레임워크입니다.

 

2. Use Cases

항목 설명
구성 및 커스터마이징 제어
고급 설정이 필요한 경우, 전체 인증 흐름 및 동작을 세밀하게 제어할 수 있음
경량화된 서버 구조
상용 제품 대비 불필요한 기능 없이 핵심 기능만 포함되어 있음
비용 절감
오픈소스 기반, 자체 호스팅 가능 → 상용 솔루션 대비 비용 절감 가능
개발 편의성
Spring 기반 환경에 익숙한 개발자라면 빠른 셋업 가능, Spring Security와 유사한 설정 구조 제공

 

3. Default Configuration

OAuth2

OAuth2AuthorizationServerConfiguration
  • OAuth2 Authorization Server의 최소 기본 구성 제공
  • Authorization Server는 자동 설정을 지원하지 않으므로 직접 빈으로 등록해야 함

 

코드) OAuth2AuthorizationServerConfiguration

더보기
더보기
@Configuration(proxyBeanMethods = false)
public class OAuth2AuthorizationServerConfiguration {

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
        applyDefaultSecurity(http);
        return http.build();
    }

    // @formatter:off
    public static void applyDefaultSecurity(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
                new OAuth2AuthorizationServerConfigurer();
        RequestMatcher endpointsMatcher = authorizationServerConfigurer
                .getEndpointsMatcher();

        http
            .securityMatcher(endpointsMatcher)
            .authorizeHttpRequests(authorize ->
                authorize.anyRequest().authenticated()
            )
            .csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
            .apply(authorizationServerConfigurer);
    }
    // @formatter:on

    public static JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
        Set<JWSAlgorithm> jwsAlgs = new HashSet<>();
        jwsAlgs.addAll(JWSAlgorithm.Family.RSA);
        jwsAlgs.addAll(JWSAlgorithm.Family.EC);
        jwsAlgs.addAll(JWSAlgorithm.Family.HMAC_SHA);
        ConfigurableJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
        JWSKeySelector<SecurityContext> jwsKeySelector = new JWSVerificationKeySelector<>(jwsAlgs, jwkSource);
        jwtProcessor.setJWSKeySelector(jwsKeySelector);
        // Override the default Nimbus claims set verifier as NimbusJwtDecoder handles it
        // instead
        jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {
        });
        return new NimbusJwtDecoder(jwtProcessor);
    }

    @Bean
    RegisterMissingBeanPostProcessor registerMissingBeanPostProcessor() {
        RegisterMissingBeanPostProcessor postProcessor = new RegisterMissingBeanPostProcessor();
        postProcessor.addBeanDefinition(AuthorizationServerSettings.class,
                () -> AuthorizationServerSettings.builder().build());
        return postProcessor;
    }
}
  • jwtDecoder(): JWT 토큰을 검증하기 위한 디코더 설정 (Nimbus 라이브러리 사용)
  • RegisterMissingBeanPostProcessor: AuthorizationServerSettings 빈이 없을 경우 자동으로 빈 등록해줌

 

 

설정) OAuth2AuthorizationServerConfiguration

더보기
더보기
@Configuration
@Import(OAuth2AuthorizationServerConfiguration.class)
public class SecurityConfig {

 

OIDC

  • OIDC는 OAuth2 위에 확장된 스펙임
  • 모든 서비스가 OIDC 기능을 요구하지 않으므로, 기본 비활성화 상태임 (불필요한 엔드포인트 오픈 방지)
  • RegisteredClient, JWKSource, JwtDecoder 등록 필수

 

설정) oidc 활성화

더보기
더보기
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    var configurer = OAuth2AuthorizationServerConfigurer.authorizationServer();
    http.securityMatcher(configurer.getEndpointsMatcher())
        .with(configurer, (authz) -> authz.oidc(Customizer.withDefaults()));
    return http.build();
}

 

Endpoint

OAuth2
Endpoint 기본 경로 설명
Authorization Endpoint /oauth2/authorize 사용자 권한 요청
Device Authorization Endpoint /oauth2/device_authorization 장치 코드 플로우용
Device Verification Endpoint /oauth2/device_verification 장치 사용자 인증용
Token Endpoint /oauth2/token 토큰 발급/갱신
Token Introspection Endpoint /oauth2/introspect 토큰 유효성 검증
Token Revocation Endpoint /oauth2/revoke 토큰 폐기
Authorization Server Metadata Endpoint /.well-known/oauth-authorization-server 서버 메타데이터
JWK Set Endpoint /oauth2/jwks
공개 키 제공
(JWKSource<SecurityContext> 필수)

 

OIDC
Endpoint 기본 경로 비고
Provider Configuration /.well-known/openid-configuration OIDC Discovery
Logout Endpoint /connect/logout RP-initiated 로그아웃
UserInfo Endpoint /userinfo 사용자 정보 제공
Client Registration Endpoint (비활성화 기본) 필요 시 수동 활성화 필요

 

4. Customizing the configuration

OAuth2AuthorizationServerconfigurer

  • OAuth2 인가 서버의 보안 구성을 완전히 커스터마이징할 수 있게 해주는 컴포넌트
  • OAuth2 인증 플로우를 직접 제어하게 해줌
  • 각 endpoint의 세부 설정을 조정할 수 있음 (인증 방식, 토큰 정책, 사용자 동의 처리 등)
  • issure, endpoint prefix 설정 필수

 

설정) SecurityFilterChain

더보기
더보기
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
            OAuth2AuthorizationServerConfigurer.authorizationServer();

    http
        .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
        .with(authorizationServerConfigurer, (authorizationServer) ->
            authorizationServer
                .registeredClientRepository(registeredClientRepository)	
                .authorizationService(authorizationService)	
                .authorizationConsentService(authorizationConsentService)	
                .authorizationServerSettings(authorizationServerSettings)	
                .tokenGenerator(tokenGenerator)	
                .clientAuthentication(clientAuthentication -> { })	
                .authorizationEndpoint(authorizationEndpoint -> { })	
                .pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint -> { })
                .deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { })	
                .deviceVerificationEndpoint(deviceVerificationEndpoint -> { })	
                .tokenEndpoint(tokenEndpoint -> { })	
                .tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { })	
                .tokenRevocationEndpoint(tokenRevocationEndpoint -> { })	
                .authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { })	
                .oidc(oidc -> oidc
                    .providerConfigurationEndpoint(providerConfigurationEndpoint -> { })	
                    .logoutEndpoint(logoutEndpoint -> { })	
                    .userInfoEndpoint(userInfoEndpoint -> { })	
                    .clientRegistrationEndpoint(clientRegistrationEndpoint -> { })	
                )
        );

    return http.build();
}

 

메서드 설명
registeredClientRepository()
등록된 클라이언트 정보 저장소 (반드시 필요)
authorizationService()
인가 코드, 토큰 정보 등을 저장하는 서비스
authorizationConsentService() 유저의 권한 동의 정보 저장용
authorizationServerSettings()
issuer URI, endpoint 경로 커스터마이징
tokenGenerator()
access token, refresh token, id token 생성기 지정
clientAuthentication() 클라이언트 인증 로직 커스터마이징
authorizationEndpoint() /oauth2/authorize 설정
pushedAuthorizationRequestEndpoint() PAR 지원 시 설정
deviceAuthorizationEndpoint()
디바이스 흐름 인증 시작 엔드포인트
deviceVerificationEndpoint() 디바이스 인증 확인 엔드포인트
tokenEndpoint() 토큰 발급 /oauth2/token 설정
tokenIntrospectionEndpoint()
토큰 유효성 검사 /oauth2/introspect
tokenRevocationEndpoint() 토큰 폐기 /oauth2/revoke 설정
authorizationServerMetadataEndpoint()
서버 메타데이터 (/.well-known/oauth-authorization-server)
oidc(...)
OpenID Connect 확장 기능들 설정
┗ providerConfigurationEndpoint()
OIDC 제공자 메타 정보 (/.well-known/openid-configuration)
┗ logoutEndpoint()
OIDC 로그아웃 처리 엔드포인트 설정
┗ userInfoEndpoint() 사용자 정보 조회 엔드포인트 설정
┗ clientRegistrationEndpoint() 동적 클라이언트 등록 설정

 

5. Configuring Authorization Server Settings

AuthorizationServerSettings

  • OAuth2 인가 서버의 설정을 담당하는 클래스
  • 프로토콜 엔드포인트 URI와 issuer 식별자 지정에 사용됨
  • OAuth2AuthorizationServerConfiguration를 import하면 자동으로 등록됨

 

표) 프로토콜 엔드포인트

더보기
더보기
기능 기본 URI
Authorization 요청 /oauth2/authorize
Pushed Authorization Request (PAR) /oauth2/par
Device Authorization /oauth2/device_authorization
Device Verification /oauth2/device_verification
Access Token 발급 /oauth2/token
Token Introspection /oauth2/introspect
Token Revocation /oauth2/revoke
JWK Set (공개키) 제공 /oauth2/jwks
OIDC Logout /connect/logout
OIDC UserInfo /userinfo
OIDC Client Registration /connect/register

 

커스터마이징) 프로토콜 엔드포인트

더보기
더보기
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
    return AuthorizationServerSettings.builder()
        .issuer("https://example.com")  // issuer 식별자
        .authorizationEndpoint("/oauth2/v1/authorize")
        .pushedAuthorizationRequestEndpoint("/oauth2/v1/par")
        .deviceAuthorizationEndpoint("/oauth2/v1/device_authorization")
        .deviceVerificationEndpoint("/oauth2/v1/device_verification")
        .tokenEndpoint("/oauth2/v1/token")
        .tokenIntrospectionEndpoint("/oauth2/v1/introspect")
        .tokenRevocationEndpoint("/oauth2/v1/revoke")
        .jwkSetEndpoint("/oauth2/v1/jwks")
        .oidcLogoutEndpoint("/connect/v1/logout")
        .oidcUserInfoEndpoint("/connect/v1/userinfo")
        .oidcClientRegistrationEndpoint("/connect/v1/register")
        .build();
}

 

AuthorizationServerContext

  • 인가 서버의 런타임 환경 정보를 담는 객체
    • 현재 요청에 연관된 AuthorizationServerSettings 정보에 접근 가능
    • 현재의 issuer 획득 가능
  • AuthorizationServerContextHolder를 통해 접근함 
  • 내부적으로는 ThreadLocal에 저장됨

 

6. Configuring Client Authentication

OAuth2ClientAuthenticationFilter

  • 클라이언트 인증을 담당하는 필터

 

OAuth2ClientAuthenticationConfigurer

  • OAuth2 클라이언트 인증을 커스터마이징할 수 있게 해주는 설정 컴포넌트 (전처리/처리/후처리)
  • OAuth2ClientAuthenticationFilter에 적용됨

 

기본 동작
구성 요소 설명
AuthenticationConverter
다양한 변환기를 위임하여 사용하는 DelegatingAuthenticationConverter
(예: JWT, X.509, Basic, POST 등)
AuthenticationManager
위 변환된 인증 토큰들을 실제 인증하는 Provider 모음
AuthenticationSuccessHandler
인증 성공 시 SecurityContext에 저장
AuthenticationFailureHandler
인증 실패 시 적절한 OAuth2 오류 응답 반환

 

설정) SecurityFilterChain

더보기
더보기
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
        OAuth2AuthorizationServerConfigurer.authorizationServer();

    http
        .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
        .with(authorizationServerConfigurer, (authorizationServer) ->
            authorizationServer
                .clientAuthentication(clientAuthentication ->
                    clientAuthentication
                        .authenticationConverter(...)           // 전처리
                        .authenticationConverters(...)          // 전처리 목록 제어
                        .authenticationProvider(...)            // 인증 처리
                        .authenticationProviders(...)           // 인증 처리 목록 제어
                        .authenticationSuccessHandler(...)      // 성공 후처리
                        .errorResponseHandler(...)              // 실패 후처리
                )
        );

    return http.build();
}
메서드 설명
authenticationConverter()
전처리
HttpServletRequest에서 OAuth2ClientAuthenticationToken으로 변환하는 역할
authenticationConverters()
AuthenticationConverter 리스트를 수정할 수 있도록 Consumer 제공.
기본 전환기들을 제거하거나 추가 가능.
authenticationProvider()
클라이언트 인증을 수행하는 AuthenticationProvider를 하나 추가.
(예: 비밀번호 검사, JWT 검사 등).
authenticationProviders()
AuthenticationProvider 리스트를 수정할 수 있는 Consumer 제공.
authenticationSuccessHandler()
인증 성공 시 후처리 로직 정의.
예: SecurityContext에 인증된 토큰 저장.
errorResponseHandler()
인증 실패 시 오류 응답 처리.
OAuth2Error를 기반으로 응답 생성.

 

Customizing Jwt Client Assertion Validation

Customizing Mutual-TLS Client Authentication

 

출처