JAX RS Best practices for bearer token management on client side - java

I have a client app using jax-rs Client and making REST calls to bunch of services. One of those services uses bearer token authorization, and after first hard authentication (BASIC) lends a json with an access token, expiry delay, token type etc...
{
"access_token": "hashed_value",
"token_type": "bearer",
"expires_in": 1800 }
I wish to know what would be the best practices for managing this token for replay. Would it be via a global structure like a Map in memory that I would access at each request and update when token comes to expiration ? an other structure ?
To get a new token after expiration, would it be better to manage it requesting a new token based on a 401 status code ? or by requesting it automatically 1 minute or so before the 1800 seconds passes ?

Related

How to refreseh keycloak user token from the refresh token in java

Due to the architecture of our product, the loadbalancer that I use is not able to manage correctly my servers. To solve this point, I have create a kind of manager which forward the call to the correct server by requesting it directly from the first server when it is needed. The issue is to do that I forward the user keycloak token string in the header of the second call. It works pretty well but after few minutes to token is invalidate. I tried to refresh it by many way without success. I have 2 constraints. I can't reask the credentials to the user, and I can't use the keycloak secret because I'm working in a multi tenant / multi realm app. Do you have any idea?
I'm assuming that you have just the access_token on login.
First you need to exchange that access token for a refresh token (and another access token), you do this by calling:
HTTP POST {{host}}/auth/realms/{{realm}}/protocol/openid-connect/token
HEADERS:
Content-Type: application/x-www-form-urlencoded
BODY:
grant_type: urn:ietf:params:oauth:grant-type:token-exchange
subject_token: the_user_access_token
client_id: your_client_id (in my case this is "public")
requested_token_type: urn:ietf:params:oauth:token-type:refresh_token
you will get back a response that looks like this:
{
"access_token": "access_token_value",
"expires_in": access_token_time_in_seconds,
"refresh_expires_in": refresh_token_time_in_seconds,
"refresh_token": "refresh_token_value",
"token_type": "bearer",
...
}
So with this you have what you need to actually refresh your token with the following request:
HTTP POST {{host}}/auth/realms/{{realm}}/protocol/openid-connect/token
HEADERS:
Content-Type: application/x-www-form-urlencoded
BODY:
grant_type: refresh_token
refresh_token: refresh_token_value
client_id: public
This will get you the following response:
{
"access_token": "access_token_value",
"expires_in": access_token_time_in_seconds,
"refresh_expires_in": refresh_token_time_in_seconds,
"refresh_token": "refresh_token_value",
"token_type": "bearer",
...
}
Now you can repeat step 3 and 4 up until the maximum session duration.

How to re generate access_token in Oauth2.0 with refresh_token

We are using Spring Cloud Netflix Zull as Gateway Application for our backend services. Front end is Angular. But we are testing endpoints in Postman only(Front end is under development). We have one module called LoginServiceModule and another is ZullServerModule. The LoginSericeModuke take username and password from front end and make call to the following oauth/token endpoint by including required headers and body.
http://localhost:XXXX/login
and response is
{
"access_token": "XXXXXXXXX",
"token_type": "bearer",
"refresh_token": "XXXXXXXXX",
"expires_in": 3600,
"scope": "read write",
"jti": "XXXXXXXXXXX"
}
and the ZullServerModule contains ZullServerConfiguration, Authorisation Server Configuration and Resource Server Configuration and etc...
The LoginModule internally calls oauth/token end point like this.
ResponseEntity<String> loginResponse = restTemplate.exchange("http://localhost:XXXX/oauth/token", HttpMethod.POST, entity, String.class);
and the response is ..
{
"access_token": "XXXXXXXXX",
"token_type": "bearer",
"refresh_token": "XXXXXXXXX",
"expires_in": 3600,
"scope": "read write",
"jti": "XXXXXXXXXXX"
}
we extract the access_token from the response and call following endpoint...
http://localhost:XXXX/ProjectName/api/endpointname?access_token={access_token}.
But when the access_token expires, and when i access the above backend service url, its saying
{
"error": "invalid_token",
"error_description": "Access token expired:XXXXXXXXXXXXXXX(access_token)"
}
I know its expired and tried regenerating access_token with help of refresh_token in terminal like this
curl clientID:clientSecret#localhost:XXXX/oauth/token -d grant_type=refresh_token -drefresh_token={refresh_token}
But i need to include this in our code and don't know where to place it.
After searching on net, i came across about ZullFilter. I tried all pre, route and post filters. For each request they are all executed (i.e all long as access_token not expired), but when token expires and if i test endpoint, none of the filters are executed and i am getting error response
{
"error": "invalid_token",
"error_description": "Access token expired: XXXXXXXXXX"
}
I have placed sysouts in run method of every filters. I don't know much about filterOrder also.
#Override
public Object run() throws ZuulException {
System.out.println("pre filter...");
RequestContext context =
RequestContext.getCurrentContext();
HttpServletResponse response = context.getResponse();
System.out.println(response.getStatus());
return null;
}
I want to control access_token generation with help of refresh_token. How could i code that whenever the access_token expires and if i access resources after expire,then i get to know that token expired and re generate access_token and call the previous call with new access_token.
Typically it is the client that is responsible for maintaining its own token and refreshing it when it is about to expire. Moving this logic into your Zuul layer seems like a really bad idea. Think about the implementation for a second, how would it work?
Once a client's token has expired, it would be calling your endpoints with a perpetually expired token that Zuul would have to try and refresh with every request. This would add a lot of overhead for each API call. You could possibly introduce some kind of hack where you always pass back a new token in a response header or something... but at this point you'd be violating the authorization flow of OAuth2.

Using docusign-java-client and ApiClient.configureJWTAuthorizationFlow how do I get the token expiration?

I am following the example for JWT Auth and getting a new token each time. I need to be able to request a new token only when the current one is about to expire. The examples do not show how to access this information and the methods exposed in the api do not seem to apply. Does anyone know how to use the api to get this or am I going to have to track it manually?
If you are using JWT then you will be getting response like below:
{
"access_token": "eyJ0eX...AnHDQ0bbA",
"token_type": "Bearer",
"expires_in": 3600
}
It returns expires_in value in seconds, this will help you in knowing when the token is about to expire, also you should know the expiry time because while creating JWT you would have populated exp claim attribute in JWT and this exp time is your token expiry time.

How to use token based authorization on REST?

So after reading lots about BasicAuth, OAuth, JWT... etc. i came up with this question.
I have a client where some ppl can log in (Authentication is done). When ppl want to do an api call they use the clients GUI and the client is sending some requests to the a webservice endpoint.
host/resources/{id}
//id=path, res=post
public Response updateResourceById(String id, Resource res) {
....
So a typical update call could be
POST host/resources/1234 -d={ some json for a resource }
Now i don't want every user to have all rights for every reosurce, so i would
need to add some info about the user who is doing a request.
For this i was thinking to use some JSON Token with some payload (or any user info at all). But i was wondering how to send this token correctly in a RESTful API.
My first idea would be to change the code to something like this:
//id=path, token=post
public Response updateResourceById(String id, Token token) {
...
The endpoint would not change only the POST data.
Would this be correct or are there other approaches?
Edit: Also possible would be sending the Token via HTTP Header.
Sending credentials in HTTP
In HTTP, the credentials should be sent in the standard HTTP Authorization header.
Have a look at the RFC 7235, the current reference for authentication in HTTP 1.1:
4.2. Authorization
The Authorization header field allows a user agent to authenticate
itself with an origin server -- usually, but not necessarily, after
receiving a 401 (Unauthorized) response. Its value consists of
credentials containing the authentication information of the user
agent for the realm of the resource being requested.
Authorization = credentials
[...]
Please note that the name of this HTTP header is unfortunate because it carries authentication data instead of authorization. Anyways, this is the standard header for sending credentials.
In a token based authentication, the tokens are credentials. In this approach, hard credentials such as username and password are exchanged for a token that is sent in each request to identify a user.
It never hurts to say that you should use HTTPS when sending sensitive data, such as credentials, over the wire. HTTPS will protect your application against the man-in-the-middle attack.
Reading the authentication token in JAX-RS
You can read the Authorization header in a JAX-RS application as following and then check if the token is valid:
#GET
public Response myMethod(#HeaderParam("Authorization") String token) {
...
}
However, a better approach would be using a ContainerRequestFilter, keeping your endpoints leans and focused on the business logic. For more information on token based authentication and on how to use a ContainerRequestFilter, have a look at this question.

Using Java and OAuth 2.0 how to maintain the session

How to maintain the session by using OAuth 2.0 ?
Like I logged into the Android application , now I want to make user logged in till the user dont logged out manually , so for each span of time and the request the token will change.
How should I handle the same in my Android Application ?
Can Anybody suggest ?
Thanks
Dhiraj
Store the expires_in field and refresh_token delivered along with the access_token, and the unix timestamp of when the token was delivered in somewhere like SharedPreferences.
The next time you need to use something that requires authentication, double check the current unix timestamp with the unix timestamp delivered when you obtained the original access token + the expires_in*1000.
If the current timestamp is greater than the sum of those two, your access_token is expired, and you need to send a request to the authentication service for a new token, using the renewal_token, client_id, and client_secret to the OAuth endpoint.
You can also use this url: https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=your_access_token and get json response like below for valid token:
{
"audience":"8819981768.apps.googleusercontent.com",
"user_id":"123456789",
"scope":"profile email",
"expires_in":436
}
and for invalid token:
{"error":"invalid_token"}
For more information, check this link: Using OAuth 2.0 for Client-side Applications, there is a heading Validating the Token that explains this procedure.
OAuth has no concept of a session. Each REST request needs a valid access token in the Authorization header. Any "session" you want to implement is your responsibility. Any access token you acquire will TYPICALLY (not necessarily) last for 1 hour, but that is NOT the same as a session.

Categories