PasswordReactiveOAuth2AuthorizedClientProvider — Не получает новый ключ доступа по истечении срока действия

#oauth-2.0

Вопрос:

Согласно приведенной ниже проблеме, упоминается, что PasswordReactiveOAuth2AuthorizedClientProvider автоматически получит новый ключ доступа по истечении срока действия, если мы не настроим refreshReactiveOAuth2AuthorizedClientProvider, но для меня это не работает. После истечения срока действия токена получение 401.my в первоначальном ответе есть refresh_token, но я понял, что он будет проигнорирован, если мы не вызовем use refresh_token в коде

https://github.com/spring-projects/spring-security/issues/9043

ниже приведен мой полный код

 import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.security.oauth2.client.AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizationContext;
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
import org.springframework.security.oauth2.client.PasswordReactiveOAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.endpoint.WebClientReactivePasswordTokenResponseClient;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.InMemoryReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.InMemoryReactiveOAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.transport.ProxyProvider;

@Configuration

public class Oauth2ClientConfigLocal {
  
    private static final Logger log = LoggerFactory.getLogger(Oauth2ClientConfigLocal.class);
    
    @Bean
    ReactiveClientRegistrationRepository getRegistration(
        @Value("${spring.security.oauth2.client.provider.test.token-uri}")
        final String tokenUri,
        @Value("${spring.security.oauth2.client.registration.test.client-id}")
        final String clientId,
        @Value("${spring.security.oauth2.client.registration.test.client-secret}")
        final String clientSecret
    ) {
        final ClientRegistration registration = ClientRegistration
                .withRegistrationId("test")
                .tokenUri(tokenUri)
                .clientId(clientId)
                .clientSecret(clientSecret)
                .authorizationGrantType(AuthorizationGrantType.PASSWORD)    
                
                .build();
        return new InMemoryReactiveClientRegistrationRepository(registration);
    }
    
   @Bean
   public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
           ReactiveClientRegistrationRepository clientRegistrationRepository,
           @Value("${spring.security.oauth2.client.registration.test.username}") final String username,
           @Value("${spring.security.oauth2.client.registration.test.password}") final String password
           ) {
       ReactiveOAuth2AuthorizedClientService authorizedClientService = new InMemoryReactiveOAuth2AuthorizedClientService(
            clientRegistrationRepository);
       
       return configureHttpProxy(
               new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                       clientRegistrationRepository,
                       authorizedClientService),
                       username,
                       password
                       
               );      
   }  
 

    @Bean
    WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager,
            @Value("${api-host") final String baseURL) {
      ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
      oauth2Client.setDefaultClientRegistrationId("test");  

      ReactorClientHttpConnector connector = new ReactorClientHttpConnector(proxyHttpClient());

      return WebClient.builder()
          .filter(oauth2Client)
          .baseUrl(api-host)
          .clientConnector(connector)
          .filter(logRequest())
          .filter(logResponse())
          .build();
    }
    
    public HttpClient proxyHttpClient() {

        return HttpClient.create()
               .proxy(proxy -> proxy
                          .type(ProxyProvider.Proxy.HTTP)
                          .host("cloudproxy.dhl.com")
                          .port(10123));
    }
    
    private AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager configureHttpProxy(AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager,
            String username,
            String password) {
        // set the webclient with proxy configuration in the ReactiveOAuth2AccessTokenResponseClient
        WebClientReactivePasswordTokenResponseClient tokenResponseClient = new WebClientReactivePasswordTokenResponseClient();
       
        tokenResponseClient.setWebClient(
                WebClient.builder()
                        .clientConnector(new ReactorClientHttpConnector(proxyHttpClient()))
                        .build()
        );

        // set the ReactiveOAuth2AccessTokenResponseClient with webclient configuration in the ReactiveOAuth2AuthorizedClientProvider
        PasswordReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new PasswordReactiveOAuth2AuthorizedClientProvider();
        authorizedClientProvider.setAccessTokenResponseClient(tokenResponseClient);
        


        // set the ReactiveOAuth2AuthorizedClientProvider in the ReactiveOAuth2AuthorizedClientManager
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
        authorizedClientManager.setContextAttributesMapper(contextAttributesMapper(username, password));

        return authorizedClientManager;
    }
    
     private Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>> contextAttributesMapper(final String username, final String password) {
         return authorizeRequest -> {
             final Map<String, Object> contextAttributes = new HashMap<>();
             contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
             contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
            
             return Mono.just(contextAttributes);
         };
     }
     
      private ExchangeFilterFunction logRequest() {
            return (clientRequest, next) -> {
                log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
                clientRequest.headers()
                        .forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
                return next.exchange(clientRequest);
            };
        }

        private ExchangeFilterFunction logResponse() {
            return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
                log.info("Response: {}", clientResponse.headers().asHttpHeaders().get("property-header"));
                return Mono.just(clientResponse);
            });}
    

}
 

Комментарии:

1. кажется, мне нужно настроить RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler..может у кого-нибудь есть примеры, как его настроить