Last Updated On By Khizer Ali
Table of Contents
Login flow is the key to managing websites. To make sure, many users are logged in with their credentials registered in your website, most websites allow only to reveal their content until the user is logged in. This means redirecting the user back to the login page if they are not logged in or have logged out of the session.
Today, in this comprehensive post, we will inspect in detail how to use React routers to regulate the flow of login/logout through redirecting the pages.
First thing first, I have used express-js rest API for react in this demonstration.
A REST(Representational State Transfer) API proactively manages operability between the client request and the constraints set up then returns the appropriate HTTP response with the desired functionality.
The most pleasing thing about REST web services is that it is light weighted, embeddable, and consumable with other services.
Restful API services handle your intended application and promptly carry out the extensive operations of the client in a secure and stateless manner. Just how the name states, a transfer of a representation of a
state in a stateless manner.
Let’s get started!
In this code, note that two paths have been created.
The requisition “/login” discharges a function that listens to the requests incoming from the user through the post method. For the sake of the purpose, I have assumed the username and password.
The if condition checks the request for login, only to be fulfilled by the established criteria of that the req.body.username and req.body.password exists, and the provided username and password match the correct username and password.
If that’s the case then a token is being generated. This token is granted to the user that has requested to login.
app.post("/login", function(req, res) {
let username = "[email protected]";
let password = "12345678";
console.log(req.body);
if (
(req.body.username || req.body.password) &&
username === req.body.username &&
password === req.body.password
) {
console.log("Success");
let token = btoa(username + password);
return res.send({ token: token });
}
console.log("error");
return res.send(req.body);
});
Notice that the token is typically generated by concatenating the username and password then encoding it in base 64 with btoa() method. Through response, the token is sent to the client to resume his/her session.
However, if the username and password are not a match and the condition fails, then the introductory requested page is returned. That means back to the login page.
app.post("/islogin", function(req, res) {
return res.send({
status:
req.headers.authorization &&
req.headers.authorization === "amFtZXNAZ21haWwuY29tMTIzNDU2Nzg="
});
});
This path is simpler. Its updating the status to true if the req.headers.Authorization is true, and it matches to the token that has just been generated.
When an explicit request is taken in, all the details of it are in the header. Who initiated the login, the credentials, type of protocol used, all the details being sent to the server from the browser.
Through this, authentication is carried out to make sure that the user logged in is authorized.
<iframe
src="https://codesandbox.io/embed/express-js-rest-api-for-react-route-x60t8?fontsize=14&hidenavigation=1&theme=dark"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="express-js-rest-api-for-react-route"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts>
</iframe>
This is a way of implementing the react routing using
<BrowserRouter>, <Switch> and <Route> components. Two paths are being routed, with the “/”, the LogIn component will be rendered while if the user uses “/home” then the Home component will be rendered.
import React, { Component } from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "./Home";
import LogIn from "./LogIn";
export default class App extends Component {
render() {
return (
<div className="app">
<BrowserRouter>
<Switch>
<Route exact path={"/"} component={LogIn} />
<Route exact path={"/home"} component={Home} />
</Switch>
</BrowserRouter>
</div>
);
}
}
Now let’s take a look at the React application. To keep things simple, I have created two components, Login and Home.
Let first go through the Login component, the jsx being rendered of the login form in the browser through the following code. A form is created in which input fields like email and password are generated.
render() {
return (
<div>
<form onSubmit={this.c}>
<h1>welcome to log in!</h1>
<br />
<input
type="email"
name="email"
placeholder="Email"
defaultValue={this.state.email}
onChange={e => {
this.setState({ email: e.target.value });
}}
/>
<br />
<br />
<input
type="password"
name="password"
placeholder="Password"
defaultValue={this.state.password}
onChange={e => {
this.setState({ password: e.target.value });
}}
/>
<br />
<br />
<button type="submit"> Login </button>
</form>
</div>
);
}
Now when the form is being submitted, handleSubmit is being called. Below I have defined handleSubmit() that handles the event when the user submits the form. event.preventDefault() stops the form from being submitted if it’s in its default state. Now take a look at the axios.post() method.
The URL being hit is that of the REST API created above of the path “/login”. If you review “/login”, it generates a token if the email and password is a match. This is how React and the Rest API is interacting through passing the user’s request.
handleSubmit(event) {
event.preventDefault();
const { email, password } = this.state;
// console.log(this.state);
axios
.post(
"https://x60t8.sse.codesandbox.io/login",
{
username: email,
password: password
}
// { withCredentials: true }
)
.then(res => {
console.log(res);
window.localStorage.setItem("token", res.data.token);
this.props.history.push("/home");
// return <Redirect to="/home" />;
})
.catch(err => {
console.log(err);
});
}
Once the Rest API responds with a successful match with a token then I have saved the token in the localStorage.
History prop comes from the History Library and has properties related to routing. The push property What it does is it pushes a new entry into the history stack and redirects the user to the defined route. In our case, after a successful login, redirecting the user to the home page, else throws an error message and prevents them from submitting.
ComponentDidMount() will be called when all the components of the page has been rendered to the client-side properly. The first condition checks if the token exists in the localstorage.
componentDidMount() {
if (window.localStorage.getItem("token")) {
axios.defaults.headers.common[
"Authorization"
] = window.localStorage.getItem("token");
axios
.post("https://x60t8.sse.codesandbox.io/islogin")
.then(res => {
if (res.data.status) {
this.props.history.push("/home");
}
})
.catch(res => console.log(res));
}
}
Call back the “/islogin” path that we’ve defined in the REST web services, we are hitting the “/islogin” path to send the credentials for authorization.
When the URL is successfully operational and response is received from the REST service, I have checked that if the status is updated to true. If so then the user will successfully be redirected to the home page. In case the authorization fails, an error will be generated and the user will stay on the login page.
We’ve gone through the login page. What about the home page? The Home component first checks if the token doesn’t exists then push the user back to the login page. If the token’s value exists, only then it’s being sent back to the REST web service we created for authentication.
If the response returned from the service in the variable of status is false, meaning the user failed the authentication, he/she will be redirected back to the login page.
export default class Home extends Component {
componentDidMount() {
if (!window.localStorage.getItem("token")) {
//redirect to Login
console.log("redirect to login");
this.props.history.push("/");
}
if (window.localStorage.getItem("token")) {
axios.defaults.headers.common[
"Authorization"
] = window.localStorage.getItem("token");
axios
.post("https://x60t8.sse.codesandbox.io/islogin")
.then(res => {
console.log();
if (!res.data.status) {
//window.location.href = window.location.toString() + "/home";
console.log("redirct to login");
this.props.history.push("/");
}
})
.catch(res => console.log(res));
}
}
Now if the user logs out, the token is being removed from the localstorage and is being pushed back to the login page.
render() {
return (
<div>
<h1>Home</h1>
<h1>You are logged in</h1>
<button
onClick={e => {
window.localStorage.removeItem("token");
this.props.history.push("/");
}}
>
Logout
</button>
</div>
);
Output
let’s try to understand what we have overall covered in the article by understanding the output
First, let’s try to access the homepage without logging in.
You will be redirected back to the login page
Now try to log in, this will redirect you to the home page.
With the correct credentials, you are redirected to the home page.
Log out and you will be redirected back to the login webpage. Just the way we require.
The React routers can be used efficiently to direct the user to various pages the developer desires to connect. They remain an excellent way to have control over the paths of the website that the user might take and utilize it in a favorable manner for both the user and developer.
<iframe
src="https://codesandbox.io/embed/tender-volhard-jk0f6?fontsize=14&hidenavigation=1&theme=dark"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="tender-volhard-jk0f6"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts">
</iframe>