What is JWT?
JWT is an open standard for transferring data securely between two parties. It is used with authentication systems to make authenticated requests. It is mainly composed of header
, payload
, and signature
. JWT is a stateless authentication mechanism i.e it maintains sessions in the client-side itself instead of storing it in the server.
- Creating React App and Initial Setup
Initially, let’s create a new React App. Also, check if everything is fine with the created project.
npx create-react-app jwtreact
cd jwtreact/
npm start
Now let’s install all the required packages.
a. react-router-dom — For routing
b. react-bootstrap — For Styling our components
c. Axios — For making Request
npm i react-router-dom
npm install react-bootstrap bootstrap
npm i axios
src/index.js
Once installing every package, add the below line in the index.js
file which initializes bootstrap.
import 'bootstrap/dist/css/bootstrap.min.css';
Now, to begin with, I am creating Four pages inside the src/Pages
folder.
a. Dashboard Page — Page where the user will be redirected after login.
b. Login Page — Page to check if the credentials of the user are correct
b. Login Pag
c. Register Page — Page where the new user stores their data to the server.
d. 404 Page — Page which is used to handle garbage routes.
Once done, create the routes inside the main file which is App.js.
src/App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { Route, Switch, BrowserRouter as Router } from 'react
router-dom';
import Login from './Pages/Login'
import NotFound from './Pages/NotFound'
import Register from './Pages/Register'
import Dashboard from './Pages/Dashboard'function App() {
return (
<Router>
<Switch>
<Route exact path="/" component={Dashboard} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route component={NotFound} />
</Switch>
</Router>
);
}export default App;
2. Creating Our Views
We need an App bar to navigate within pages right. So I am using the basic Navbar by react-bootstrap.
src/App.js
import { Navbar, Nav, NavDropdown } from 'react-bootstrap'<Router>
<Navbar bg="dark" variant="dark" expand="lg">
<Navbar.Brand href="#home">React-JWT Login</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href='/login'>Login</Nav.Link>
<Nav.Link href='/register'>Register</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
<Switch>
<Route exact path="/" component={Dashboard} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route component={NotFound} />
</Switch>
</Router>
Also, here I am using the basic login and register pages provided by bootstrap. You can style it in your own way if you want.
src/Pages/Login.js
import React, { Component } from 'react'
import { Form, Button, Container } from 'react-bootstrap'export default class Login extends Component {constructor(props) {
super(props);
this.state = {
email: '',
password: '',
};
this.onChange = this.onChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}onChange = (e) => this.setState({ [e.target.name]: e.target.value });handleSubmit(event) {
console.log(this.state.email)
console.log(this.state.password)
event.preventDefault();
}render() {
return (
<Container style={{ marginTop: '100px' }}>
<Form>
<Form.Group controlId="formBasicEmail" style={{ width: '300px' }}>. <Form.Label>Email address</Form.Label>
<Form.Control type="text" placeholder="Enter email" name="email" value={this.state.email} onChange={this.onChange}/>
</Form.Group>
<Form.Group controlId="formBasicPassword" style={{ width: '300px' }}>
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" name="password" value={this.state.password} onChange={this.onChange}/>
</Form.Group>
<Form.Group controlId="formBasicCheckbox">
<Form.Check type="checkbox" label="Check me out" />
</Form.Group>
<Button variant="primary" type="submit" onClick={this.handleSubmit}>
Submit
</Button>
</Form>
</Container>
)
}
}
URL — http://localhost:3000/login
src/Pages/Register.js
import React, { Component } from 'react'
import { Form, Button, Container } from 'react-bootstrap'export default class Register extends Component {constructor(props) {
super(props);
this.state = {
first_name: '',
last_name: '',
email: '',
password: '',
};
this.onChange = this.onChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}onChange = (e) => this.setState({ [e.target.name]: e.target.value });handleSubmit(event) {
console.log(this.state.first_name)
console.log(this.state.last_name)
console.log(this.state.email)
console.log(this.state.password)
event.preventDefault();
}render() {
return (
<Container style={{ marginTop: '100px' }}>
<Form><Form.Group controlId="formBasicFirstName" style={{ width: '300px' }}>
<Form.Label>First name</Form.Label>
<Form.Control type="text" placeholder="Enter First Name" name="first_name" value={this.state.first_name} onChange={this.onChange}/>
</Form.Group><Form.Group controlId="formBasicLastName" style={{ width: '300px' }}>
<Form.Label>Last Name</Form.Label>
<Form.Control type="text" placeholder="Enter Last Name" name="last_name" value={this.state.last_name} onChange={this.onChange}/>
</Form.Group><Form.Group controlId="formBasicEmail" style={{ width: '300px' }}>
<Form.Label>Email address</Form.Label>
<Form.Control type="text" placeholder="Enter email" name="email" value={this.state.email} onChange={this.onChange}/>
</Form.Group><Form.Group controlId="formBasicPassword" style={{ width: '300px' }}>
<Form.Label>Password</Form.Label>
<Form.Control type="password" placeholder="Password" name="password" value={this.state.password} onChange={this.onChange}/>
</Form.Group><Button variant="primary" type="submit" onClick={this.handleSubmit}>
Register
</Button></Form>
</Container>
)
}
}
URL — http://localhost:3000/register
3. Making Auth Request to the API
To make a request to the API, I am Axios
which is a React library that helps to make all types of requests. Pass all the value to the URL http://localhost:8000/account/api/register with the required parameters. This stores all our data to the server.
src/Pages/Register.js
handleSubmit(event) {
axios.post('http://localhost:8000/account/api/register',{
username: this.state.email,
password: this.state.password,
first_name: this.state.first_name,
last_name: this.state.last_name
}).then(function (res){
console.log(res)
localStorage.setItem('token', res.data.access);
localStorage.setItem('user', res.config.data);
}).catch(function (err){
console.log(err)
})
event.preventDefault();
}
Do the same for Login also. Just change the URL to http://localhost:8000/api/token/. This will check if the credentials are right.
src/Pages/Login.js
handleSubmit(event) {
axios.post('http://localhost:8000/api/token/',{
username: this.state.email,
password: this.state.password,
}).then(function (res){
console.log(res)
localStorage.setItem('token', res.data.access);
localStorage.setItem('user', res.config.data);
}).catch(function (err){
console.log(err)
})
event.preventDefault();
}
Now we have logged in, but other pages should know that we have logged in right. To do that, we can store the token in the local storage of the device. In the handleSubmit
function, I am storing both the token and the user details to the local storage. So that I can access the token and user details anywhere within the project as I did below.
src/Pages/Dashboard.js
import React, { Component } from 'react'
import { Redirect } from 'react-router-dom'export default class Dashboard extends Component {
render() {
if(!localStorage.getItem('token')){
return <Redirect to='login'/>
}
return (
<div>
{localStorage.getItem('user')}
</div>
)
}
}
Feel free to contact me for any queries.
Email: sjlouji10@gmail.com
Linkedin: https://www.linkedin.com/in/sjlouji/
The complete code can be found on my Github: https://github.com/sjlouji/JWT-login-register-Medium
Happy coding…