0

In my server application, I want to consume some third party API using a MicroProfile REST client. To do so, I need to send an Authorization Header with a bearer token.

I don't want to always get a token before I make any call so I need a mechanism to only retrieve a new token if there is no token yet or if the token expired. The token could then be stored and used in each call until it expires. The next call to the API which would cause a HTTP 401 Unauthorized shall then cause a new token to be obtained.

Unfortunately so far I wasn't able to find any resources on how to consume OAuth secured APIs using the MicroProfile REST client. I hope anybody can give me any tips. I'm using Kotlin and Quarkus but Java related documentation would be fine as well. Anything helps.

Here is my rather simple client:

@RegisterRestClient
@Produces(MediaType.APPLICATION_JSON)
interface SomeThirdPartyApiClient {
    @POST
    @Path("/some/random/url")
    fun someRandomUrl(body: SomeJsonRequestObject, @HeaderParam("Authorization") bearer: String): SomeJsonResponseObject
}
xxtesaxx
  • 6,175
  • 2
  • 31
  • 50
  • What you are doing is right for me. But I advise to do some common-code that do the token verification/refresh logic and use it. I know spring has something like OAuthRestClient, but actually, it is not that big deal and I believe it is easy to implement. – iabughosh Apr 02 '20 at 18:04
  • Any suggestion where to start? I was thinking about making the call and placing it in a try-catch. In the catch I would then check for 401 status and recursively call the function again after trying to get a new token. – xxtesaxx Apr 03 '20 at 10:10
  • You can use this or you can store tokens in an in-memory database. Whenever you are receiving an already existing token then you can check if token-expiry > current time, then you can hit refresh and store the updated token. – iabughosh Apr 03 '20 at 20:35
  • Hmm I wonder: In 99.9999...% of the time this could work well but if a call is made a few millis before the token expires it could fail, right?. But if I subtract the timeout time from the expiration time it should work I guess. Thank you for the idea. – xxtesaxx Apr 04 '20 at 21:06
  • Then in that case you can do a combination on my suggestion and yours to get the best :) – iabughosh Apr 05 '20 at 08:39

2 Answers2

0

As discussed with iabughosh, there seems to be no automatic way of doing what I want to do. Instead I have written the code myself as suggested by iabughosh. I went with the route of catching errors in the call. If the error has a 401 status, then I retrieve a new token and retry the call.

When the application starts and has no token yet, the first call always causes a 401 and then I get the first token. The next 401 appears only when the token expires (or was removed by a server admin prematurely) so then I simply get the token and do the call again.

As for now this seems to work just fine. I'll have to see how it turns out in production when there are a lot of (parallel) calls. If I find a better solution, I'll try to remember this question and update it accordingly.

xxtesaxx
  • 6,175
  • 2
  • 31
  • 50
0

There isn't any way to pass it at annotation level, through eclipse microprofile configuration, the only way to pass a dynamic token is by adding

@HeadParameter("Authorization") authString in your rest call, in case you are using jwt, usually you can inject the JsonWebToken and do all the checks with this object, so you wouldn't need that parameter, however, you can add it and just ignore, than in your rest client method declaration you have to add it too (as I seen your case you did it already, just assure the order of parameters is the same), and the restclient will be able to pass the token though the header (you need to pass "Bearer "+tokenString), but you need to access to the code of your rest service.