Spring Security ‐ OAuth 2.0 oauth2Client - dnwls16071/Backend_Summary GitHub Wiki
📚 OAuth2ClientConfigurer 초기화 및 설정
OAuth2AuthorizedClient
- OAuth2AuthorizedClient는 인가받은 클라이언트를 의미하는 클래스이다.
- 최종 사용자가 클라이언트에게 리소스에 접근할 수 있는 권한을 부여하면 클라이언트를 인가된 클라이언트로 간주한다.
- OAuth2AuthorizedClient는 Access Token과 Refresh Token을 ClientRegistration와 권한을 부여한 최종 사용자인 Principal과 함께 묶어준다.
- OAuth2AuthorizedClient의 Access Token을 사용해서 리소스 서버 자원에 접근할 수 있으며 인가 서버와의 통신으로 토큰을 검증할 수 있다.
- OAuth2AuthorizedClient의 ClientRegistration과 Access Token을 사용해서 UserInfo 엔드포인트로 요청할 수 있다.
public class OAuth2AuthorizedClient implements Serializable {
private static final long serialVersionUID = 620L;
private final ClientRegistration clientRegistration;
private final String principalName;
private final OAuth2AccessToken accessToken;
private final OAuth2RefreshToken refreshToken;
public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken) {
this(clientRegistration, principalName, accessToken, (OAuth2RefreshToken)null);
}
public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) {
Assert.notNull(clientRegistration, "clientRegistration cannot be null");
Assert.hasText(principalName, "principalName cannot be empty");
Assert.notNull(accessToken, "accessToken cannot be null");
this.clientRegistration = clientRegistration;
this.principalName = principalName;
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
public ClientRegistration getClientRegistration() {
return this.clientRegistration;
}
public String getPrincipalName() {
return this.principalName;
}
public OAuth2AccessToken getAccessToken() {
return this.accessToken;
}
@Nullable
public OAuth2RefreshToken getRefreshToken() {
return this.refreshToken;
}
}
OAuth2AuthorizedClientRepository
- OAuth2AuthorizedClientRepository는 다른 웹 요청이 와도 동일한 OAuth2AuthorizedClient를 유지하는 역할을 담당한다.
- OAuth2AuthorizedClientService에게 OAuth2AuthorizedClient의 저장/조회/삭제 처리를 위임한다.
OAuth2AuthorizedClientService
- OAuth2AuthorizedClientService는 애플리케이션 레벨에서 OAuth2AuthorizedClient를 관리(저장/조회/삭제)하는 일이다.
- OAuth2AuthorizedClientRepository나 OAuth2AuthorizedClientService는 OAuth2AuthorizedClient 에서 OAuth2AccessToken 을 찾을 수 있는 기능을 제공하므로 보호중인 리소스 요청을 시작할 때 사용할 수 있다.
OAuth2AuthorizationCodeGrantFilter
- Authorization Code Grant 방식으로 권한 부여 요청을 지원하는 필터
- 인가서버로부터 리다이렉트되면서 전달된 code를 인가 서버의 access token으로 교환한다.
- OAuth2AuthorizedClientRepository를 사용하여 OAuth2AuthorizedClient를 저장 후 클라이언트 Redirect URI로 이동한다.
📚 DefaultOAuth2AuthorizedClientManager
- OAuth2AuthorizedClient를 전반적으로 관리하는 인터페이스
- OAuth2AuthorizedClientProvider로 OAuth 2.0 클라이언트에 권한 부여
- OAuth2AuthorizedClientService나 OAuth2AuthorizedClientRepository에 OAuth2AuthorizedClient 저장을 위임한 후 OAuth2AuthorizedClient가 최종 반환된다.
- 사용자 정의 OAuth2AuthorizationSuccessHandler, OAuth2AuthorizationFailureHandler를 구성하여 성공/실패 처리를 변경할 수 있다.
invalid_grant 오류로 인해 권한 부여가 실패하면 이전에 저장된 OAuth2AuthorizedClient가 OAuth2AuthorizedClientRepository에서 제거가 된다.
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.clientCredentials()
.password()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
📚 Resource Owner Password Flow
📚 Client Credentials Flow
📚 Refresh Token Flow
📚 DefaultOAuth2AuthorizedClientManager - 필터 기반으로 구현하기
- 인증 요청 시작
- 인증 요청 객체 생성
- 클라이언트 관리 계층
- 토큰 발급 처리
- 토큰 저장
- 사용자 정보 조회
- 인증 완료
- 파라미터를 OAuth2AuthorizedClient 타입 인자로 리졸브해준다.
- OAuth2AuthorizedClientArgumentResolver에서 요청을 가로채 유형별로 권한 부여 흐름을 실행하도록 한다.
- 이 방법은 OAuth2AuthorizedClientManager나 OAuth2AuthorizedClientService로 OAuth2AuthorizedClient에 접근하는 것보다 편리하다.
@GetMapping("/")
public String index(@RegisteredOAuth2AuthorizedClient("keycloak") OAuth2AuthorizedClient client) {
OAuth2AccessToken token = client.getAccessToken();
}