Spring-cloud-sleuth: Set up for `OAuth2RestTemplate` not documented

Created on 1 May 2017  路  17Comments  路  Source: spring-cloud/spring-cloud-sleuth

Out of the box, the X-B3-TraceId and X-B3-SpanId headers are not set on requests made with the OAuth2RestTemplate. The workaround for this is to add the TraceRestTemplateInterceptor to the list of OAuth2RestTemplate interceptors. Until out-of-the-box support for OAuth2RestTemplate is provided, the Spring Cloud Sleuth documentation should note that the TraceRestTemplateInterceptor must be added to the OAuth2RestTemplate.

enhancement

Most helpful comment

As far as I researched UserInfoRestTemplateCustomizer using for customizing OAuth2RestTemplate, because list of UserInfoRestTemplateCustomizer is used in DefaultUserInfoRestTemplateFactory:getUserInfoRestTemplate().

    @Override
    public OAuth2RestTemplate getUserInfoRestTemplate() {
        if (this.oauth2RestTemplate == null) {
            this.oauth2RestTemplate = createOAuth2RestTemplate(
                    this.details == null ? DEFAULT_RESOURCE_DETAILS : this.details);
            this.oauth2RestTemplate.getInterceptors()
                    .add(new AcceptJsonRequestInterceptor());
            AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
            accessTokenProvider.setTokenRequestEnhancer(new AcceptJsonRequestEnhancer());
            this.oauth2RestTemplate.setAccessTokenProvider(accessTokenProvider);
            if (!CollectionUtils.isEmpty(this.customizers)) {
                AnnotationAwareOrderComparator.sort(this.customizers);
                for (UserInfoRestTemplateCustomizer customizer : this.customizers) {
                    customizer.customize(this.oauth2RestTemplate);
                }
            }
        }
        return this.oauth2RestTemplate;
    }

All 17 comments

Do you think you could push a sample to Github of how you set up a project with the @OAuth2RestTemplate in such a way that things don't work? That way it will be easier for me to analyze what's wrong

Hi Marcin,
Sorry for the delayed response -- was out of the office. Let me see what I can get together.
Thanks!

Ping @mhuisking ?

Closing due to inactivity

@marcingrzejszczak, @mhuisking
I've faced with this issue too.

I've solved with next code:

    @Bean
    public UserInfoRestTemplateCustomizer userInfoRestTemplateCustomizer(
            TraceRestTemplateInterceptor traceRestTemplateInterceptor) {
        return restTemplate -> {
            List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>(
                    restTemplate.getInterceptors());
            interceptors.add(traceRestTemplateInterceptor);
            restTemplate.setInterceptors(interceptors);
        };
    }

So you're saying that for some reason the TraceRestTemplateInterceptor doesn't get injected into the OAuth2RestTemplate ? That's super strange. @rwinch, @dsyer - are OAuth2RestTemplate's interceptors somehow separated from the "traditional" RestTemplate interceptors? In other words, do I have to do sth special for my custom RestTemplate interceptor to get registered in my OAuth2RestTemplate

@marcingrzejszczak,
TraceRestTemplateInterceptor works good with OAuth2RestTemplate using my solution.
So now my requests for instance client->user-service [solution added here]->auth-service to security.oauth2.resource.user-info-uri has the same X-B3-TraceId, without config only client and user-service has the same X-B3-TraceId, but auth-service different.

Yeah using your solution it works fine, but the idea was that that TraceRestTemplateInterceptor gets injected automatically - https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java#L63-L83 . In theory all rest templates should have it injected. For some reason it seems that the OAuth2RestTemplate is not in that collection. BTW @Triggerself could you put a breakpoint here - https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java#L78 and see if your OAuth2RestTemplate is there?

@marcingrzejszczak,
I see only my RestTemplate, which was configured this way:

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

There is no OAuth2RestTemplate there.

P.S
OAuth2RestTemplate class extends RestTemplate and implements OAuth2RestOperations

That's what I suspected... Meh. @rwinch @dsyer any ideas? Maybe that OAuth2RestTemplate is created later than this interceptor injection gets executed?

@Triggerself Have you created the OAuth2RestTemplate as a bean?

@marcingrzejszczak,
No, it's created in backgroud here:

ResourceServerTokenServicesConfiguration:RemoteTokenServicesConfiguration:UserInfoTokenServicesConfiguration[constructor with constructor autowired UserInfoRestTemplateFactory restTemplateFactory] by calling restTemplateFactory.getUserInfoRestTemplate()

That's why it's not working out of the box. @dsyer suggested that, in Sleuth, we could

just provide a customizer (That's the supported extension point in Spring Boot).
UserInfoRestTemplateCustomizer works for this precise instance (that isn't a bean)

So, at the end the issue will be solved by providing UserInfoRestTemplateCustomizer as I suggested?

Not necessarilly UserInfoRestTemplateCustomizer but some customizer. I don't know yet how to do it exactly, but that's good that you've provided a workaround for this

As far as I researched UserInfoRestTemplateCustomizer using for customizing OAuth2RestTemplate, because list of UserInfoRestTemplateCustomizer is used in DefaultUserInfoRestTemplateFactory:getUserInfoRestTemplate().

    @Override
    public OAuth2RestTemplate getUserInfoRestTemplate() {
        if (this.oauth2RestTemplate == null) {
            this.oauth2RestTemplate = createOAuth2RestTemplate(
                    this.details == null ? DEFAULT_RESOURCE_DETAILS : this.details);
            this.oauth2RestTemplate.getInterceptors()
                    .add(new AcceptJsonRequestInterceptor());
            AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
            accessTokenProvider.setTokenRequestEnhancer(new AcceptJsonRequestEnhancer());
            this.oauth2RestTemplate.setAccessTokenProvider(accessTokenProvider);
            if (!CollectionUtils.isEmpty(this.customizers)) {
                AnnotationAwareOrderComparator.sort(this.customizers);
                for (UserInfoRestTemplateCustomizer customizer : this.customizers) {
                    customizer.customize(this.oauth2RestTemplate);
                }
            }
        }
        return this.oauth2RestTemplate;
    }
Was this page helpful?
0 / 5 - 0 ratings

Related issues

andcuevas picture andcuevas  路  5Comments

barrycommins picture barrycommins  路  6Comments

apolischuk picture apolischuk  路  7Comments

oburgosm picture oburgosm  路  4Comments

marcingrzejszczak picture marcingrzejszczak  路  6Comments