Spring/Spring Security

[Spring Security] 7-1. OAuth2 Client

noahkim_ 2025. 7. 13. 06:05

1. OAuth2 Client

  • 로그인 흐름을 시작하고, 응답으로 토큰을 받아 API 요청에 사용할 수 있게 해주는 애플리케이션
  • ✅ 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에서 access token을 발급받는 방식
  • ➡️ 상황에 따라 Authorization Server에 서로 다른 방식으로 토큰을 요청함

 

타입

Grant Type 설명 보안 고려사항 사용 주체 사용 예시
authorization_code user-agent가 로그인하여 authorization code를 받고, OAuth2 Client가 이 code를 access_token으로 교환하는 방식 가장 안전한 방식
(리디렉션 + 서버 측 처리)
user,
OAuth2 Client
소셜 로그인
refresh_token access_token이 만료되었을 때, refresh_token을 사용해 새 access_token 발급받는 방식 refresh_token은 장기 보관되므로 유출 시 위험 OAuth2 Client 자동 로그인 유지
client_credentials 사용자 없이 client id/secret만으로 access_token을 발급받는 방식 클라이언트 자격이 노출되면 악용 가능 server 백엔드 API 호출
스케줄러
배치
jwt_bearer 클라이언트가 서명된 JWT를 통해 access_token 발급 (assertion 기반) JWT 위변조/만료 검증 필요 server
3rd party 시스템 연동
token_exchange 기존 access_token을 다른 시스템의 token으로 교환 원본 토큰의 권한 관리가 중요 server
마이크로서비스 간 인증

 

3. Login

타입

항목 OIDC (OpenID Connect)
OAuth 2.0
주요 목적 사용자 인증 (누구인지 확인)
권한 부여 (무엇을 할 수 있는지 허가)
사용 토큰 ID Token (JWT)
Access Token (리소스 접근 권한을 부여받은 토큰)
사용자 정보 포함 여부 ✔️ ID Token에 사용자 정보 포함됨 (sub, email 등)
❌  별도 API 호출 필요
사용 위치 내 애플리케이션의 로그인 인증 처리
외부 API 사용 (예: Kakao, Google API)
scope 'openid' 포함 ✅ 
표준 확장 규격 여부 ✅ OAuth2의 인증 기능 확장 ❌ 인가 표준
리턴 시 포함 토큰 ID Token, Access Token
Access Token, (선택적 Refresh Token)
provider 클래스 OidcAuthorizationCodeAuthenticationProvider OAuth2LoginAuthenticationProvider
  • OAuth2는 원래 로그인 프로토콜이 아닌 권한 부여 프로토콜
  • ✅ OAUth2 AccessToken으로 UserInfo APi를 호출해 사용자 정보를 가져오면 로그인처럼 쓸 수 있음
  •  OIDC는 OAuth2 위에 사용자 인증을 수행하는 확장 규격임 (ID Token가 추가로 응답됨)

 

흐름

단계 주체 동작 내용 관련 컴포넌트
1 User-Agent 클라이언트에서 제공한 OAuth2 로그인 페이지 접속 DefaultLoginPageGeneratingFilter
(/oauth2/authorization/{registrationId})
2 OAuth2-Client Authorization Server의 로그인 페이지로 리다이렉션 OAuth2AuthorizationRequestRedirectFilter
3 User-Agent Authorization Server에 로그인 요청 (브라우저를 통한 직접 요청)
4 Authorization Server 로그인 처리 및 인증 결과 생성 redirect_uri로 리다이렉션됨
(/login/oauth2/code/{registrationId})
5 OAuth2-Client redirect_uri로 전달된 authorization code를 수신하고, 이를 token으로 교환한 뒤 사용자 인증 객체를 생성 OAuth2LoginAuthenticationFilter
OAuth2LoginAuthenticationProvider
OidcAuthorizationCodeAuthenticationProvider
OAuth2UserService

 

 

구현체) AuthenticationProvider

더보기
더보기
클래스명 주요 역할 및 설명
OAuth2LoginAuthenticationProvider OAuth2 로그인 인증 처리 담당. Authorization Code를 Access Token으로 교환하고, OAuth2UserService를 통해 사용자 정보를 조회한 뒤 인증 객체를 생성한다.
OAuth2AuthorizationCodeAuthenticationProvider Authorization Code를 Access Token으로 교환하는 단계 담당. 로그인 전체보다는 code-token 교환에 초점이 있다.
OidcAuthorizationCodeAuthenticationProvider OIDC 로그인 처리 담당. Authorization Code를 ID Token, Access Token으로 교환하고, ID Token을 검증한 뒤 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

  • 서버 애플리케이션이 자기 자신의 client 자격으로 Resource Server API를 호출하는 방식
  •  Auhtorization Server에서 access token을 발급받아 요청함
  • ✅ 사용자가 직접 로그인하지 않음

 

타입

항목 Client Credentials Flow (client_credentials)
Extension Grant Type (custom_grant)
주체 클라이언트 자체가 주체 (사용자 ❌)
정의에 따라 달라짐 (ex. JWT, SAML, 내부 토큰 등)
용도 - 서버-서버 API 호출
- 백엔드 시스템 인증
특수 목적
(예: token_exchange, jwt_bearer, 커스텀 인증 등)
표준 여부 ✅ OAuth2.0 공식 표준 grant type
❌ OAuth2 확장 사양 (RFC 8693 등 또는 사용자 정의)
사용되는 토큰 access_token (refresh_token ❌)
access_token (refresh_token )
Spring에서 지원 여부 ✅ 기본 내장
❌ 직접 구현 필요
access token 관리 클라이언트별로 분리 가능
(principal 기반 OAuth2AuthorizationService 저장)
직접 처리 필요
(토큰 컨텍스트/스코프 등 커스터마이징 등)

 

 

표) 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용으로 교환

 

흐름

단계 구성 요소 역할 설명 비고 / 주요 메서드
1 OAuth2ClientHttpRequestInterceptor RestClient 요청 시 자동으로 access token을 Authorization 헤더에 실어주는 인터셉터 Bearer <access_token>
2 OAuth2AuthorizedClientManager 인증된 client에서 access token 획득
(필요시 재인증 또는 재발급 흐름을 관리함)
authorize(OAuth2AuthorizeRequest)
3 OAuth2AuthorizedClientProvider 다양한 grant type 처리 내부적으로 token 발급 처리
4 OAuth2AuthorizedClientService 발급된 access token 및 관련 정보를 저장하고 재사용할 수 있도록 관리 저장소 구현체 존재
(DB/메모리 등)

 

 

설정) 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. 연동

 

출처