Home > Software engineering >  How to handle token refreshing in Spring Webflux WebClient
How to handle token refreshing in Spring Webflux WebClient

Time:03-26

I want to create some authentication service to be used for WebClient, so it automatically refresh the token when needed:

@Service
public class AuthService {

    private String token;

    private final WebClient webClient;

    private final Map<String, String> bodyValues;

    @Autowired
    public AuthService(WebClient webClient) {
        this.webClient = webClient;
        this.bodyValues = new HashMap<>();
        this.bodyValues.put("user", "myUser");
        this.bodyValues.put("password", "somePassword");
    }

    public String getToken() {
        if (this.token == null || this.isExpired(this.token) {
            this.refreshToken();
        } 
        return this.token;
    }


    private void refreshToken() {
        this.token = webClient.post()
                .uri("authEndpointPath")
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(bodyValues))
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }

    private boolean isExpired() {
        //implementation
    }
}

It gets the token correctly when it is expired. Is there a way to use it ONLY ONCE, without injecting it to other services? I was thinking about defining the Bean which uses authService.getToken() method:

@Configuration
public class CustomWebClientConfig {

    private final AuthService authService;

    @Autowired
    public CustomWebClientConfig(AuthService authService) {
        this.authService = authService;
    }  
  
    @Bean("myCustomWebClient")
    WebClient webClient() {
        return WebClient.builder()
                .defaultHeader("Access-Token", authService.getToken())
                .build()
    }
}

But obviously it will get the token only once at Application startup. Is there a way to inject it somehow or to intercept all of the webclient request and add the token then?

CodePudding user response:

You can declare a custom WebClient with filter that is applied on each request.

@Configuration
public class CustomWebClientConfig {

    private final AuthService authService;

    @Autowired
    public CustomWebClientConfig(AuthService authService) {
        this.authService = authService;
    }  
  
    @Bean("myCustomWebClient")
    WebClient webClient() {
        return WebClient.builder()
                .filter(ExchangeFilterFunction.ofRequestProcessor(
                    (ClientRequest request) -> Mono.just(
                        ClientRequest.from(request)
                            .header("Access-Token", authService.getToken())
                            .build()
                    )
                ))
                .build();
    }
}
  • Related