Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with rendering of Authenticated routes and Non authenticated routes #108

Open
NileshTops opened this issue Mar 13, 2020 · 1 comment

Comments

@NileshTops
Copy link

NileshTops commented Mar 13, 2020

Hi, Can you please tell me how can i implement Authenticated routes and Non authenticated routes with react-router in this repository?

@zorgick
Copy link

zorgick commented Mar 13, 2020

Hi! I was asking the same question a while ago. Despite the fact that @manuelbieh gave me a quick and detailed response #100 I did follow his advice, but modified it for my purposes.

So you don't want to render a cheap login page for an authenticated user to request later a heavy main page with all them fancy images, large bundles and texts, right?

There 2 main things in my solution that really helped me out, which are http-only cookies and separation of authentication and routing.

Firstly, usage of http-only cookie shifts the weight of storing a user ID in webstorage, accessing its value on the client, protecting it from CRSF and sending it with each request from your shoulders onto the browser's. Browser will send it every time he sees your origin in the URL.

Secondly, routing needs to do only one thing in your app, respond to the path change in the URL and bring a user to a necessary page, depending on the state of the app. So there is no need to create something similar to react-router's private routes, but the logic stays the same - there are public routes and there are private routes.

So, provided a browser is using a http-only cookie, you don't have to worry about the initial request to your server, which will be for index.html (I suppose any proxy server in your network allows the request to reach the node server, which will SSR your page into a html file). You will always receive information about the user, because browser will send a token - user ID preserved in browser's internals. You will either receive it - that tells you user is authenticated and it is ok to let him through or he needs to update his expired token, OR you will not (your server didn't previously set a unique ID for this user, or the user cleared his browser internal storage).

The solution is rather simple, the store must have information about the user before being created. Thus, you need to check for the presence of a cookie, its value (it can be expired) and initialise the store with some initial state of the app, let's say, "profileType" of the user, which can be 'authenticated', 'unauthenticated' or better an empty string '', 'expired' and so forth.

Going further, there are two basic scenarios - authenticated and not authenticated user. Both of them are allowed to access a requested URL, but what will be returned in response differs and depends on the "profileType" in the store.

What you need is a HOC (well, it is not a pure HOF, but let's call it HOC) for each container (except the one where routing happens - App.js) that will act like an interceptor in express.
My example looks like this (I can show you only its API):


/**
 * auth is a HOC that checks provided conditions on mount and on nextUpdate
 * It receives 3 function arguments
 * @param {function} meetCondition - verify user identity
 * @param {function}  damnGoBack - function that is called when the condition above is not met (it can be redirect to login page or any other page or just a notifier)
 * @param {function} whenToCheck - due to the fact that it is HOC, any props change is registered. So you can tune when you want meetCondition to be invoked. (used in CDM(), CDUP() etc)
 */
const withAuth = auth(
  ({profileType}) => profileType !== 'unauthenticated',
  ({some props you need}) => customFunction(with those props),
  (nextProps, props) => nextProps.profileType !== props.profileType
)

withAuth(YourContainer)

Before rendering a component provided for a certain route it will check for your provided condition to be met and either grant access to the container OR do whatever you want it to do, in your case redirect to the login page to let the user proceed with authentication process.

This HOC allows you to follow flux architecture (the View changes based on the changes in the global state) and react on API request interceptors that require token to let the request knock on your DB door. If server API interceptor returns 'expired' or 'unauthenticated' (logged out in another open tab), this HOC will know it first.

There is yet a lot to mention, but I hope you got my idea and wish you to solve your problem)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants