I have a React application and I'm using Axios to make http calls. Calls are authorized with an authorization header.
In Axios I'm using the response interceptor and in case I get a 401 from one of the calls I make another call to get a new token using a refresh token obtained upon login and stored in the browser, and then retry the original call using the new token. It works well.
The issue starts with the way it's handled in my application. I have pages where there are multiple components that request data from the server, at the same time. The page returns a 401 causing my logic to ask for a refresh token - so basically all requests are also asking for a new token using that refresh token. The issue is that the first request asking the new token is served while the others are failing - this is because when asking a new token using the refresh token a new refresh token it granted. Meanwhile the other calls for a new token all use an "old" refresh token that cannot be validated on the server side because it had been replaced on the first call - making the request fail.
Also in the above logic - the login is called more then it should - it should be called only once when the first call detects that it should.
What I'm looking for is a way that if the first call fails due to the need to refresh the token, how do I make the other calls understand that a call for a new token is already made and hang until it's returned (or retry with the newly stored token once it's available)?
Related
I am currently trying to design a new web-application for a rest-api service I have running. In basic I am trying to realize the login/logoff system. For authorization-management the API provides three endpoints:
/login, which takes username and password via a POST request and returns a token embedded in a json answer. This token is not a JWT, but its some arbitrary unique string. It is valid for X hours and everytime it used it is reset to be X hours valid again. The validity is check on the server in each request.
/logout, which makes the token invalid on the server.
/validate, which takes a token as json in POST request and checks if it is valid. If not it returns a 401.
Now I realized a login procedure following https://www.digitalocean.com/community/tutorials/how-to-add-login-authentication-to-react-applications . The application finally should used the react-router to provide the different pages. My problem is not how to integrate the validation of the token on each page change and if a 401 is returned, switch to the login page again.
PS: The server is written in C++ and accesses a custom database.
As Suggested By You That You Want To Integrate Validation, So You Need To Create A Component Over The Current Route Component.
It would serve as the private Route and as soon as you get a 401 Response From Your Server You Would Redirect To The Login Page By Updating the Token as empty depenedending upon the storage you are using i.e. session storage or localstorage.
This way whenever your token expires the next request responds with 401 and you are logged out.
Further I am Linking An Example Gist For Creating Private Routes And Logging Out
https://gist.github.com/EduVencovsky/f8f6c275f42f7352571c92a59309e31d
I am new to web dev. I built a backend using Django Rest Framework and am using JWT to handle auth.
Now, I want to connect my backend to my frontend in React. But, I am confused how this should be done. Here are my question:
What is the whole flow of requesting and using JWT access and refresh tokens? Like, when should I request a new access token with my refresh token and when should I request a new refresh token? Thanks!
I will make a quick response:
Flow of requesting and using JWT:
A picture worth a thousand words.
The access token is not lasting forever. Whenever it expires, you have to request a new access token with your refresh token.
Refresh tokens can expire, although their expiration time is usually much longer than access tokens. To handle this case, almost all implementations I've seen return a known error code of 'invalid_grant' that you can check for on the client-side and handle by your business. (ex: Show login page...)
Regarding your questions:
What is the whole flow of requesting and using JWT access and refresh tokens?
I don't know you're using what's package about JWT, having too many packages about Django JWT on github (pyjwt, djangorestframework_simplejwt, ...). And Im using pyjwt in my application, because I want to custom my authentication in-app for security.
The workflow:
When FE send request to login/signup APIs, BE generate a token by using JWT, and return that token in the response.
FE store that token on local storage, using it for sending other requests.
BE will take the token by each request from FE to verify. The same as TokenAuthentication of DRF, we must be custom it when using pyjwt. Will verify the JWT token instead.
when should I request a new access token with my refresh token and when should I request a new refresh token?
You can request a new access token after that token is expired.
When you're using djangorestframework_simplejwt you can see the refresh token but in my case (pyjwt), I just need re-generate jwt token again :)
There could be options, but simple flow is next:
You do auth and get access and refresh tokens from a backend and save them as cookies.
You use your access token until you get error 401 because access token has expired
Then you try to refresh your tokens using your refresh token. If you use axios on frontend, good option to write a middleware for this case. This middleware will refresh tokens and repeat a last request. There should be recipes in google.
If success you got new pair of access and refresh tokens and continue your workflow.
If fail, you need to auth again to get tokens.
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
Lets say I have a method called getUsers and an API Interceptor which handles my token refresh functionality.
Here is the scenario:
I send a GET request using getUsers to:
http://example.com/api/users
My token is expired so I get a 401 error
API Interceptor refreshes my token and calls the endpoint again:
response.config.headers.Authorization = "Bearer " + response.access_token;
$http(response.config);
It works fine, but how do I actually re-use my original method (getUsers) instead of just resending $http request because I need to modify some data on callback
What really worked in my case is actually intercepting requests, not responses. So basically I have a timestamp of my token creation in my local storage which I compare to current time every time I send an API request. If it's been longer than say 10 hours (insert your lifespan) I request a new token.
I am working on an AnjularJS project with Token authentication and Refresh token.
In some case when i am submit a form and make the api call, i get 401 in which the Token has expired and automatic refresh the token. Which works just fine.
The issue i am having is, after it refresh the token i want to automatic make the api call to resubmit the form.
Do i have to create a service to keep track of all calls? Does angular keep track of all calls?
Any ideas on how to do this.
Thanks
I used the following module that create a buffer of all the state and then i just have to recreate all the api call in the buffer.
I used https://github.com/witoldsz/angular-http-auth