1. OAuth2 Resource Server
- 보호된 자원에 대한 요청에 대하여, 인증 과정을 거쳐 자원을 응답하는 서버
Protect Access with an OAuth2 Access Token
구분 | 설명 | 사용 구성 |
JWT | 자체 서명 토큰 (일반적인 OAuth2/JWT 기반 API 보호) | 자체 디코딩 가능 (검증용 public key만 있으면 됨) |
Opaque Token | 토큰 내용을 알 수 없는 토큰 | introspection 엔드포인트로 검증 (외부 인증 서버에서 introspection 제공 시 사용 가능) |
설정) JWT
더보기
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://my-auth-server.com
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.jwt());
return http.build();
}
@Bean
public JwtDecoder jwtDecoder() {
return JwtDecoders.fromIssuerLocation("https://my-auth-server.com");
}
}
설정) Opaque Token
더보기
spring:
security:
oauth2:
resourceserver:
opaquetoken:
introspection-uri: https://my-auth-server.com/oauth2/introspect
client-id: my-client-id
client-secret: my-client-secret
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2.opaqueToken());
return http.build();
}
@Bean
public OpaqueTokenIntrospector opaqueTokenIntrospector() {
return new SpringOpaqueTokenIntrospector(
"https://my-auth-server.com/oauth2/introspect",
"my-client-id",
"my-client-secret");
}
}
Protect Access with a custom JWT
- 수동으로 직접 발급된 Access Token을 검증하는 방법
- BearerTokenAuthenticationFilter + JwtAuthenticationProvider (NimbusJwtDecoder)
설정) Custom Access Token 검증
더보기
spring:
security:
oauth2:
resourceserver:
jwt:
public-key-location: classpath:my-public-key.pub
- 공개키만 등록하면 됨 (NimbusJwtDecoder)
2. OAuth2 Client
- 로그인 처리하거나 API 요청에 사용할 수 있게 해주는 애플리케이션
- Spring 앱이 외부 인증/인가 서버와 통신
설정) client 등록
더보기
사용할 외부 인증 서버에 대한 정보 등록
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
provider:
my-oidc-provider:
issuer-uri: https://my-oidc-provider.com
항목 경로 | 설명 |
spring.security.oauth2.client.registration.<registration-id> | OAuth2 로그인용 클라이언트 등록 설정 |
registration.provider | 연결할 인증 서버 설정명 (아래 provider 항목 참조) |
registration.client-id | 외부 인증 서버에서 발급받은 클라이언트 ID |
registration.client-secret | 외부 인증 서버에서 발급받은 클라이언트 비밀번호 |
registration.authorization-grant-type | 권한 부여 방식 |
registration.scope | 인증 요청 시 필요한 정보 범위 (OIDC의 경우 반드시 openid 포함) |
spring.security.oauth2.client.provider.<provider-id> | 인증 서버 설정 |
provider.issuer-uri | OIDC 메타데이터를 조회할 인증 서버 주소 |
- ClientRegistrationRepository에 등록됨
Grant Type
- access token을 얻는 방식
- 상황에 따라 받는 방식이 달라지므로 여러 종류의 grant type이 정의됨
Grant Type | 설명 | 보안 고려사항 | 사용 주체 | 사용 예시 |
authorization_code | user-agent가 로그인 후, Authorization Code를 받아 access_token 발급 | 가장 안전한 방식 (리디렉션 + 서버 측 처리) |
user | 소셜 로그인 |
refresh_token | access_token이 만료되었을 때, refresh_token으로 새 access_token 재발급 | refresh_token은 장기 보관되므로 유출 시 위험 | user | 자동 로그인 유지 |
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 |
마이크로서비스 간 인증
|
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 | OAuth2AuthorizationCodeAuthenticationProvider |
흐름) 로그인
더보기
단계 | 주체 | 동작 내용 | 관련 컴포넌트 |
1 | User-Agent | 클라이언트에서 제공한 OAuth2 로그인 페이지 접속 | DefaultLoginPageGeneratingFilter (/oauth2/authorization/{registrationId}) |
2 | Client | Authorization Server의 로그인 페이지로 리다이렉션 | OAuth2AuthorizationRequestRedirectFilter |
3 | User-Agent | Authorization Server에 로그인 요청 | (브라우저를 통한 직접 요청) |
4 | Authorization Server | 로그인 처리 및 인증 결과 생성 → redirect_uri로 리다이렉션 (code 포함) |
(서버 내부 인증 처리) (/login/oauth2/code/{registrationId}) |
5 | Client | 받은 authorization code로 토큰 및 사용자 정보 요청 | OAuth2LoginAuthenticationFilter |
구현체) AuthenticationProvider
더보기
클래스명 | 주요 역할 및 설명 |
OAuth2LoginAuthenticationProvider | OAuth2 로그인 흐름 - Authorization Code → Access Token 교환 - 인증 토큰 생성 |
- OAuth2AuthorizationCodeAuthenticationProvider | OAuth2 로그인 흐름 - Authorization Code → Access Token 교환 |
- OidcAuthorizationCodeAuthenticationProvider | OIDC 로그인 흐름 - ID Token, Access Token 처리 |
OidcBackChannelLogoutAuthenticationProvider |
OIDC 로그아웃 흐름
- OIDC Back-Channel Logout 요청을 처리하는 Provider - 서버 간 로그아웃 연동 지원 |
구현체) OAuth2UserService
더보기
Access Token → Userinfo 를 가져오는 것을 담당하는 클래스
항목 | 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
더보기
OAuth2Login()
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// ...
.oauth2Login(Customizer.withDefaults());
return http.build();
}
- Spring Security에서 OAuth2/OIDC 로그인 흐름을 처리
server-to-server
항목 | Client Credentials Flow (client_credentials) |
Extension Grant Type (custom_grant)
|
주체 | 사용자 ❌ 없음 → 클라이언트(client_id) 자체가 주체 |
정의에 따라 유동적
(예: 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 저장) |
직접 처리 필요
(토큰 컨텍스트/스코프 등 커스터마이징 필요) |
흐름) server-to-server
더보기
단계 | 구성 요소 | 역할 설명 | 비고 / 주요 메서드 |
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/메모리 등) |
표) 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용으로 교환 |
설정) 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();
}
- 사용하고 싶은 확장 인증 방식의 구현체를 빈으로 등록하기
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-3. OAuth2 Login: Advanced Configuration (0) | 2025.07.17 |
---|---|
[Spring Security] 6-2. 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 |