1. Resolving an Authorized Client
@RegisteredOAuth2AuthorizedClient
- 컨트롤러 메서드에서 OAuth2AuthorizedClient를 주입받을 수 있음
- OAuth2AuthorizedClientArgumentResolver에 의해 주입됨
- OAuth2AuthorizedClientArgumentResolver는 OAuth2AuthorizedClientManager를 사용하여 가져옴
- OAuth2AuthorizedClientManager는 Repository와 Provider에게 위임하여 OAuth2AuthorizedClient를 반환함
- Provider의 전략 객체별 조건을 만족해야 동작함
예시) OAuth2ClientController
더보기
@Controller
public class OAuth2ClientController {
@GetMapping("/")
public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
// accessToken으로 외부 API 호출 등 수행
return "index";
}
}
2. RestClient Integration
OAuth2ClientHttpRequestInterceptor
- 보호된 자원 서버에 접근할 때 Bearer 토큰을 자동으로 Authorization Header에 넣어주는 인터셉터 설정
- 인증 토큰이 없을 경우, 내부적으로 OAuth2AuthorizedManager를 사용해서 인증 토큰 얻어온 후, 요청함
설정) RestClient
더보기
@Configuration
public class RestClientConfig {
@Bean
public RestClient restClient(OAuth2AuthorizedClientManager authorizedClientManager) {
OAuth2ClientHttpRequestInterceptor requestInterceptor =
new OAuth2ClientHttpRequestInterceptor(authorizedClientManager);
return RestClient.builder()
.requestInterceptor(requestInterceptor)
.build();
}
}
Providing the clientRegistrationId
- 요청 시, 어떤 provider에 요청할지는 clientRegistrationIdResolver가 담당함
- 기본적으로 RequestAttributeClientRegistrationIdResolver를 사용함
- request의 'clientRegistrationId' attribute에 의해 결정됨
커스터마이징) clientRegistrationIdResolver
더보기
@Bean
public RestClient restClient(OAuth2AuthorizedClientManager authorizedClientManager) {
OAuth2ClientHttpRequestInterceptor interceptor =
new OAuth2ClientHttpRequestInterceptor(authorizedClientManager);
interceptor.setClientRegistrationIdResolver((request) -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return (authentication instanceof OAuth2AuthenticationToken principal)
? principal.getAuthorizedClientRegistrationId()
: null;
});
return RestClient.builder()
.requestInterceptor(interceptor)
.build();
}
Providing the principal
- OAuth2ClientHttpRequestInterceptor는 기본적으로 SecurityContextHolder에서 현재 로그인한 사용자(principal)를 읽음
- clientRegistrationId + principal로 그 사용자의 OAuth2AuthorizedClient를 찾거나 새로 토큰을 받음
커스터마이징) principleResolver
더보기
requestInterceptor.setPrincipalResolver(new RequestAttributePrincipalResolver());
- HttpRequest의 attributes()에 명시적으로 principle을 지정할 수 있음
Handling Failure
- Access Token이 실패했을 때, 해당 OAuth2AuthorizedClient를 자동으로 삭제하는 방식이 필요 (예: 만료됨)
- OAuth2ClientHttpRequestInterceptor는 OAuth2AuthorizedClient를 저장하는 두가지 컴포넌트를 주입받아 삭제함
- Repository: http request 흐름일 경우
- Service: 서버 사이드 동작 경우
설정) Repository 기반
더보기
OAuth2AuthorizationFailureHandler failureHandler =
OAuth2ClientHttpRequestInterceptor.authorizationFailureHandler(authorizedClientRepository);
requestInterceptor.setAuthorizationFailureHandler(failureHandler);
설정) Service 기반
더보기
OAuth2AuthorizationFailureHandler failureHandler =
OAuth2ClientHttpRequestInterceptor.authorizationFailureHandler(authorizedClientService);
requestInterceptor.setAuthorizationFailureHandler(failureHandler);
출처
'Spring > Spring Security' 카테고리의 다른 글
[JWT] 2-3. Practical Application: OAuth2 & OpenID (0) | 2025.07.22 |
---|---|
[Spring Authorization Server] 1. Configuration Model (0) | 2025.07.20 |
[Spring Security] 7-2. OAuth2 Client: Authorization Grant Support (3) | 2025.07.19 |
[Spring Security] 7-1. OAuth2 Client: Core Interfaces and Classes (0) | 2025.07.18 |
[Spring Security] 6-4. OAuth2 Login: OIDC Logout (1) | 2025.07.18 |