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 - 필터 기반으로 구현하기

  • 인증 요청 시작
  • 인증 요청 객체 생성
  • 클라이언트 관리 계층
  • 토큰 발급 처리
  • 토큰 저장
  • 사용자 정보 조회
  • 인증 완료

📚 @RegisteredOAuth2AuthorizedClient

  • 파라미터를 OAuth2AuthorizedClient 타입 인자로 리졸브해준다.
  • OAuth2AuthorizedClientArgumentResolver에서 요청을 가로채 유형별로 권한 부여 흐름을 실행하도록 한다.
  • 이 방법은 OAuth2AuthorizedClientManager나 OAuth2AuthorizedClientService로 OAuth2AuthorizedClient에 접근하는 것보다 편리하다.
@GetMapping("/")
public String index(@RegisteredOAuth2AuthorizedClient("keycloak") OAuth2AuthorizedClient client) {
    OAuth2AccessToken token = client.getAccessToken();
}