1

I have a service which exposes a number of Jax-RS interfaces for its services. I now want to use those interfaces to connect with the services. I am using Quarkus, which means I am using the microprofile rest client. Because I already have the JaxRS interface, using the @RegisterRestClient method is not really viable. Instead I am using the RestClientBuilder.

    MyService client = RestClientBuilder.newBuilder()
        .baseUri(URI.create("https://localhost:8080"))
        .build(MyService.class);

The problem I am running into is authentication. The services i need to reach are locked behind basic Auth. All the guides I have found for the microprofile REST client are variations of this where the solution is to add a headerparam. This is not possible however, because I already have the interface premade, and copy-pasting the entire thing to add a header parameter is really something i would rather avoid.

It should also be mentioned that i have tried a @Provider filter to set the headers, but I can't seem to figure out how to only target a single REST client using that method, and I have several.

So: How do i set up basic authentication without messing with the Jax-Rs interface itself, using the microprofile rest client?

Martin Nielsen
  • 1,865
  • 6
  • 30
  • 54
  • I *think* you can add your provider to that client only by registering it manually. The `RestClientBuilder` implements `Configurable`, you can use an appropriate `register` method. On the other hand, authentication through HTTP headers *IS* a part of your contract, just like query params would be. I think it would be appropriate to add this annotation to the original JAX-RS interface, if you have access to modify it. – Nikos Paraskevopoulos Jun 23 '21 at 14:22

2 Answers2

6

You should be able to use the @ClientHeaderParam annotation on MyService. Something like:

@Path("/my")
@ClientHeaderParam(name = "Authorization", value = "{lookupAuth}")
public interface MyService {

  default String lookupAuth() {
    return "Basic " + 
         Base64.getEncoder().encodeToString("someuser:somepass".getBytes());
  }
}

See this for more details

If modifying the interface is not possible, you have two options:

  • Create an interface that extends the one you use with this annotation:
@ClientHeaderParam(name = "Authorization", value = "{lookupAuth}")
public interface MyServiceWrapper extends MyService {
  default String lookupAuth() {
    return "Basic " + Base64.getEncoder().encodeToString("someuser:somepass".getBytes());
  }
}
  • Create a ClientRequestFilter that fills the Authorization header:
@Priority(Priorities.AUTHENTICATION)
public class BasicRequestFilter implements ClientRequestFilter {
    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, getAccessToken());
    }

    private String getAccessToken() {
        return "Basic " + Base64.getEncoder().encodeToString("someuser:somepass".getBytes());
    }
}

And register the filter, e.g. programmatically:

MyService client = RestClientBuilder.newBuilder()
    .register(BasicRequestFilter.class)
    .baseUri(URI.create("https://localhost:8080"))
    .build(MyService.class);
ZygD
  • 22,092
  • 39
  • 79
  • 102
geoand
  • 60,071
  • 24
  • 172
  • 190
1

You can register a per-instance org.jboss.resteasy.client.jaxrs.internal.BasicAuthentication (or you can write a similar component) and register it using RestClientBuilder.

Luca Basso Ricci
  • 17,829
  • 2
  • 47
  • 69