Oauth2. Asynchronous refresh_token calls - reactjs

We have a client which communicates with a server secured by OAuth2.
As implementing tokens flow we have faced a problem. When page loads, there are few components that make calls to different secured endpoints.
There is a situation when access token is expired so all requests get error and try to refresh it. So we have few asynchronous requests.
Is there an approach to deal with such situation?
Our client is written on React JS.

There are a number of solutions to this.
One solution would be to create something like a TokenService.
Before you fire any http call, you work with this service and check if you have a valid token. This is easy since when you create the token you get back information on how long the token is valid for. You store that somewhere and before you fire a call you check if you are still in the validity window. If you are then you fire the http call, if you are not then you request another and update the stored one with the new one. Once this is done then you fire your http call with the valid token.
If you don't want to manage this complexity then you could simply request a new token for every request and you're done. You use each token for one call and that's it really.
You could also use the refresh tokens functionality if you have that implemented, so if your token expires, you simply refresh it and move on

Related

Handle refresh token and failed requests retry when access token expires in redux-saga

I am trying to implement an OAuth authentication mechanism with refresh token and access token. I have searched for the solution a lot. But, still I haven't find any comprehensive solution that works for me.
I have different watchers for different actions. The main problem is when the access token expires. I want to have a solution for refreshing the token and more importantly re-try failed request with 401 code. What is the best solution for my case? I don't want to miss any failed request and want to retry them all.
I got that I should handle it in axios level. Saga waits for the request to be resolved and there is no need to be aware what happens in request level.

Best practices for refreshing JWT in SPA?

Hi I'm developing a React app that communicates with an Express API. I'm trying to implement JWT authentication but I don't know what should happen when the jwt expires. It not seems very user friendly if the user is logged out when the token expires.
Should I use refresh tokens? As it says in the node-jsonwebtoken package documentation (jsonwebtoken). This may not be the best approach.
Should I create a new jwt in every request to the server? If the user reads an article for a long time without doing any request, he is going to be logged out.
Maybe I'm wrong and the best practice is using a big expiration time and let the user be logged out. If this is the case what would be a reasonable time?
Thanks!
A pattern commonly used along with refresh tokens is to follow a workflow along the lines of:
Some API call / resource returns with a 401, alerting that the token has expired, this sometimes is accompanied by a reason, e.g. Expired token, invalid token
Create a reference to the API call that failed, to retry later
Attempt to refresh the token with the refresh_token
If the refresh works, go ahead and perform the queued API call again
If the refresh fails, the user will need to log in again
You can also use the above approach to queue multiple failed requests, in the event that multiple calls fails whilst a refresh is taking place.
Coupled with a decent expiry time, which really depends on your application, this has proven to be a robust solution in the past for me.
An alternative approach would be to implement a 'heartbeat' API call that updates the user's token periodically whilst they are on the site, however this may come with side effects that may not be desired.

Best Way For Token Validation in Angular

In a WebApp development with AngularJS which uses token validation for authentication purposes, what's the best way to do this validation? For example:
Validate the Token every time I have a route transition. For this I have to make a rest call for everytime I want to validate.
Validate the token just one time, with one rest call, and then store the token in local storage. (The token itself just have a boolean telling if it is authenticated or not)
My concern is to not make a rest call in every route transaction, I don't want to consume that much of http traffic. But, if there isn't another way, I will do that.
If we look into what a JSON Web Token (JWT) is (although you're not specifically referring to JWT, but simply to "token"), you will realize that once you got a JWT you do not need to validate it every time you make a transition in the client app (Angular). This is because JWT are usually signed, so the server can be sure the senders (in this case the Angular app) are who they say they are when they make a request.
What you need to do is to send the JWT on every request in a header to the API server every time you try to consume a resource. The server is in charge of checking that you are sending a valid JWT and to assign the proper permissions to that request in order to get access to the resources.
Concluding (and answering your questions)
1.Validate the Token every time I have a route transition. For this I
have to make a rest call for every time I want to validate.
No, this is useless, since the given token is already signed by the server. If the token is manipulated in the client in any way the resource server will know it and will answer with the proper HTTP Status Code (usually a 401 HTTP Status).
What you can do is, in case the server respond with a 401, you can use a Refresh Token (if the server provides it) in order to get a new access token and use it again on every request. This way the final user will never know what's going on behind scenes (and won't see a login form again) because you won't ask him/her again about the username and password.
2.Validate the token just one time, with one rest call, and then store the token in local storage. (The token itself just have a boolean
telling if it is authenticated or not)
This is a correct approach (and used by most people), this way you do not overload the traffic with unnecessary requests. Actually, when you get the access token, you do not need to validate it because as I said before the token itself is Self-contained (it contains all the required information about the user and other necessary data the token provider considers important).
If I were you I would read a lot about this since there is much more to get to know than what any answerer can put together in a single answer here on SO (I put some links to sources I've used and which describe pretty well these topics).
Bear in mind that all theses behaviors can be modified according to your needs and not all of them have to be the way I just described. I just put some examples of how it could be.
The image below will give you a big picture about all these matters I just described.

Resend REST Call in Restangular after JWT Refresh

I am currently working on a web application that uses a JWT for authentication on all REST calls. The problem we are having is when a customer is performing an action needing a REST call and the JWT is expired, for whatever reason. At that point it kicks back a 401 response, as it should.
The functionality I am looking for is some way to intercept the 401 error, refresh the JWT, and retry the request without sending errors to the user.
The application runs on AngularJS and uses Restangular to handle all of the rest calls. So far I have been looking closely at the setErrorInterceptor as outlined here and at the Restangular documentation. Using a version of that posted code, I could successfully resend the request and in the .then() portion I had a successful response. However, it seems from the documentation that this method can only return false or true, so I couldn't get at it.
At the moment we have a timer that basically compares the jwt expiration time to the current system time and refreshes the jwt when there are 60 seconds left before expiration. This caused issues when the user's system clock was off compared to the server clock, resulting in a token not being refreshed because the application thought there was more time.
A solution to that specifically would be something like getting the system time, comparing to server time and creating an offset variable, but that doesn't cover all the bases for things that could go wrong. On another topic, checking the JWT before every request is not feasible.
Is there a way within Restangular's interceptors to accomplish the error interception and resending? If not, are there ways outside of it?

Refreshing JWT in Express.js

I'm using JWT for authentication in my Angular.js application, with Express.js on the server side.
Basically, when user logs in, a new token is created (using https://github.com/auth0/node-jsonwebtoken) and send back to the client. If token is valid also on the client side (angular.js part, using https://github.com/auth0/angular-jwt), a new user is created and the token gets stored in a cookie.
So, each request to certain path on the server is protected by a token validation. However, my token has an expiration time. Now let's say for the sake of argument that expiration time is 30 seconds; user can actively use my application for 30 seconds and after that, he gets logged out. That's not exactly user friendly.
So what I did was that with each request to the server, I create a NEW token and send it back in the head of response. When I receive the response in my Angular.js client-side, I read the token and overwrite the token in the cookie. That way, as long as client is active (or rather, makes requests to the server side), the token gets refreshed.
Now I'd like to know the following:
Is such an approach correct? The downside is, that token gets created at each request and send back in each head of response. Cookies get overwritten quite often (performance issues?)
What would be the correct approach?
Is it OK that the token expires if there are no requests to the server? Client might still be using the application, however, if he's only writing on client side something (or reading), the token does not get refreshed.
Thanks for your time and responses!
Yes, that is a valid approach. It is the same approach many take,
including the popular Angular module ng-token-auth. You might
consider saving the tokens to local storage, with a fall back to
cookie storage if the browser doesn't support it (see
http://caniuse.com/#feat=namevalue-storage for coverage).
I would do what you describe.
One solution is to use $interval to basically ping the API. All you need to do is send in a token a get a new one back (i.e., in headers like you are now). Keep track of how many "pings" you've sent. You can reset the number of "pings" upon certain actions like on ui-router's $stateChangeSuccess (i.e., navigating to a new view) or anything you like, including submitting a form or other non-ping requests. When the number of "pings" reaches your threshold, warn the user that their session is expiring, and after a delay, erase the stored token and log them out. Check your ping responses for authentication errors from the API, indicating that the user might need to be logged out and/or redirected.
Perhaps you just gave 30 seconds as an example token lifespan. I would recommend getting closer to the browsing session timeout that you want. As points of reference, consider that the Ruby gem devise_token_auth defaults to 2 weeks and that .NET defaults to 10 hours. Your needs may vary.
The problem is also addressed by using refresh tokens. Your access token has a short life and is verified by signature. The refresh token has a longer life and is used to get new access tokens.
When the refresh token is used to get a new access token, that is a good time to do extra checks: has the refresh token been revoked? Is this user account still valid?
Both tokens can be stored in secure cookies and supplied on every request. Doing this allows your server to transparently use the refresh token when needed and set new access tokens in cookie responses.
This is the approach we've taken for Express-Stormpath and is documented in our Authentication section of the documentation. If you'd like to offload your authentication layer, I'd suggest Stormpath. (Disclaimer: I work there, and wrote that module).

Resources