In this tutorial, we’re gonna build a React Hooks JWT Authentication example with LocalStorage, React Router, Axios and Bootstrap (without Redux). I will show you:
- JWT Authentication Flow for User Signup & User Login
- Project Structure for React Hooks JWT Authentication (without Redux) with LocalStorage, React Router & Axios
- Creating React Function Components with Hooks & Form Validation
- React Function Components for accessing protected Resources (Authorization)
- Dynamic Navigation Bar in React Hooks App
Related Posts:
– In-depth Introduction to JWT-JSON Web Token
– React Hooks CRUD example with Axios and Web API
– React Hooks File Upload example with Axios & Progress Bar
– React Form Validation with Hooks example
– React Custom Hook
Fullstack (JWT Authentication & Authorization example):
– React + Spring Boot
– React + Node.js Express + MySQL/PostgreSQL
– React + Node.js Express + MongoDB
The example without using Hooks:
React JWT Authentication (without Redux) example
Using Redux: React Hooks + Redux: JWT Authentication & Authorization example
Contents
- Overview of React Hooks JWT Authentication example
- User Registration and User Login Flow
- React Function Component Diagram with Router, Axios & LocalStorage
- Technology
- Project Structure
- Setup React.js Hooks Authentication Project
- Add React Router
- Import Bootstrap
- Create Services
- Create React Pages for Authentication
- Create React Pages for accessing Resources
- Add Navbar and define Routes
- Logout when Token is expired
- Add CSS style for React Pages
- Configure Port for React JWT Auth Client with Web API
- Conclusion
- Further Reading
Overview of React Hooks JWT Authentication example
We will build a React Hooks application in that:
- There are Login/Logout, Signup pages.
- Form data will be validated by front-end before being sent to back-end.
- Depending on User’s roles (admin, moderator, user), Navigation Bar changes its items automatically.
Here are the screenshots:
– Signup Page:
– Form Validation Support:
If you need Form Validation with React Hook Form 7, please visit:
React Form Validation with Hooks example
Or Formik and Yup:
React Form Validation example with Hooks, Formik and Yup
– Login Page:
– Profile Page (for successful Login):
– For Moderator account login, the navigation bar will change by authorities:
– Check Browser Local Storage:
If you want to add refresh token, please visit:
React Refresh Token with JWT and Axios Interceptors
User Registration and User Login Flow
For JWT Authentication, we’re gonna call 2 endpoints:
- POST
api/auth/signup
for User Registration - POST
api/auth/signin
for User Login
The following flow shows you an overview of Requests and Responses that React Client will make or receive. This React Client must add a JWT to HTTP Header before sending request to protected resources.
You can find step by step to implement these back-end servers in following tutorial:
- Spring Boot JWT Authentication with Spring Security, MySQL
- Spring Boot JWT Authentication with Spring Security, PostgreSQL
- Spring Boot JWT Authentication with Spring Security, MongoDB
- Node.js JWT Authentication & Authorization with MySQL
- Node.js JWT Authentication & Authorization with MongoDB
- Node.js JWT Authentication & Authorization with PostgreSQL
Demo Video
This is full React + Spring Boot JWT Authentication & Authorization demo (with form validation, check signup username/email duplicates, test authorization with 3 roles: Admin, Moderator, User):
React + Node Express:
The React project in video uses React Components instead of React Hooks, but the flow or structure is the same.
React Function Component Diagram with Router, Axios & LocalStorage
Let’s look at the diagram below.
– The App
component is a container with React Router (BrowserRouter
). Basing on the state, the navbar can display its items.
– Login
& Register
pages have form for data submission (with support of react-validation
library). They call methods from auth.service
to make login/register request.
– auth.service
methods use axios
to make HTTP requests. Its also store or get JWT from Browser Local Storage inside these methods.
– Home
page is public for all visitor.
– Profile
page displays user information after the login action is successful.
– BoardUser
, BoardModerator
, BoardAdmin
pages will be displayed by state user.roles
. In these pages, we use user.service
to access protected resources from Web API.
– user.service
uses auth-header()
helper function to add JWT to HTTP header. auth-header()
returns an object containing the JWT of the currently logged in user from Local Storage.
If you want to use Typescript instead, please visit:
React Typescript Authentication example with Hooks
Or using HttpOnly Cookie for storing JWT:
React.js Login & Registration example โ JWT & HttpOnly Cookie
Technology
We’re gonna use these modules:
- React 17/16
- react-router-dom 6.2.2
- axios 0.26.1
- react-validation 3.0.7
- Bootstrap 4
- validator 12.2.0
Project Structure
This is folders & files structure for this React application:
With the explanation in diagram above, you can understand the project structure easily.
Setup React.js Hooks Authentication Project
Open cmd at the folder you want to save Project folder, run command:
npx create-react-app react-hooks-jwt-auth
Add React Router
– Run the command: npm install react-router-dom
.
– Open src/index.js and wrap App
component by BrowserRouter
object.
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
serviceWorker.unregister();
Import Bootstrap
Run command: npm install [email protected]
.
Open src/App.js and modify the code inside it as following-
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
function App() {
return (
...
);
}
export default App;
Create Services
We’re gonna create two services in src/services folder:
- Authentication service
- Data service
services
auth-header.js
auth.service.js (Authentication service)
user.service.js (Data service)
Before working with these services, we need to install Axios with command:
npm install axios
Authentication service
The service uses Axios for HTTP requests and Local Storage for user information & JWT.
It provides following important functions:
login()
: POST {username, password} & saveJWT
to Local Storagelogout()
: removeJWT
from Local Storageregister()
: POST {username, email, password}getCurrentUser()
: get stored user information (including JWT)
services/auth.service.js
import axios from "axios";
const API_URL = "http://localhost:8080/api/auth/";
const register = (username, email, password) => {
return axios.post(API_URL + "signup", {
username,
email,
password,
});
};
const login = (username, password) => {
return axios
.post(API_URL + "signin", {
username,
password,
})
.then((response) => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
};
const logout = () => {
localStorage.removeItem("user");
};
const getCurrentUser = () => {
return JSON.parse(localStorage.getItem("user"));
};
const AuthService = {
register,
login,
logout,
getCurrentUser,
};
export default AuthService;
Data service
We also have methods for retrieving data from server. In the case we access protected resources, the HTTP request needs Authorization header.
Let’s create a helper function called authHeader()
inside auth-header.js:
export default function authHeader() {
const user = JSON.parse(localStorage.getItem('user'));
if (user && user.accessToken) {
return { Authorization: 'Bearer ' + user.accessToken };
} else {
return {};
}
}
The code above checks Local Storage for user
item. If there is a logged in user
with accessToken
(JWT), return HTTP Authorization header. Otherwise, return an empty object.
Note: For Node.js Express back-end, please use x-access-token header like this:
export default function authHeader() {
const user = JSON.parse(localStorage.getItem('user'));
if (user && user.accessToken) {
// for Node.js Express back-end
return { 'x-access-token': user.accessToken };
} else {
return {};
}
}
Now we define a service for accessing data in services/user.service.js:
import axios from "axios";
import authHeader from "./auth-header";
const API_URL = "http://localhost:8080/api/test/";
const getPublicContent = () => {
return axios.get(API_URL + "all");
};
const getUserBoard = () => {
return axios.get(API_URL + "user", { headers: authHeader() });
};
const getModeratorBoard = () => {
return axios.get(API_URL + "mod", { headers: authHeader() });
};
const getAdminBoard = () => {
return axios.get(API_URL + "admin", { headers: authHeader() });
};
const UserService = {
getPublicContent,
getUserBoard,
getModeratorBoard,
getAdminBoard,
};
export default UserService;
You can see that we add a HTTP header with the help of authHeader()
function when requesting authorized resource.
Create React Pages for Authentication
In src folder, create new folder named components and add several files as following:
components
Login.js
Register.js
Profile.js
Form Validation overview
Now we need a library for Form validation, so we’re gonna add react-validation library to our project.
Run the command: npm install react-validation validator
To use react-validation in this example, you need to import following items:
import Form from "react-validation/build/form";
import Input from "react-validation/build/input";
import CheckButton from "react-validation/build/button";
import { isEmail } from "validator";
We also use isEmail()
function from validator to verify email.
This is how we put them in render()
method with validations
attribute:
const required = value => {
if (!value) {
return (
<div className="alert alert-danger" role="alert">
This field is required!
</div>
);
}
};
const email = value => {
if (!isEmail(value)) {
return (
<div className="alert alert-danger" role="alert">
This is not a valid email.
</div>
);
}
};
render() {
return (
...
<Form
onSubmit={handleLogin}
ref={form}
>
...
<Input
type="text"
className="form-control"
...
validations={[required, email]}
/>
<CheckButton
style={{ display: "none" }}
ref={checkBtn}
/>
</Form>
...
);
}
We’re gonna call Form validateAll()
method to check validation functions in validations
. Then CheckButton
helps us to verify if the form validation is successful or not. So this button will not display on the form.
form.validateAll();
if (checkBtn.context._errors.length === 0) {
// do something when no error
}
If you need Form Validation with React Hook Form 7, please visit:
React Form Validation with Hooks example
Or Formik and Yup:
React Form Validation example with Hooks, Formik and Yup
Login Page
This page has a Form with username
& password
.
– We’re gonna verify them as required field.
– If the verification is ok, we call AuthService.login()
method, then direct user to Profile page using useNavigate()
hook, or show message
with response error.
components/Login.js
import React, { useState, useRef } from "react";
import { useNavigate } from 'react-router-dom';
import Form from "react-validation/build/form";
import Input from "react-validation/build/input";
import CheckButton from "react-validation/build/button";
import AuthService from "../services/auth.service";
const required = (value) => {
if (!value) {
return (
<div className="alert alert-danger" role="alert">
This field is required!
</div>
);
}
};
const Login = () => {
let navigate = useNavigate();
const form = useRef();
const checkBtn = useRef();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const onChangeUsername = (e) => {
const username = e.target.value;
setUsername(username);
};
const onChangePassword = (e) => {
const password = e.target.value;
setPassword(password);
};
const handleLogin = (e) => {
e.preventDefault();
setMessage("");
setLoading(true);
form.current.validateAll();
if (checkBtn.current.context._errors.length === 0) {
AuthService.login(username, password).then(
() => {
navigate("/profile");
window.location.reload();
},
(error) => {
const resMessage =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
setLoading(false);
setMessage(resMessage);
}
);
} else {
setLoading(false);
}
};
return (
<div className="col-md-12">
<div className="card card-container">
<img
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
alt="profile-img"
className="profile-img-card"
/>
<Form onSubmit={handleLogin} ref={form}>
<div className="form-group">
<label htmlFor="username">Username</label>
<Input
type="text"
className="form-control"
name="username"
value={username}
onChange={onChangeUsername}
validations={[required]}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Input
type="password"
className="form-control"
name="password"
value={password}
onChange={onChangePassword}
validations={[required]}
/>
</div>
<div className="form-group">
<button className="btn btn-primary btn-block" disabled={loading}>
{loading && (
<span className="spinner-border spinner-border-sm"></span>
)}
<span>Login</span>
</button>
</div>
{message && (
<div className="form-group">
<div className="alert alert-danger" role="alert">
{message}
</div>
</div>
)}
<CheckButton style={{ display: "none" }} ref={checkBtn} />
</Form>
</div>
</div>
);
};
export default Login;
Register Page
This page is similar to Login Page.
For Form Validation, there are some more details:
username
: required, between 3 and 20 charactersemail
: required, email formatpassword
: required, between 6 and 40 characters
We’re gonna call AuthService.register()
method and show response message (successful or error).
components/Register.js
import React, { useState, useRef } from "react";
import Form from "react-validation/build/form";
import Input from "react-validation/build/input";
import CheckButton from "react-validation/build/button";
import { isEmail } from "validator";
import AuthService from "../services/auth.service";
const required = (value) => {
if (!value) {
return (
<div className="alert alert-danger" role="alert">
This field is required!
</div>
);
}
};
const validEmail = (value) => {
if (!isEmail(value)) {
return (
<div className="alert alert-danger" role="alert">
This is not a valid email.
</div>
);
}
};
const vusername = (value) => {
if (value.length < 3 || value.length > 20) {
return (
<div className="alert alert-danger" role="alert">
The username must be between 3 and 20 characters.
</div>
);
}
};
const vpassword = (value) => {
if (value.length < 6 || value.length > 40) {
return (
<div className="alert alert-danger" role="alert">
The password must be between 6 and 40 characters.
</div>
);
}
};
const Register = () => {
const form = useRef();
const checkBtn = useRef();
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [successful, setSuccessful] = useState(false);
const [message, setMessage] = useState("");
const onChangeUsername = (e) => {
const username = e.target.value;
setUsername(username);
};
const onChangeEmail = (e) => {
const email = e.target.value;
setEmail(email);
};
const onChangePassword = (e) => {
const password = e.target.value;
setPassword(password);
};
const handleRegister = (e) => {
e.preventDefault();
setMessage("");
setSuccessful(false);
form.current.validateAll();
if (checkBtn.current.context._errors.length === 0) {
AuthService.register(username, email, password).then(
(response) => {
setMessage(response.data.message);
setSuccessful(true);
},
(error) => {
const resMessage =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
setMessage(resMessage);
setSuccessful(false);
}
);
}
};
return (
<div className="col-md-12">
<div className="card card-container">
<img
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"
alt="profile-img"
className="profile-img-card"
/>
<Form onSubmit={handleRegister} ref={form}>
{!successful && (
<div>
<div className="form-group">
<label htmlFor="username">Username</label>
<Input
type="text"
className="form-control"
name="username"
value={username}
onChange={onChangeUsername}
validations={[required, vusername]}
/>
</div>
<div className="form-group">
<label htmlFor="email">Email</label>
<Input
type="text"
className="form-control"
name="email"
value={email}
onChange={onChangeEmail}
validations={[required, validEmail]}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Input
type="password"
className="form-control"
name="password"
value={password}
onChange={onChangePassword}
validations={[required, vpassword]}
/>
</div>
<div className="form-group">
<button className="btn btn-primary btn-block">Sign Up</button>
</div>
</div>
)}
{message && (
<div className="form-group">
<div
className={ successful ? "alert alert-success" : "alert alert-danger" }
role="alert"
>
{message}
</div>
</div>
)}
<CheckButton style={{ display: "none" }} ref={checkBtn} />
</Form>
</div>
</div>
);
};
export default Register;
Profile Page
This page gets current User from Local Storage by calling AuthService.getCurrentUser()
method and show user information (with token).
components/Profile.js
import React from "react";
import AuthService from "../services/auth.service";
const Profile = () => {
const currentUser = AuthService.getCurrentUser();
return (
<div className="container">
<header className="jumbotron">
<h3>
<strong>{currentUser.username}</strong> Profile
</h3>
</header>
<p>
<strong>Token:</strong> {currentUser.accessToken.substring(0, 20)} ...{" "}
{currentUser.accessToken.substr(currentUser.accessToken.length - 20)}
</p>
<p>
<strong>Id:</strong> {currentUser.id}
</p>
<p>
<strong>Email:</strong> {currentUser.email}
</p>
<strong>Authorities:</strong>
<ul>
{currentUser.roles &&
currentUser.roles.map((role, index) => <li key={index}>{role}</li>)}
</ul>
</div>
);
};
export default Profile;
Create React Pages for accessing Resources
These pages will use UserService
to request data from API.
components
Home.js
BoardUser.js
BoardModerator.js
BoardAdmin.js
Home Page
This is a public page that shows public content. People don’t need to log in to view this page.
components/Home.js
import React, { useState, useEffect } from "react";
import UserService from "../services/user.service";
const Home = () => {
const [content, setContent] = useState("");
useEffect(() => {
UserService.getPublicContent().then(
(response) => {
setContent(response.data);
},
(error) => {
const _content =
(error.response && error.response.data) ||
error.message ||
error.toString();
setContent(_content);
}
);
}, []);
return (
<div className="container">
<header className="jumbotron">
<h3>{content}</h3>
</header>
</div>
);
};
export default Home;
Role-based Pages
We’re gonna have 3 pages for accessing protected data:
- BoardUser page calls
UserService.getUserBoard()
- BoardModerator page calls
UserService.getModeratorBoard()
- BoardAdmin page calls
UserService.getAdminBoard()
I will show you User Page for example, other Pages are similar to this Page.
components/BoardUser.js
import React, { useState, useEffect } from "react";
import UserService from "../services/user.service";
const BoardUser = () => {
const [content, setContent] = useState("");
useEffect(() => {
UserService.getUserBoard().then(
(response) => {
setContent(response.data);
},
(error) => {
const _content =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
setContent(_content);
}
);
}, []);
return (
<div className="container">
<header className="jumbotron">
<h3>{content}</h3>
</header>
</div>
);
};
export default BoardUser;
You can simplify import statement with:
Absolute Import in React
Now we add a navigation bar in App
component. This is the root container for our application.
The navbar dynamically changes by login status and current User’s roles.
- Home: always
- Login & Sign Up: if user hasn’t signed in yet
- User:
AuthService.getCurrentUser()
returns a value - Board Moderator: roles includes
ROLE_MODERATOR
- Board Admin: roles includes
ROLE_ADMIN
App.js
import React, { useState, useEffect } from "react";
import { Routes, Route, Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import AuthService from "./services/auth.service";
import Login from "./components/Login";
import Register from "./components/Register";
import Home from "./components/Home";
import Profile from "./components/Profile";
import BoardUser from "./components/BoardUser";
import BoardModerator from "./components/BoardModerator";
import BoardAdmin from "./components/BoardAdmin";
const App = () => {
const [showModeratorBoard, setShowModeratorBoard] = useState(false);
const [showAdminBoard, setShowAdminBoard] = useState(false);
const [currentUser, setCurrentUser] = useState(undefined);
useEffect(() => {
const user = AuthService.getCurrentUser();
if (user) {
setCurrentUser(user);
setShowModeratorBoard(user.roles.includes("ROLE_MODERATOR"));
setShowAdminBoard(user.roles.includes("ROLE_ADMIN"));
}
}, []);
const logOut = () => {
AuthService.logout();
};
return (
<div>
<nav className="navbar navbar-expand navbar-dark bg-dark">
<Link to={"/"} className="navbar-brand">
bezKoder
</Link>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/home"} className="nav-link">
Home
</Link>
</li>
{showModeratorBoard && (
<li className="nav-item">
<Link to={"/mod"} className="nav-link">
Moderator Board
</Link>
</li>
)}
{showAdminBoard && (
<li className="nav-item">
<Link to={"/admin"} className="nav-link">
Admin Board
</Link>
</li>
)}
{currentUser && (
<li className="nav-item">
<Link to={"/user"} className="nav-link">
User
</Link>
</li>
)}
</div>
{currentUser ? (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/profile"} className="nav-link">
{currentUser.username}
</Link>
</li>
<li className="nav-item">
<a href="/login" className="nav-link" onClick={logOut}>
LogOut
</a>
</li>
</div>
) : (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/login"} className="nav-link">
Login
</Link>
</li>
<li className="nav-item">
<Link to={"/register"} className="nav-link">
Sign Up
</Link>
</li>
</div>
)}
</nav>
<div className="container mt-3">
<Routes>
<Route path="/" element={<Home/>} />
<Route path="/home" element={<Home/>} />
<Route path="/login" element={<Login/>} />
<Route path="/register" element={<Register/>} />
<Route path="/profile" element={<Profile/>} />
<Route path="/user" element={<BoardUser/>} />
<Route path="/mod" element={<BoardModerator/>} />
<Route path="/admin" element={<BoardAdmin/>} />
</Routes>
</div>
</div>
);
};
export default App;
Logout when Token is expired
There are two ways to handle JWT Token expiration.
For more details, please visit:
Handle JWT Token expiration in React with Hooks
Add CSS style for React Pages
Open src/App.css and write some CSS code as following:
label {
display: block;
margin-top: 10px;
}
.card-container.card {
max-width: 350px !important;
padding: 40px 40px;
}
.card {
background-color: #f7f7f7;
padding: 20px 25px 30px;
margin: 0 auto 25px;
margin-top: 50px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.profile-img-card {
width: 96px;
height: 96px;
margin: 0 auto 10px;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
Configure Port for React Hooks JWT Auth Client with Web API
Because most of HTTP Server use CORS configuration that accepts resource sharing retricted to some sites or ports, so we also need to configure port for our App.
In project folder, create .env file with following content:
PORT=8081
Now we’ve set our app running at port 8081
. You will need to do this work if you use one of following Servers:
- Spring Boot JWT Authentication with Spring Security, MySQL
- Spring Boot JWT Authentication with Spring Security, PostgreSQL
- Spring Boot JWT Authentication with Spring Security, MongoDB
- Node.js JWT Authentication & Authorization with MySQL
- Node.js JWT Authentication & Authorization with PostgreSQL
- Node.js JWT Authentication & Authorization with MongoDB
Conclusion
Congratulation!
Today we’ve done so many interesting things. I hope you understand the overall layers of our React Hooks JWT Authentication App (without Redux) using LocalStorage, React Router, Axios, Bootstrap. Now you can apply it in your project at ease.
Don’t forget to read this tutorial:
Handle JWT Token expiration in React with Hooks
If you don’t want to use Hooks, you can find the instruction at:
React JWT Authentication (without Redux) example
Or you need React Redux for this example:
– using React Components: React Redux: JWT Authentication & Authorization example
– using Hooks: React Hooks + Redux: JWT Authentication & Authorization example
Or add refresh token:
React Refresh Token with JWT and Axios Interceptors
Happy learning, see you again!
Further Reading
- React Router Guide
- React Hooks
- React Custom Hook
- https://www.npmjs.com/package/react-validation
- https://www.npmjs.com/package/validator
- In-depth Introduction to JWT-JSON Web Token
Fullstack CRUD:
– React + Spring Boot + MySQL
– React + Spring Boot + PostgreSQL
– React + Spring Boot + MongoDB
– React + Node.js Express + MySQL
– React + Node.js Express + PostgreSQL
– React + Node.js Express + MongoDB
– React + Django
Source Code
You can find the complete source code for this tutorial on Github.
Typescript version:
React Typescript Authentication example with Hooks
Or using HttpOnly Cookie for storing JWT:
React.js Login & Registration example โ JWT & HttpOnly Cookie
I have followed this tutorial and the one for the backend (Nodejs/Express/MongoDB) and got them connected and working correctly. However I am not wanting to fill in the User/Admin Content section in particular I want to add a dashboard page where it says ‘Admin Content’. Any suggestions on how I would go about this?
Many thanks for these tutorials btw
Thanks for wonderful tutorial. How to achieve this functionality ( user will receive confirmation code in email on sign up submit ). Do I have to make lot of changes?
Hey There. I discovered your tutorial. That is a very well written article. Thanks for the post. I will definitely comeback.
Nice post. I was checking continuously your React tutorials.
I’m impressed! Extremely helpful.
Thanks and best of luck.
can you please explain the role of the checkbutton. i’m one that likes to understand everything and i’m confused how this validates the form.
much love and respect for this tutorial. seen a lot of your stuff recently and digging it!
Hello, I did everything as you show but I am getting an error:
Access to XMLHttpRequest at ‘http://localhost:8080/api/auth/login’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
I added .env 3000 port. Please help
Hi, you need to run your React Client on port 8081 ๐ It is because we configure server CORS for that port.
But, I wrote 3000 port in .env file ๐
You can change it to 8081, or configure server CORS with your port.
you are awesome! the best tutorial!
Okay sure. I had tried with the configuration from your tutorial but am still running into the cors issue with the error message as follows:
Access to XMLHttpRequest at ‘http://localhost:8080/api/auth/signup’ from origin ‘http://localhost:8081’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
For this I have ensured both the ports are running correctly and were restarted before trying so that the front end in on 8081 and the back end is on 8080. I have also checked to ensure that there are no typos with the calls and both are still functional with postman as per your spring boot java jwt back end tutorial. I have unfortunately run out of things to try and so would love any help you could provide.
I’m currently having an issue with CORS. I have set the WebSecurityConfig as you suggested in the back end spring java tutorial and made sure all of the names are correct. The back end works on postman but its when i try to access it from react i have issues. What could be a potential solution to this. I also experimented with adding a proxy in my package.json file but I’m not sure why this was not working. Also as a separate question, what is the significance of changing to port 8081 as opposed to using port 3000 as default for the front end?
Hi, the backend server is configured to work with frontend at port 8081. You will get a CORS issue if you run this Client on port 3000.
Hi Bezkoder, I just finished implementing the backend tutorial with springboot/mysql and works perfect then i did front end with this one as you had suggested in postman i acn register/sign up but on front end when i sign up i get Network error… what could be the problem?
Hi, it is the connection between backend and frontend. You can check everything related to HTTP requests such as: axios instance, port… Then make sure that cors is configured correctly.
You are amazing
Hi, is accessToken specific to axios? I am using rails api backend so I want to know if (response.data.accessToken) in the http request will be something else.
I used the node-js-jwt-auth and react-hooks-jwt-auth. All was great. Only one change I had to do is add ‘x-access-token’ to header in src/services/auth-header.js
return { Authorization: ‘Bearer ‘ + user.accessToken, ‘x-access-token’: user.accessToken };
As the server (middleware/authJwt.js) was looks for ‘x-access-token’
Thank you for the nice tutorial
Hola amigos, buenas noches quisiera saber como puedo agregar mรกs paginas a un rol teniendo en cuenta los roles.
Gracias…
I would like to know that after I am logged in, how can I obtain the token to be able to consume the other api services such as registering departments, listing, etc …?
when I run the command
npx create-react-app react-hooks-jwt-authentication it throws an 404 error that react-hooks-jwt-authentication doesn’t exist
sorry my bad
This tutorial, along with node-js-jwt-authentication, was my first introduction to setting up authentication in a react app and rest-api endpoints. Everything works great except for one thing – when the token expires, it does not automatically log the user out. The user stays logged in but is unable to do anything (unauthorized). The NavBar still shows the user as being logged in. Of course all you need to do is log out and log back in for everything to work again, but your tutorial should check if the token has expired and log the user out if it has.
Yeah, I will write a tutorial for your case when having time. ๐
In the mean time, how about a hint? Would like to know how you would go about implementing this. Doesn’t look like it would be too difficult, but I don’t really know where to begin. I’m thinking I would need another function in auth.service.js that checks to see if the token is current or expired. Maybe something like this:
https://stackoverflow.com/questions/59713592/why-am-i-unable-to-see-the-response-of-this-axios-post-request
Would appreciate any insight you could find the time to provide. Your tutorial would be 100% complete if your code would check for this.
Thanks.
Hi Bezkoder,
I’m also facing the same problem and not been able to resolve it yet. It seems so simple, but I have yet to find a solution so if you could point us in the right direction that would be great.
Thanks,
Reinier
Hey. Thanks a lot for this tutorial. It is really helpful. Any update regarding the question asked by Rayner ? Im in the same situation and not sure how to go about it ? Thank you!
AuthVerify.js worked for me, thanks Tien! https://www.bezkoder.com/react-logout-token-expired/
Dude why are you putting it in localstorage? Isn’t that horrible practice?
Why not make a tutorial where you store it inside memory and update it with http-only or put it in the database???
Hi, please read more about Token-based Authentication and Session-based Authentication along with their pros/cons.
Does this support refresh tokens?
Hi, you can read an additional tutorial: React Refresh Token with JWT and Axios Interceptors
can some one please let me know how to register a user with admin and other roles. the default registration creates just a User
Hi, you can use Http Client tool to make Http Post request with roles in payload.
I’m still having the same problem plz did you solve it?
Hi, you should write Component with form that contains
roles
/role
array for sending HTTP signup requests.Excellent tutorial! Found only one mistake – for the react version on GitHub, in auth-header.js, the wrong line is commented out. Kept getting “No token provided!” until I commented out the Spring Boot back-end code and uncommented the Node.js Express back-end code. Well done! Thanks for sharing!