I want to check if the backend is returning a error code `ERR_USER_NOT_AUTHORIZED' whenever any fetch request is sent, and logout the user from frontend if this occurs.
Basically I want to redirect user to login whenever the token is incorrect, expired, etc. One method is polling, I poll the server every x seconds and validate, but the time between polls is vulnerable and the user may see lots of errors.
P.S. I'm a newbie to React, I work mostly on Django, what I would prefer is something like #login_required decorator in Django.
You can handle this in two ways:
Every fetch would attach the authentication token in the fetch's header, and the backend would check if the token is valid. If not, the backend would send a 301 Redirect response to your fetch pointing to your login page
You can handle this in the frontend by wrapping all your fetch request routes in a method that, if the fetch fails with Unauthorised, would redirect the page to login
You can check the response.status on the back-end. It usually returns 401: not authorised.
Related
I have React signIn form and sessions mechanism implemented in NodeJs. In React I have protected routes only for authenticated users.
How should I check if user is authenticated. I have two ideas:
If user sign in for the fisrt time I can save this information in LocalStorage and then evrytime just check localStorage.
Send request to NodeJS server every time to check if user is authenticated.
Do you have any other ideas? Which solution should I pick?
I tried both options and second one is more UI unfriendly becasue I have to run loading state evrytime I am waiting for auth response. On the other hand, first option has also disadvantege, because I am based on token in LocalStorage which can be malicious.
Every time a request is made to an endpoint that requires authentication, the request should contain proof that they are who they claim to be.
The classic way to do this is by storing some sort of "Session ID" in a cookie or localStorage (client side), that you send along with every request.
Using a "Token" (e.g: JWT) instead of a "Session ID" is another popular way to handle authentication.
Check out this article for more information about both: https://dzone.com/articles/cookies-vs-tokens-the-definitive-guide
To return to your question, I'm not sure what you're worried about in regards to a "malicious Token in localStorage" (Or do you mean localStorage can be malicious?). But for a secure application you have to either:
Store something client-side
Require your user to provide credentials (username + password) for every request
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'm using the following combination of packages:
react
redux
react-cognito
react-router (v4)
redux-saga
(and I'll disclaim that I'm pretty new with all of these)
Currently I have a PrivateRoute component which will check (and refresh if necessary) an expired IdToken on route changes. This works well.
My problem is if the browser is open past token expiry to a PrivateRoute which is polling my API and sending along the IdToken in its 'Authorization' header. The API will start returning 401.
Options I've Thought of:
Act on API Error
I could catch the 401 error and dispatch an action to refresh the token, but
if there is any issue refreshing the token I wind up in an infinite loop hammering AWS, so need some logic to catch and prevent this. Perhaps redirect to login route if refresh fails?
I then need to add complexity to all my private API calls throughout my app to have this logic, and re-do the requested API call upon successful refresh.
Pre-empt API Error
To me it makes more sense to separate API calls and keeping the auth token valid. Considering react-cognito stores the token expiry time in cognito.user.signInUserSession.idToken.payload.exp, maybe it is possible to pre-empt the API call and expiry.
How to best do this though? At login a refresh action could be 'scheduled' using setTimeout for (currentTime - expiryTime - someBuffer) seconds in the future.
I'm assuming (haven't verified) AWS will let you refresh an IdToken before it expires. I don't want to wait until afterwards else some API calls may have already failed.
are there concerns with using setTimeout with a timeout that may be up to 1 hour long?
Alternatively I could set something up to poll cognito.user.signInUserSession.idToken.payload.exp frequently to detect and refresh an almost-expired token?
Any suggestions?
So this is my structure:
HTML form sends authentication to nodejs.
Authenticate using passportjs > res.send the userid with jwt-simple (json web token).
The received info is saved in $localStorage.user. I use that info in any of the controllers needed and include it and send my post/get requests to nodejs.
I decode the info in nodejs and query the DB.
Is this safe? Is this how it works in real world?
Many thanks.
#Somename:
The workflow which you have mentioned is slightly correct.
The ideal way to get passport authentication done is,
User log's in entering his username and passport.
Send a post request with these form data.
Authenticate the credentials using Passport. Using the passport.authenticate will invoke the serializeUser and get you the valid user if it exists. Else we return a login error response.
A Successful login will automatically create a session in back end, save it in the sessionStorage and adds it with the response.
This cookie will be saved automatically into browser's local storage once the response is fetched at client side.
Every time we send a subsequent API request we need to include this cookie in the req headers.
This cookie should be validated each time in back end. passport.authorize will again make use of the cookie and check if the session is valid.
Logout session once the User logs out.
Hope I've made things clear for you.
Some newbie questions of how to handle unauthorisedin redux and redux-observable
I have an application where user must be authenticated in order make requests to an api.
If user provides token that is invalid, endpoint returns 401 http error code.
So how do I elegantly handle this (i'm using fetch)?
Option 1:
create some kind of function with which I would wrap all api calls in epics which would convert 401 responses to something like NotLoggedInAction
create a reducer that handles NotLoggedInAction and sets flag on the state that user is not logged in
subscribe to state changes in root component (?) and check for not logged in flag
if not logged in flag arrives, redirect user to login page (login page is external app, so i would just use window.location.href ?)
This option is kind of flexible, because before redirecting i can show some popup like "hey your session expired, etc."
But it is also not error prone (I have to always hook up error handling to each call, and add dependency in each epic to NotLoggedInAction)
Option 2:
- in combineEpics use do and watch for errors
- if 401 arrives, simply redirect user to login page (via same window.location.href
This Looks much simpler to me, but this is more like a 'hack`?
Am I going the right way? Are the better options?