'Webclient - refresh API key on unauthorized

I'm looking for solution how to properly implement token refreshing mechanism. A token should be changed after we got 401, or 403 http status code from external API. I'd like to call login endpoint to obtain a valid token, save the token into database and try again with the new token.

Currently, I'm having problem with reactor and streams. Below are two methods that contains core functionality.

register method (external call)

public Mono<Void> register(UserConfiguration configuration) {
        return externalClient.post()
                             .uri("http://example.com")
                             .body(Mono.just(new SomeRequest()), SomeRequest.class)
                             .header(AUTHORIZATION_TOKEN_HEADER, token)
                             .exchangeToMono(clientResponse -> handleResponse(clientResponse, Void.class, configuration))
                             .retryWhen(Retry.max(5)
                                             .doBeforeRetry(retrySignal -> log.info("Unauthorized request"))
                                             .filter(UnauthorizedException.class::isInstance))
                             .then();
    }

handleResponse method

private <R> Mono<R> handleResponse(ClientResponse clientResponse, Class<R> clazz, Configuration configuration, ) {
        if (clientResponse.statusCode().equals(HttpStatus.OK)) {
            return clientResponse.bodyToMono(clazz);
        } else if (clientResponse.statusCode().equals(HttpStatus.FORBIDDEN) || clientResponse.statusCode().equals(HttpStatus.UNAUTHORIZED)) {
            return authenticationService.refreshToken(configuration).flatMap(conf -> Mono.error(new UnauthorizedException()));
        } else {
            return clientResponse.createException()
                                 .flatMap(Mono::error);
        }
    }

register is responsible for calling external API. handleResponse take care of handling response status, and when there is unauthorized response, the method invokes authenticationService in order to obtain a new token and save the token into db (UserConfiguration). Retry detects an exception instance and when there is problem with a token, it enforces the stream going again. Unfortunately, register method uses the same instance of UserConfiguration so values there are outdated as well as token is not valid anymore.

What would be the better approach? Now I can see the only workaround to start a stream from getting UserConfiguration, so on retry we will have the latest state of db. It seems to work, but it's not perfect from a performance view.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source