Spring/Spring Security

[Spring Security] 7-1. OAuth2 Client

noahkim_ 2025. 7. 13. 06:05

1. OAuth2 Client

  • 사용자를 Authorization Server로 보내 로그인 및 동의를 진행하고, 발급받은 토큰으로 보호된 자원에 접근하려는 애플리케이션
  • ✅ registration: OAuth2 client 애플리케이션 등록 정보
  • ✅ provider: 통신할 Authorization Server or OIDC Provider 등록 정보
  • ➡️ 로그인 흐름 부터 자원 접근 흐름을 제어함

 

설정) registration 등록

더보기
spring:
  security:
    oauth2:
      client:
        registration:
          my-oidc-client:
            provider: my-oidc-provider
            client-id: my-client-id
            client-secret: my-client-secret
            authorization-grant-type: authorization_code
            scope: openid,profile

 

항목 경로 설명
spring.security.oauth2.client.registration.<registration-id> OAuth2 로그인용 클라이언트 이름
<registration-id>.provider 연결할 인증 서버 설정명 (아래 provider 항목 참조)
<registration-id>.client-id 외부 인증 서버에서 발급받은 클라이언트 ID
<registration-id>.client-secret 외부 인증 서버에서 발급받은 클라이언트 비밀번호
<registration-id>.authorization-grant-type 권한 부여 방식
<registration-id>.scope 인증 요청 시 필요한 정보 범위
(OIDC의 경우 반드시 openid 포함 필수)
  • 위 설정은 ClientRegistration 객체로 변환되며, ClientRegistrationRepository에 등록됨
  • Spring Security는 로그인 요청 시, 이 저장소에서 ClientRegistration 정보를 조회함

 

설정) provider 등록

더보기
spring:
  security:
    oauth2:
      client:
        provider:
          my-oidc-provider:
            issuer-uri: https://my-oidc-provider.com

 

항목 경로 설명
spring.security.oauth2.client.provider.<provider-id> 인증 서버 설정
<provider-id>.issuer-uri OIDC 메타데이터를 조회할 인증 서버 주소
  • "/.well-known/openid-configuration" 경로로 메타데이터를 요청함
  • 메타데이터에는 인증 서버의 주요 endpoint 정보가 들어있음
  • ✅ authorization_endpoint, token_endpoint, jwks_uri, userinfo_endpoint, issuer

 

2. Grant Type

  • OAuth2 Client가 Authorization Server에게 어떤식으로 access token을 발급받을 지 정하는 방식
  • ➡️ 상황과 클라이언트 유형에 따라 서로 다른 방식으로 토큰을 요청함

 

타입

Grant Type 설명 보안 고려사항 사용 주체 사용 예시
authorization_code 사용자 인증 및 동의 후, 받은 Authorization Code를 Token Endpoint에서 Access Token으로 교환 PKCE 사용, Redirect URI 정확한 검증, Code의 일회성 및 짧은 수명 user,
OAuth2 Client
소셜 로그인
refresh_token Refresh Token으로 새로운 Access Token을 발급받을 때 안전한 저장, Rotation, 재사용 탐지, 폐기 관리 OAuth2 Client 자동 로그인 유지
client_credentials 사용자 없이 클라이언트가 client id/secret만으로 access_token을 발급받는 방식 Client Secret 보호, 최소 Scope 부여 server 백엔드 API 호출
스케줄러
배치
jwt_bearer 서명된 JWT를 통해 access_token 발급 (assertion 기반) JWT 위변조/만료 검증 필요 server
3rd party 시스템 연동
token_exchange 기존 토큰을 제출해 다른 대상용 토큰으로 발급 위임 범위 제한, 대상 Audience 확인 server
마이크로서비스 간 인증

 

3. OIDC Login

OIDC vs OAuth2.0

항목 OIDC (OpenID Connect)
OAuth 2.0
주요 목적 사용자 인증: 사용자가 누구인지 확인
인가: 클라이언트가 어떤 자원에 접근 할 수 있는지 허가
사용 위치 소셜 로그인, SSO
외부 API 접근 권한 위임 (예: Kakao, Google API)
사용 토큰 ID Token (JWT)
Access Token
사용자 정보 포함 ✅ ID Token의 Claim (sub, email 등)
❌  별도 API 호출 필요
scope 'openid' 포함 ✅ 
표준 확장 규격 여부 ✅ OAuth2 위에 인증 기능을 추가한 확장 규격 ❌ 권한 위임을 위한 인가 프레임워크
Token endpoint 응답 ID Token, Access Token
Access Token, (선택적 Refresh Token)
provider 클래스 OidcAuthorizationCodeAuthenticationProvider OAuth2LoginAuthenticationProvider
사용자 조회 서비스 OidcUserService DefaultOAuth2UserService

 

요청 흐름

단계 주체 동작 내용 관련 컴포넌트
1 User-Agent 클라이언트가 제공하는 OAuth2 로그인 페이지에 접속
원하는 Provider의 로그인 링크를 선택
DefaultLoginPageGeneratingFilter
/oauth2/authorization/{registrationId}
2 OAuth2 Client 로그인 요청 정보를 생성
Authorization Server의 Authorization Endpoint로 리다이렉트한다.
OAuth2AuthorizationRequestRedirectFilter
3 User-Agent Authorization Server의 로그인 페이지에 접속
사용자 인증 및 동의를 수행한다.
브라우저와 Authorization Server 간 직접 통신
4 Authorization Server 사용자 인증과 동의를 완료함
등록된 redirect_uri로 브라우저를 리다이렉트한다.
(Authorization Code와 state를 포함함)
/login/oauth2/code/{registrationId}
5 OAuth2 Client Callback 요청에서 Authorization Code를 수신하고, 인증 처리를 위해 AuthenticationManager에 위임한다. OAuth2LoginAuthenticationFilter
6 OAuth2 Client Authorization Code를 Token Endpoint에 전달해 Access Token을 발급받음
OIDC 로그인이라면 ID Token도 함께 발급받고 검증한다.
OAuth2LoginAuthenticationProvider
or OidcAuthorizationCodeAuthenticationProvider
7 OAuth2 Client Access Token으로 UserInfo Endpoint를 호출하거나 ID Token의 Claim을 사용해 사용자 정보를 조회하고 인증 사용자를 생성한다. OAuth2UserService
DefaultOAuth2UserService
OidcUserService
8 OAuth2 Client 인증이 완료된 OAuth2AuthenticationToken을 생성
SecurityContext에 저장
로그인 성공 처리를 수행
OAuth2LoginAuthenticationFilter
AuthenticationSuccessHandler

 

 

구현체) AuthenticationProvider

더보기
클래스명 주요 역할 처리 결과
OAuth2LoginAuthenticationProvider OAuth2 Login 전체 인증 처리를 담당
Authorization Code를 Access Token으로 교환한 뒤, OAuth2UserService를 통해 UserInfo Endpoint에서 사용자 정보를 조회하고 최종 로그인 인증 객체를 생성한다.
OAuth2LoginAuthenticationToken을 인증 완료 상태로 반환
OAuth2AuthorizationCodeAuthenticationProvider OAuth2 Authorization Code Grant의 Code-to-Token 교환만 담당
Authorization Code를 Token Endpoint에 제출해 Access Token과 필요하면 Refresh Token을 발급받는다.
OAuth2AuthorizationCodeAuthenticationToken에 Access Token 응답을 담아 반환
OidcAuthorizationCodeAuthenticationProvider OpenID Connect Authorization Code Flow 전체 인증 처리를 담당한다.
Authorization Code를 Access Token과 ID Token으로 교환하고, ID Token의 서명과 Claim을 검증한다.
필요하면 OidcUserService를 통해 UserInfo Endpoint를 호출한 뒤 OIDC 사용자 인증 객체를 생성한다.
OAuth2LoginAuthenticationToken을 OIDC 사용자 정보와 함께 인증 완료 상태로 반환

 

 

구현체) OAuth2UserService

더보기
항목 OidcUserService DefaultOAuth2UserService
사용 조건 scope에 openid 포함 (OpenID Connect) scope에 openid 없음 (순수 OAuth2)
사용 목적 사용자 인증 + 정보 조회 (id_token + access token 기반) 사용자 정보 조회용 (access token 기반)
호출 대상 id_token + 선택적 user-info-uri user-info-uri
반환 타입 OidcUser (extends OAuth2User) OAuth2User
토큰 활용 방식 id_token을 먼저 파싱 → 필요 시 user info endpoint 호출 access_token으로 user info endpoint 호출
사용 위치 OidcAuthorizationCodeAuthenticationProvider OAuth2LoginAuthenticationProvider

 

 

설정) oauth2Login()

더보기
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        // ...
        .oauth2Login(Customizer.withDefaults());
        
    return http.build();
}
  • Spring Security에서 OAuth2/OIDC 로그인 흐름을 자동으로 처리하도록 켜는 설정임

 

4. Server-To-Server

  • 사용자 로그인 없이 서버 애플리케이션이 자신의 자격으로 access token을 발급받아 Resource Server API를 호출
  •  Auhtorization Server에서 자신의 자격 증명이나 기존 보안 토큰을 사용해 access token을 발급받아 요청함

 

요청 타입

항목 Client Credentials Flow (client_credentials)
Extension Grant Type (custom_grant)
주체 클라이언트 자기 자신의 자격 증명으로 발급받는 방식
추가 규격이나 사용자 정의 방식으로 발급받는 방식
용도 서버-서버 API 호출, 백엔드 시스템 인증 등 특수 목적 (token_exchange, jwt_bearer 등)
표준 여부 ✅ OAuth2.0 공식 표준 grant type
❌ OAuth2 확장 사양 (RFC 8693 등 또는 사용자 정의)
access_token 발급 여부 ✅ 
Client 지원 여부
✅ Token Exchange는 기본 지원
❌ 나머지는 직접 확장해야 함

 

 

표) extension grant type

더보기
항목 jwt-bearer token-exchange
Grant Type urn:ietf:params:oauth:grant-type:jwt-bearer urn:ietf:params:oauth:grant-type:token-exchange
주요 목적 기존 JWT 토큰을 사용해 Access Token 발급받기 기존 토큰을 새로운 토큰으로 교환
권한 위임 여부 ❌ (자기 자신 인증) ✅ (토큰 위임 및 재발급)
사용자 정보 포함  (클라이언트 인증 중심)  (sub, actor 등 교환 대상 지정)
Provider JwtBearerOAuth2AuthorizedClientProvider
TokenExchangeOAuth2AuthorizedClientProvider
사용 예시 사전에 발급받은 JWT를 제출해 자원 권한 요청 사용자가 받은 외부 토큰을 자사 API용으로 교환

 

API 호출 흐름

단계 구성 요소 역할 비고 / 주요 메서드
1 OAuth2ClientHttpRequestInterceptor - RestClient 요청을 가로채 사용할 OAuth2 Client를 결정
- Auth2AuthorizedClientManager에 Access Token 요청
- 최종적으로 발급받은 토큰을
Authorization 요청 헤더에 추가
Authorization: Bearer <access_token>
2 OAuth2AuthorizedClientManager OAuth2AuthorizedClient의 조회, 최초 인가, 재인가 및 저장 흐름을 총괄함
(기존 토큰이 유효하면 재사용하고, 없거나 갱신이 필요하면 Provider에 처리를 위임함)
authorize(OAuth2AuthorizeRequest)
3 OAuth2AuthorizedClientService 또는 OAuth2AuthorizedClientRepository 기존에 발급된 OAuth2AuthorizedClient를 조회하고, 새로 발급되거나 갱신된 토큰 정보를 저장한다. 메모리·JDBC 등의 구현체 사용 가능
4 OAuth2AuthorizedClientProvider 설정된 Grant Type에 따라 최초 Access Token 발급 또는 재인가 가능 여부를 판단하고 실제 토큰 요청을 수행한다. authorization_code, refresh_token, client_credentials
5 OAuth2AuthorizedClientManager Provider가 반환한 새 OAuth2AuthorizedClient를 저장소에 저장하고 Interceptor에 반환한다. Access Token 및 필요 시 Refresh Token 포함
6 OAuth2ClientHttpRequestInterceptor 반환받은 Access Token을 Bearer Token으로 요청 헤더에 추가한 뒤 실제 Resource Server 요청을 전송한다. Authorization: Bearer ...

 

 

설정) RestClient

더보기
@Bean
public RestClient restClient(OAuth2AuthorizedClientManager authorizedClientManager) {
    OAuth2ClientHttpRequestInterceptor requestInterceptor =
            new OAuth2ClientHttpRequestInterceptor(authorizedClientManager);

    // 사용자가 아닌, 요청 속성에 지정된 "가상의 주체" 이름을 principal로 사용
    requestInterceptor.setPrincipalResolver(new RequestAttributePrincipalResolver());

    return RestClient.builder()
            .requestInterceptor(requestInterceptor)
            .build();
}

 

설정) OAuth2AuthorizedClientProvider

더보기

 jwt-bearer

@Bean
public OAuth2AuthorizedClientProvider jwtBearer() {
    return new JwtBearerOAuth2AuthorizedClientProvider();
}
  • 사용하고 싶은 확장 인증 방식의 구현체를 빈으로 등록하기

 

5. Customize the RestOperations used by OAuth2 Client Components

  • OAuth2 Client가 토큰을 요청할 때 사용하는 HTTP 클라이언트를 직접 설정할 수 있음

 

설정) OAuth2AcccessTokenResposneClient

더보기
@Bean
public OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeAccessTokenResponseClient() {
    var client = new DefaultAuthorizationCodeTokenResponseClient();
    client.setRestOperations(restTemplate()); // 커스터마이징된 RestTemplate 주입
    return client;
}

 

설정) RestTemplate

더보기
@Bean
public RestTemplate restTemplate() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
    factory.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.mycorp.com", 8080)));
    factory.setConnectTimeout(3000);
    factory.setReadTimeout(3000);

    RestTemplate restTemplate = new RestTemplate(factory);
    restTemplate.setMessageConverters(List.of(new MappingJackson2HttpMessageConverter()));
    return restTemplate;
}
목적 설명
프록시 설정
기업 내부망에서 HTTP/HTTPS 프록시 설정 필요할 때
커스텀 인증 헤더 추가
예: mTLS, Basic 인증, 커스텀 헤더
메시지 변환기 교체
JSON → XML 또는 특수한 응답 파싱이 필요할 때
로깅 또는 트레이싱
요청/응답 로깅, Zipkin, Sleuth, etc. 연동

 

출처