programing

Spring Cloud Security와 함께 OAuth2 "Token Exchange"를 구현하는 방법

padding 2023. 7. 22. 09:31
반응형

Spring Cloud Security와 함께 OAuth2 "Token Exchange"를 구현하는 방법

Spring Cloud Security(OAuth2 사용)로 "토큰 교환" 기술을 구현하는 방법을 확인할 수 있는 사례가 있는지 알고 싶습니다.

현재 저는 마이크로서비스 환경에서 ZuulProxy를 사용하여 OAuth2 토큰을 "릴레이"하고 SSO를 구현하는 "토큰 릴레이" 기술을 구현했습니다.이것은 훌륭하지만 모든 마이크로서비스가 동일한 clientId를 사용한다는 것을 의미합니다(ZuulProxy 설정에서 ZuulProxy가 authorization_code grant type과 제공된 clientId로만 토큰을 릴레이하도록 지정됨).그러나 마이크로서비스 내 통화의 경우 토큰을 "교환"하고 싶습니다.이는 경우에 따라 ZuulProxy가 릴레이하는 토큰이 Microservice A를 Microservice B의 클라이언트로 인증/인가하는 데 사용해야 하는 토큰이 아님을 의미합니다.

Spring Cloud 참조 문서에는 현재 "Spring Boot and Spring Security OAuth2를 기반으로 싱글 사인온, 토큰 릴레이 및 토큰 교환과 같은 일반적인 패턴을 구현하는 시스템을 신속하게 생성할 수 있습니다."(http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html)

참고 문서에서 "토큰 교환"을 사용하면 기본적으로 제가 필요로 하는 OAuth2 확장의 구현을 의미한다고 생각합니다. https://datatracker.ietf.org/doc/html/draft-ietf-oauth-token-exchange-03

앞서 말했듯이 SSO 및 토큰 릴레이 사용 방법은 이해하지만 참조 문서에서 "토큰 교환"을 구현하는 방법에 대한 자세한 설명은 볼 수 없습니다.저도 구현 예를 찾을 수 없었습니다.

제가 어디서 더 많은 정보나 예를 찾을 수 있는지 아는 사람 있나요?

감사합니다!

저는 왜 당신이 A 마이크로 서비스에서 B 마이크로 서비스로 전화를 걸기 위해 토큰을 "교환"해야 하는지, 왜 중계가 충분하지 않은지 궁금합니다.서비스 간 요청에 토큰을 교환하여 무엇을 달성하려고 합니까?

Nordic API 항목에 설명된 것과 매우 유사한 설정이 있습니다.간단한 버전은 외부 발신자가 불투명 토큰을 사용하지만 요청이 게이트웨이를 통과하면 모든 마이크로서비스가 동일한 토큰의 JWT 표현을 받습니다.우리는 불투명한 JWT 교환을 수행하기 위해 사용자 정의 엔드포인트를 구현해야 했습니다.서비스가 서로 상호 작용해야 할 때, 우리는 A가 B를 호출해야 할 때 토큰을 교환하지 않고 단순히 토큰을 중계합니다.RestTemplate 또는 Feign 클라이언트는 자동으로 토큰을 A에서 B로 전달합니다.따라서 컨텍스트가 손실되지 않습니다.

만약 우리가 접근을 통제하고 싶다면, JWT는 시청자 가치의 집합을 지정하거나 스코프를 통해 접근을 강제할 수 있습니다.우리는 실제로 사용 사례에 따라 두 가지를 조합하여 사용하고 있습니다.

토큰을 교환하는 것은 저렴한 작업이 아닙니다. 실제로 규모 면에서 상당히 비용이 많이 들기 때문에 서비스 내 통신을 위해 토큰 교환을 해야 하는 이유를 정말로 고려해야 합니다.모든 API 요청이 A 서비스에서 B 서비스를 호출하고 토큰 교환을 해야 하는 경우, 인증 서비스가 해당 유형의 워크로드를 처리할 수 있는지 확인해야 합니다.마지막으로, IETF 토큰 교환은 여전히 초안 상태이며, 진화 과정에서 상당한 변화가 있었기 때문에 사양이 최종화에 가까워질 때까지 구현 조언 방식에 대해 많은 것을 기대하지 않을 것입니다.

저는 이것이 당신이 시도해 볼만한 것이라고 생각합니다.

제 프로젝트에서는 마이크로 서비스를 위해 OAuth2, Eureka, Ribbon을 사용하여 서로 통신합니다.Ribbon을 OAuth2와 함께 사용하기 위해 우리가 취한 접근 방식은 조금 달랐습니다.

먼저 나머지 템플릿은 그대로 둡니다.

  @LoadBalanced
  @Bean
  public RestTemplate restTemplate() {

하지만 우리는 Request를 구현하는 FeignClientIntercepter를 만들었습니다.restTemplate를 통해 요청할 때 OAuth에 대한 인증 토큰을 설정하는 인터셉터.

  @Component
  public class FeignClientInterceptor implements RequestInterceptor {

    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_TOKEN_TYPE = "Jwt";

    @Override
    public void apply(RequestTemplate template) {
      SecurityContext securityContext = SecurityContextHolder.getContext();
      Authentication authentication = securityContext.getAuthentication();

      if (authentication != null && authentication
          .getDetails() instanceof OAuth2AuthenticationDetails) {
        OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication
          .getDetails();
        template.header(AUTHORIZATION_HEADER,
            String.format("%s %s", BEARER_TOKEN_TYPE, details.getTokenValue()));
      }
    }
  }

언급URL : https://stackoverflow.com/questions/34905628/how-to-implement-oauth2-token-exchange-with-spring-cloud-security

반응형