React.Js is a single-page dynamic web application with many small and reusable components. It enriches developers to be more flexible because it has an extensive JSX library and other valuable libraries. Since it is a single-page application, it is cumbersome to manage the login (authenticated user) or logout states across the application’s multiple components using prop chains alone. That is why we need authentication for protected content.
One way to solve this problem is using a single context provider that maintains all the authorization states and is wrapped around the main app component.
In the image above, you will observe the app is directly connected to the ‘Context’ tab to maintain an app-wide state. This means any sub-component of the app can access the state/data.
First, we need to send the request to the server with credentials, and we get a binary response of yes/no, which is not enough because a simple yes/no can be manipulated easily. Therefore, the response we get from the server must be more than just a boolean. To do this, we can follow two methods;
Server-side Sessions: When the user is authenticated, the server generates and stores a unique identifier for this specific user. The user gets this identifier in the response. So, for every new request sent by the user, the server recognizes the identifier and authorizes the request.
Authentication Tokens: It’s the same as the server-side session with only one key difference. The server generates the unique token and hashes it with the key, which is only known by the server, and sends back that token if the user is identified. That token can be used for further requests. For this blog, however, I will choose this approach as we advance.
The below file ‘auth-context.js’ is the context provider used to maintain the app-wide login state(isLoggedIn), token, and login/logout handler. Apart from that, the token and expiration time is stored in the browser’s local storage to keep the user logged in if they accidentally press back or close the window. The user will get logged out if they pass the expiration time.
Wrapping this context provider around the app component helps manage states app-wide. The <BrowserRouter> tag is used and implemented using HTML5 history API to keep UI in sync with the URL.
The login state can be accessed by importing the ‘useContex’ hook. Here ‘authCtx’ is a structure that contains the token, login state, login handler, and logout hander (defined in the auth-context.js file). Based on the router path and login state, relevant components are rendered.
On submitting the below code, the request is sent to the server with user credentials and you can observe the ‘returnSecureToken’ is set to true, in order to get the token in response for authorized users. This must always be set to ‘true’. On success, the token and the expiration time are sent to the login handler of the context provider to keep the user logged in and the page navigates to the user profile since this blog is more concentrated on authentication and app-wide state management. To log out, all we need to do is set the ‘isLoggedin’ state to false and the token to null.
Similarly, we can maintain the states across the components of the app using the context provider. Context providers can be used for small/medium applications. For a large real-time project it’s better to use Redux. The complete React code above is available at https://github.com/rakeshmd44/Auth
If you are interested in viewing similar articles, visit our blog, here.
View our LinkedIn, here.