-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Description
I'm trying to refactor some code to use custom filters using AbstractOidcClientRequestReactiveFilter and when I override getTokens(), it's not called because the filter implementation is calling super.getTokens(), so calling the method in parent class AbstractTokensProducer.
Would it be possible to change this so custom AbstractOidcClientRequestReactiveFilter can override getTokens() properly?
Note: if you have a better/more standard solution on how to do this in Quarkus OIDC clients, I'll be very happy to get a second opinion! Like maybe implement a custom OidcClient with inside the default OIDC client and then use the AbstractOidcClientRequestReactiveFilter without overriding anything but AbstractTokensProducer.client?
Use case:
I have to get an OIDC token to call an API, that gives another OIDC token.
I know it's weird, it was introduced more in details in this comment
What I have now:
I have a REST client taking @HeaderParam(HttpHeaders.AUTHORIZATION) String token parameter. My caller service has a piece of code to get a valid OIDC token from client (so very classic flow), then it calls another REST client to get the second token, and then it calls my REST client token in parameter.
What I'm trying to achieve:
For a while now, we're using @OidcClientFilter("xxx") for our REST clients (I have like 4 or 5 REST clients with specific OIDC client for each). And I wanted to unify this logic.
I can't do what I want with @OidcClientFilter but I was thinking of doing something like this:
// @OidcClientFilter("inventory-visibility") // Can't use this because of the token exchange
@RegisterProvider(InventoryVisibilityOidcClientFilter.class)
public interface InventoryVisibilityApiClient {
@POST
@Path("onhand/indexquery")
Uni<List<D365InventoryResponse>> getInventories(D365InventoryRequest request);
}
// ---
@Priority(Priorities.AUTHENTICATION)
public class InventoryVisibilityOidcClientFilter extends AbstractOidcClientRequestReactiveFilter {
@Inject
protected SecurityServiceApiClient client;
// This is the token of for inventory visibility
private volatile Tokens tokens;
@Override
public Uni<Tokens> getTokens() {
if (tokens != null && !tokens.isAccessTokenExpired() && !tokens.isAccessTokenWithinRefreshInterval()) {
return Uni.createFrom().item(tokens);
}
return refresh()
.invoke(t -> this.tokens = t);
}
@Override
protected Optional<String> clientId() {
return Optional.of("inventory-visibility");
}
private Uni<Tokens> refresh() {
// Get OIDC token for security service (it's regular Quarkus OIDC client)
return super.getTokens()
// Then use it to get an inventory service token
.map(securityServiceTokens -> new InventoryTokenRequest(...))
.chain(tokenReq -> client.getToken(tokenReq));
}
}The problem is, my custom OIDC client filter is created and called, but AbstractOidcClientRequestReactiveFilter.filter is not calling my implementation of getTokens, it calls the one from it's parent class AbstractTokensProducer.
Implementation ideas
In AbstractOidcClientRequestReactiveFilter.filter, call getTokens() instead of super.getTokens().