Skip to content

Let AbstractTokensProducer.getTokens being overridden in AbstractOidcClientRequestReactiveFilter implementation #50844

@jdussouillez

Description

@jdussouillez

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().

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions