티스토리 뷰

이전 글: https://gojs.tistory.com/61

 

OAuth 2.0 with Spring Security (2) - 추가적인 로그인 설정

https://gojs.tistory.com/60 OAuth 2.0 with Spring Security (1) - 기본 로그인 구현하기최근 프로젝트들의 경향을 살펴보면 자체 데이터를 기반으로 인증 로직을 구현하기보다는 대형 플랫폼의 인증 시스템을

gojs.tistory.com

 

OAuth 2.0 클라이언트는 아래와 같은 기능들을 제공한다.

  • 인가 코드
  • 리프레쉬 토큰
  • 클라이언트 자격증명
  • 리소스 소유자 비밀번호 자격증명
  • JWT
  • 토큰 교환

 

@Configuration
@EnableWebSecurity
public class OAuth2ClientSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .oauth2Client(oauth2 -> oauth2
                .clientRegistrationRepository(this.clientRegistrationRepository())
                .authorizedClientRepository(this.authorizedClientRepository())
                .authorizedClientService(this.authorizedClientService())
                .authorizationCodeGrant(codeGrant -> codeGrant
                    .authorizationRequestRepository(this.authorizationRequestRepository())
                    .authorizationRequestResolver(this.authorizationRequestResolver())
                    .accessTokenResponseClient(this.accessTokenResponseClient())
                )
            );
        return http.build();
    }
}

위 코드와 같이 HttpSecurity.oauth2Client() DSL은 OAuth 2.0 클라이언트의 핵심 컴포넌트를 커스텀할 수 있는 옵션들을 제공한다.

또한 HttpSecurity.oauth2Client().authorizationCodeGrant()는 인가 코드 증명을 커스텀할 수 있도록 한다.

 

@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
        ClientRegistrationRepository clientRegistrationRepository,
        OAuth2AuthorizedClientRepository authorizedClientRepository) {

    OAuth2AuthorizedClientProvider authorizedClientProvider = 
            OAuth2AuthorizedClientProviderBuilder.builder()
                    .authorizationCode()
                    .refreshToken()
                    .clientCredentials()
                    .password()
                    .build();
                    
    DefaultOAuth2AuthorizedClientManager authorizedClientManger = 
            new DefaultOAuth2AuthorizedClientManager(
                    clientRegistrationRepository, authorizedClientRepository);
    
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
    
    return authorizedClientManager;
}

OAuth2AuthorizedClientManager는 OAuth2AuthorizedClientProvider와 협력하여 OAuth 2.0 클라이언트의 인증을 관리하는 책임을 가진다.

위 코드를 기준으로 OAuth2AuthorizedClientProvider는 인가코드, 리프레쉬 토큰, 클라이언트 자격증명, 비밀번호의 증명 타입을 가진다.

 

위의 두 예시와 같이 OAuth 2.0 클라이언트를 설정할 수 있으며, 이 때 사용되는 핵심 인터페이스와 클래스를 알아보자.

 

ClientRegistration

ClientRegistration은 OAuth 2.0 또는 OpenID Connect 1.0 제공자에 등록된 클라이언트를 표현한다.

public final class ClientRegistration {
    private String registrationId;
    private String clientId;
    private String clientSecret;
    private ClientAuthenticationMethod clientAuthenticationMethod;
    private AuthorizationGrantType authorizationGrantType;
    private String redirectUri;
    private Set<String> scopes;
    private ProviderDetails providerDetails;
    private String clientName;
    
    public class ProviderDetails {
        private String authorizationUri;
        private String tokenUri;
        private UserInfoEndpoint userInfoEndpoint;
        private String jwkSetUri;
        private String issuerUri;
        private Map<String, Object> configurationMetadata;
        
        public class UserInfoEndpoint {
            private String uri;
            private AuthenticationMethod authenticationMethod;
            private String userNameAttributeName;
        }
    }
}

ClientRegistration 클래스에서 가지는 필드들은 아래와 같은 상태를 의미한다.

  1. registrationId: ClientRegistraion의 ID
  2. clientId: 클라이언트의 ID
  3. clientSecret: 클라이언트의 secret
  4. clientAuthenticationMethod: 클라이언트가 제공자의 인증에 사용하는 메서드 (client_seret_basic, client_secret_post, client_key_jwt, none)
  5. authorizationGrantType: OAuth 2.0 인증 프레임워크에서 정의한 인증 부여 타입
  6. redirectUri: 유저 인증 후 인증 서버가 유저의 user-agent를 redirect할 등록된 클라이언트의 redirect uri
  7. scopes: 인증 요청 흐름 중 클라이언트가 요청할 정보의 범위 (openid, email, profile, ...)
  8. clientName: 클라이언트를 위해 사용할 이름
  9. authorizationUri: 인증 서버의 인증 엔드포인트 uri
  10. tokenUri: 인증 서버의 토큰 엔드포인트 uri
  11. jwkSetUri: 인증 서버로부터 JWK를 조회하는데 사용되는 uri
  12. issuerUri: OIDC나 OAuth 서버의 issuer 식별 uri
  13. configurationMetadata: OpenID 제공자 설정 정보
  14. UserInfoEndpoint.uri: 인가된 엔드 유저의 클레임이나 속성에 접근하기 위해 사용되는 uri
  15. UserInfoEndpoint.authenticationMethod: 유저 정보 엔드포인트로 토큰을 보낼 때 사용되는 인가 방식 (header, form, query)
  16. UserInfoEndpoint.userNameAttributeName: 유저 정보 중 이름이나 식별자에 해당하는 속성의 이름

 

ClientRegistrationRepository

ClientRegistrationRepository는 ClientRegistration을 가져오는 역할을 한다.

Spring Boot는 spring.seurity.oaut2.client.registraion.registraionId로부터 바인딩된 ClientRegistraion 인스턴스를 ClientRegistraionRepository 내에 저장한다.

기본적으로 구현된 클래스는 InMemoryClientRegistrationRepository이고 ApplicationContext에 빈 오브젝트로 등록하여 특정한 구현체를 설정할 수 있다.

@Controller
public class OAuth2ClientController {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;
    
    @GetMapping("/")
    public String index() {
        ClientRegistration clientRegistration =
            clientRegistrationRepository.findByRegistrationId("okta");
        
        ...
        
        return "index";
    }
}

 

OAuth2AuthorizedClient

OAuth2AuthorizedClient 클래스는 인증된 클라이언트의 정보가 담기는 클래스이다.

OAuth2AuthorizedClientRepository는 OAuth2AuthorizedClient를 웹 요청에 따라 영속화하는 역할을 가졌으며 OAuth2AuthorizedClientService는 OAuth2AuthorizedClient를 어플리케이션 레벨에서 관리하는 역할을 가진다.

또한 이 두 클래스는 클라이언트의 OAuth2AccessToken을 찾을 수 있는 기능을 제공하여 보호된 자원에 대해 요청할 수 있도록 한다.

@Controller
public class OAuth2ClientController {

    @Autowired
    private OAuth2AuthorizedClientService authorizedClientService;
    
    @GetMapping("/")
    public String index(Authentication authentication) {
        OAuth2AuthorizedClient authorizedClient = 
            authorizedClientService.loadAuthorizedClient("okta", authentication.getName());
        
        OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
        
        ...
        
        return "index";
    }
}

 

OAuth2AuthorizedClientManager는 OAuth2AuthorizedClient의 관리 책임을 가지며 아래의 역할을 포함한다.

- OAuth2AuthorizedClientProvider를 사용하여 OAuth 2.0 클라이언트 인증

- OAuth2AuthorizedClientService와 OAuth2AuthorizedClientRepository를 사용하여 OAuth2AuthorizedClient 영속화

- OAuth 2.0 클라이언트가 성공적으로 인증되면 OAuth2AuthorizationSuccessHandler에게 위임

- OAuth 2.0 클라이언트가 인증에 실패하게되면 OAuth2AuthorizationFailurehandler에게 위임

 

OAuth2AuthorizedClientManager의 기본 구현체는 DefaultOAuth2AuthorizedClientManager이며 내부적으로 OAuth2AuthorizedClientProvider와 연관된다. OAuth2AuthorizedClientProvider는 컴포지트 패턴으로 구성되어 여러 개의 인가타입을 지원한다. 따라서 OAuth2AuthorizedClientProviderBuilder를 사용하여 authorization_code, refresh_token, client_credintials, password와 같은 인가 타입을 설정할 수 있다.

@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
        ClientRegistrationRepository clientRegistrationRepository,
        OAuth2AuthorizedClientRepository authorizedClientRepository) {
    
    OAuth2AuthorizedClientProvider authorizedClientProvider = 
        OAuth2AuthorizedClientProviderBuilder.builder()
            .authorizationCode()
            .refreshToken()
            .clientCredentials()
            .password()
            .build();
    
    DefaultOAuth2AuthorizedClientManager authorizedClientManager = 
        new DefaultOAuth2AuthorizedClientManager(
                clientRegistrationRepository, authorizedClientRepository);
    authorizedClientManger.setAuthorizedClientProvider(authorizedClientProvider);
    
    return authorizedClientManager;
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함