I am using Express for backend and passport-local for user authentication. The state has a user object with 'isAuthenticated' field to check if the user is authenticated. After the user clicks the login button, I dispatch login action, which sends a post request to the server that handles authentication logic and sets 'isAuthenticated' to true. If the user is logged in, react-redux-router dispatches 'push' to change the location.
None of this seems to work however. When I click the login button, the page simply reloads. I see the actions dispatched for a brief second from the logger middleware but the whole app just reloads. Is there a way to get this to work?
Also, I saw an example that uses server side render to save the state so that when the page refreshes, the 'isAuthenticated' still remains true. Is it possible to achieve the same without using this method or cookies? Would there be a way to get the 'req.isAuthenticated' to the client side similar the how templating engines pass objects from the server side to the client side?
Edit: So passport.js works fine on chrome apparently not Safari but I am still wondering what would be the best way to deal with the second question.
Related
I am working on a dashboard where when user login, I make a request to an API to confirm the log in details and then I save the response to localStorage(to be able to persist users) and at the same time I have an AuthContext which I also set to the response. After this is done, the user sees the dashboard main page first and the data here is gotten from the useContext Api, instead of me making another api call ....my problem is this works fine when user logs in, but when user reloads, the app breaks because it sees the context value as null...which is the default......Also, if I try getting the data directly from localStorage, it works fine
I have an application that uses express.js as the server side language and React on the front-end. I use passport.js to authenticate routes in the server, using local login and facebook strategies (no JWT). I use express-session to manage the session, which seems straight forward ( or insufficient, which I do not know yet, for my case, as its work in progress ).
My requirement is to hide/show few links in the Header component.
i.e.,
Log In
Sign Up
should show up in index page, when user has not logged in, but hidden when he is logged in. Likewise, few links should be hidden when the user is not yet logged in.
What is the best wat to check this from the client? Making an AJAX call is not ideal, as I may have more use cases of checking if the user session is valid from the client.
I can see the default connect.sid cookie, which the express creates, but how do I make use of it, or is there a best way for the client to know that the user is already logged in.
You have a couple options. Here are some:
You can check for the presence of a different cookie in the browser, and use that as your metric for whether or not you are "logged in". Your browser won't know if the session has expired server side, so you still have to account for the fact that you may be logged out and not know it. Additionally, you have to be sure to clear this cookie when logging out and set it when logging in.
When starting, your browser can make a AJAX request to get the currently logged in user. This might be useful for all sorts of things, such as displaying the user's name when logged in. You really only need to do this once (on page load and on login), then keep track of the user's login state stored in memory. You mentioned you don't want to do this, but it is fairly common.
When loading the page, you can inject the user into the page. For example, when the page loads there will be a <script> tag containing window.currentUser = null or an object representing the user. You can use this to "bootstrap" the login state without needing an AJAX request.
To clarify, you can't use the connect.sid cookie by itself because this cookie is just the ID of the session, not the session data itself. Only the server knows the session data that's being stored for that user, not the client. You need some way aside from this cookie for the server to tell the client that it's logged in, and the client to keep track of that state.
If you want the client to know from the ID component itself, you'll want to look at token options like JWTs.
I just finished my session (cookie) based login system in my React+Redux app.
Then I realized that there is no way how I can check if the user logged out from another location (different chrome tab, removing the cookie, server session invalidation, expiration).
I was looking on Instagram's website what using React too. It seems if you log out in a different browser tab, you can still route to another place in-app until u hit some API fetching... Then website is automatically refreshed...
BUT, there is also some kind of system what realize that user is unlogged even when I do some actions whatnot require API calls.
So how to realize these situations in the best way? How do you handle them when developing.
I'm not exactly sure how Instagrams Authentication works but I'd imagine that it's handled by middleware and when you request an API call, it will check to see if the user has an Auth Token stored in Cookies or whatever before initiating the API Request.
You can easily do this yourself by adding a Redux middleware that checks to see if the cookie is there before dispatching the next action. If it's not there you can return an error message to the user or redirect them or even dispatch a redux action that clears out all loaded data and then finally redirect them back to the login page.
The reason why Instagram is only locking the user when it hits an API call is that you can't really do anything dangerous to the users account if the cookie was deleted as you can't make changes to their account (commenting, posting, changing account settings etc.) without interacting with the API. Therefore, the middleware doesn't have to run every time an action has been dispatched which technically makes their application more performant.
Example Redux middleware
import Cookies from 'js-cookie';
const clientHasToken = store => next => action => {
const authToken = Cookies.get('auth');
if (!authToken) {
// redirects user, but you could do anything here
return window.location.href = '/login';
}
// if user has an auth token, proceed to the next action
next(action);
};
export default clientHasToken;
I've got a React app built using react-boilerplate, and I'm unsure of the best way to deal with authentication. Here's my questions:
If a user authenticates, their token is stored in localStorage. If they leave the app and come back, state is cleared, so I'll have to grab their profile picture and such again, as well as check expiration/validity of their token by pinging the server. Where do I do this? Doesn't make sense to add this to EVERY route's onEnter function.
On each subsequent route change, data will obviously be fetched from the server. Each piece of loaded data on the page (maybe it's graphs, products, account info, whatever) will authorize the user since the token is sent in the header of each request. If one or all of the routes come back as unauthorized, do I redirect them? Make the whole page render an error? Just show an unauthorized error on the one/many sections that were unauthorized?? Not sure how this works.
I have a mobile website written in angularjs, with my backend in Spring Boot. Right now, I have my own login page and can login a user without any trouble. However, if the user ever clicks "back", "refresh", etc., the client loses the user's id and login info (obtained from server on login). I need to make sure that this info is maintained and clicking "back" or "refresh" doesn't break everything.
Secondly, a user that knows the url's after login can type those url's in the browser and access them without logging in. I can stop them accessing anything on the server, but not sure what I can do on the client to redirect them to a login page in this case.
Any help would be greatly appreciated!
You should keep in mind that everything running in browser is stateless, there's no way to keep trace of the previous state.
Right now, if the user performs a refresh (or another similar action), Angular loses everything (AuthData included).
You have many way to work around that limit:
Perform an http request after the application bootstrap (have a look at the angular.module().run method
Save a cookie and use the server to print initial data layer directly on the dom via json
Save on local/session storage
Personally, I prefer cookies because that lets the server to work decoupled from the client.
In reference to your comment..."if the user ever clicks "back", "refresh", etc., the client loses the user's id and login info (obtained from server on login)."
Is there any reason you need to maintain the user id or login info after a successful authentication?
If Spring Security is setup for basic authentication, after a successful login, a Session Cookie will be sent back on the response to the client. On all subsequent requests to the server, the same Session Cookie will be sent on the request and the previously authenticated session will be re-established. You just need to ensure that your Angular client is passing cookies when issuing requests.
Take a look at this sample on how this is done.