So I have a React app where it has an App component. Inside this app component, I'm reaching out to the server to check the user's auth status. Now I only want to check this one time when the app is opened for the first time.
I'm also using react-router-dom for routing. Now the problem is when I enter a path manually in the address bar it renders my App component again. The same doesn't happen when I navigate with the Link component of react-router-dom. Because of this behaviour, my auth status sets to false (it is default to false in App) even when the user is logged in. Then it again reaches to the server, and then sets the auth status to true again. How can I fix this so that the app component doesn't re-render and I don't see that login screen even for a while when I'm logged in when entering paths manually?
First query the localstorage for Auth Status and if it returns fail, Query with api call and add Auth Status to localStorage and proceed further. asat!
You may suspect of what would happen if user manually update the local storage. Since if you send the auth tokens on every api. No need to worry about that.
Have a great day :)
Related
I am using reactjs+redux with firebase. I am calling a method signInWithRedirect for social providers authentication. Here after calling the method user is redirected to social auth page and then redirected back to my application. To get the authentication result firebase docs says that use getRedirectResult. I am using it but the problem is getRedirectResult gets called after few seconds and I would like to show some loader till it is called.
I am able to show loader by storing a flag in localstorage. Till here everything works fine, but when I close the window while user is redirecting to the social auth page the flag is set to true and when I open my application again instead of my login page I see loader, as there is no way for my application to know which state it is in, called from getRedirectResult or fresh load.
You can use sessionStorage instead of localStorage. It will only persist in the current window and will be cleared when the tab is closed.
I've been debugging this for hours, and can't seem to find the solution.
For some reason, after using RouteActions to switch between scenes, a function from one of the previous scenes triggers and redirects the user.
The culprit seems to be a landing page screen that onComponentDidMount reads authentication tokens from AsyncStorage. Once that is said and done, the user will be redirected to the main screen (assuming credentials are valid). The authKey is stored in the local state
this.setState({'access_token':keyValues.access_token});
The reason I do this is so that I don't have to read the authKeys from AsyncStorage all the time. Anyways, that works all fine, and the user is directed through the app. Now two screens further down in the application, the user state is updated again, and because I added some console.log() statements, I can see that MapStateToProps in the authentication screen is being executed again, as well as a routing action that exists in the render() function of the authentication screen.
Do I need to remove the authentication screen from the stack? How do I prevent the state from updating (and calling ComponentDidMount) on a scene other than the one that is currently active?
Figured out the issue: I was calling the RouteActions (using react-router-flux) within a conditional statement in the render() function of the auth screen. The authscreen stays on the scene stack when I navigate away from it, so the render function is called, even when the scene is not visible.
As a result, when the other screen fetched the auth token and updates the redux state (which was also connected to the auth screen), the RouteAction triggers.
So the fix was actually quite trivial: I put the RouteAction that caused the redirect, along with the conditional to check for presence of the access token inside the componentDidMount() function.
When user navigation to app ex: http://myapp.mydomain.com
I initialize a bunch of stuff, make requests to auth the user based on a cookie etc. This setup the main state of my main-reducer.
If a user navigation directly by pasting let say: http://myapp.mydomain.com/userProfile
The main state, will never be setupped. So the trick I'm using is putting the last part of the url (userProfile) in a cookie (or somewhere else) and redirecting to http://myapp.mydomain.com. After auth and requests, I the redirect back to the page the user wants to view. This works, but feels wrong. I was wondering: is there a better way of doing that?
Thanks!
Why don't you just make the route /userProfile as protected route.
Only if the user is authenticated he can see that page if not redirect to root page and re-validate the user.
I'm working on building an authentication mechanism over graphql, and I'm trying to figure out why a graphql-connected component isn't rerendering after relogin... for example:
At /users I have a react-apollo graphql-connected Users component that requests a list of users.
The server will return an authentication error if no token is provided; the component renders a <Redirect> to the /login route; after successful login, the Login component stashes the token and redirects back.
The Users component wrapper starts the graphql request and renders "loading..." in the meantime. When the graphql request succeeds, it rerenders and the users appear, yay.
If you Sign Out from that page, the Logout component at /logout discards the token then redirects back; the Users component's request gets the authentication error again and sends you to '/login'.
After another successful login, you're sent back to '/users'; again it starts a graphql request to the server (and renders "loading..."), but this time, when the request succeeds, the component isn't updated again.
I can see that the graphql request succeeds (and have watched in Chrome's debugger as the APOLLO_QUERY_RESULT action is handled by react-apollo's reducer and updates the state in the store).
I've tried to find where React is checking to see if the component's props have changed, but I'm enough of a React debugging noob that I haven't figured out where to find that code in the web inspector: maybe something I don't understand about how React is packaged for distribution.
I clear out the ApolloClient's store (by calling resetStore()) on both login and logout, since I don't want to accidentally reuse data from the other authenticatedness; however, removing these calls doesn't get rid of the problem. Interestingly (?), if I force the connection to bypass the cache by providing { options: { fetchPolicy: 'network-only' } } in the graphql() call, the problem goes away. (Not a viable solution - I'd like to benefit from the cache generally.)
I've built a stripped-down example: https://github.com/bryanstearns/apollo-auth-experiment
and you can see it in a CodeSandbox: https://codesandbox.io/s/m4nlpp86j (you'll probably want to access the running example from an independent browser window at https://m4nlpp86j.codesandbox.io/ because the sandbox editor kinda makes the web debug extensions act weird).
To fix this behavior, modify your graphql HOC to include notifyOnNetworkStatusChange in the options.
export const Users = graphql(usersQuery, { options: { notifyOnNetworkStatusChange: true } })(RawUsers);
I don't think you should have to do that -- I think data.loading is supposed to accurately reflect the status of your query regardless of that option being set to true, unlike data.networkStatus but it looks like it's a known bug.
As far as resetStore -- it doesn't actually wipe your entire store, but rather wipes away your store and refetches all your active queries. If you wanted to blow away your store, since you're already integrating Redux with Apollo, the easiest thing to do would be to create an action to do that.
You may also want to consider a session-based authentication mechanism, rather than relying on the client to persist a token. It's pretty simple to implement server-side, would not only involve less work on the client-side (don't have to remember to pass the token in with every request), and would let you keep your user logged in after they navigate away from the page.
For example, if I have page called home.
When a user logs in, he will see his avatar on the navigation bar.
If a user does not log in, he can see a log in button on the navigation bar.
I use Redux to manage state, and React Router to do the routing.
My problem is, on the server side, how to know which view to render.
You can create sessions and maintain the state in react accordingly. For every page request you can check that if the sessionid is present in the request headers. Then check wether it is the correct session id on the server side and return true value or thatever you want to return. And then maintain the sate accordingly. Now as you have got the state so you can render whatever you want to render.