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. 연동
|
출처
'Spring > Spring Security' 카테고리의 다른 글
| [Spring Security] 6-2. OAuth2 Login: Advanced Configuration (0) | 2025.07.17 |
|---|---|
| [Spring Security] 6-1. OAuth2 Login: Core Configuration (1) | 2025.07.15 |
| [Spring Security] 4-2. Authorization: HttpServletRequests (2) | 2025.07.11 |
| [Spring Security] 4-1. Authorization: Architecture (0) | 2025.07.03 |
| [Spring Security] 5-4. 보안: HttpFirewall (0) | 2023.10.14 |