Reactjs JWT Authentication Example

Reactjs-Jwt-Authentication-Example

Tutorial: ” Reactjs JWT Token Authentication Example – Reactjs Login Authentication Example ”

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. So in the tutorial, I introduce how to implement an application “Reactjs JWT token Authentication Example – Reactjs Login Authentication Example ” with details step by step and 100% running sourcecode.

– I give you an Epic of the application, a fullstack excutive flow from frontend to backend with overall architecture diagram.
– I give you a layer diagram of Reactjs JWT Application.
– I give you an implementatin of security backend sourcecode (SpringBoot + Nodejs JWT RestAPIs).
– I guide you step by step how to develop a Reactjs JWT Authentication application.
– Finally, I do an integrative testing from Reactjs JWT Authentication application to Backend Security RestAPIs

Related posts:


Overview Reactjs JWT Token Authentication Example

JWT Token Authentication

JSON Web Token (JWT) defines a compact and self-contained way for securely transmitting information between parties as a JSON object.

Scenarios where JSON Web Tokens are useful:

  • Authorization: the most common scenario for using JWT. Single Sign On is a feature that widely uses JWT
  • Information Exchange: Because JWTs can be signed, JSON Web Tokens are a good way of securely transmitting information between parties.

JSON Web Tokens consist of 3 parts:

  • Header
  • Payload
  • Signature

-> JWT looks like Header-Base64-String.Payload-Base64-String.Signature-Base64-String

Header consists of two parts:

  • token type.
  • hashing algorithm.

-> Example:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload contains the claims. Claims are statements about an entity and additional information.
There are 3 types of claims ->

  • Registered claims -> These are a set of predefined claims: iss (issuer), exp (expiration time), sub (subject)
  • Public claims
  • Private claims

Example:

{
  "sub": "thomasgkz",
  "iat": 1537603195,
  "exp": 1537689595
}

Signature -> To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

Example:

HMACSHA512(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret
)

Combine all together, we get 3 Base64-URL strings separated by dots,

-> Example:

eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0aG9tYXNna3oiLCJpYXQiOjE1Mzc2MDMxOTUsImV4cCI6MTUzNzY4OTU5NX0.m2YMjTYmOnfR7nnVNxqCzWbQ2FhKRe1eiizxnC2TF4eAoEzKlwo7PheVkKcxj08ST3vB-ZOIhiORvYVfSgzcog

When accessing a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema.

Example:

Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0aG9tYXNna3oiLCJpYXQiOjE1Mzc2MDMxOTUsImV4cCI6MTUzNzY4OTU5NX0.m2YMjTYmOnfR7nnVNxqCzWbQ2FhKRe1eiizxnC2TF4eAoEzKlwo7PheVkKcxj08ST3vB-ZOIhiORvYVfSgzcog

Overall Epic System Architecture Diagram

Reactjs JWT Authentication Overall Diagram
Reactjs JWT Authentication Overall Diagram

For the Reactjs JWT Authentication tutorial, we have 2 projects:
– Backend project (using SpringBoot or Nodejs Express) provides secured RestAPIs with JWT token.
– Reactjs project will request RestAPIs from Backend system with the JWT Token Authentication implementation.

JWT Authentication Sequence Diagram

The diagram below show how our system handles User Registration and User Login processes:

Reactjs Jwt Authentication Working Process Diagram
Reactjs Jwt Authentication Working Process Diagram

1. User Registration Phase:
– User uses a React.js register form to post user’s info (name, username, email, role, password) to Backend API /api/auth/signup.
– Backend will check the existing users in database and save user’s signup info to database. Finally, It will return a message (successfully or fail) to

2. User Login Phase:
– User posts user/password to signin to Backend RestAPI /api/auth/signin.
– Backend will check the username/password, if it is right, Backend will create and JWT string with secret then return it to Reactjs client.

After signin, user can request secured resources from backend server by adding the JWT token in Authorization Header. For each request, backend will check the JWT signature and then returns back the resources based on user’s registered authorities.

Reactjs JWT Authentication Layer Diagram Overview

Reactjs JWT Authentication - Layer Diagram
Reactjs JWT Authentication – Layer Diagram

Reactjs JWT Authentication would be built with 5 main kind blocks:

  • Reactjs Router is a standard library for routing in React. It enables the navigation among views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL.
  • Reactjs Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.
  • Reactjs Service is a bridge between Reactjs Component and Backend Server, it is used to do technical logic with Backend Server (using Ajax Engine to fetch data from Backend, or using Local Storage to save user login data) and returned a response data to React.js Components
  • Local Storage allow to save key/value pairs in a web browser. It is a place to save the login user’s info.
  • Axios – (an Ajax Engine) is a promise-based HTTP client for the browser and Node. js. Axios makes it easy to send asynchronous HTTP requests to REST endpoints and perform CRUD operations.

Project Goal

We create a Reactjs JWT Authentication project as below:

Reactjs Jwt Authentication project structure
Reactjs Jwt Authentication project structure

It includes 8 components and 2 services and a router in app.js file.

– Home page:

Reactjs Home Page
Reactjs Home Page

– User Register page:

Reactjs Jwt Authentication - Register Form
Reactjs Jwt Authentication – Register Form

– Login Page:

Reactjs Login Page
Reactjs Login Page

– Profile Page:

Reactjs Profile Page
Reactjs Profile Page

– Use Page:

Reactjs User Page
Reactjs User Page

– Project Manager Page:

Reactjs JWT Authentication - PM Content
Reactjs JWT Authentication – PM Content

– Reactjs Admin page:

Reactjs jwt authentication - admin page
Reactjs jwt authentication – admin page

Overvall Implementation with Backend Security RestAPIs – Reactjs Login Authentication Example

Backend Token JWT RestAPIs Goal

– Sign-Up 3 users:

  • Jack has ROLE_USER role
  • Adam has ROLE_PM & ROLE_USER roles
  • Thomas has ROLE_ADMIN role
Reactjs JWT Authentication - register a customer with admin role
Reactjs JWT Authentication – register a customer with admin role

– Check database’s tables:

Check MySQL database - add Thomas - admin user
Check MySQL database – add Thomas – admin user

SignIn and Access Protected Resources

– Jack can access api/test/user url, can NOT access others.
Sign In:

JWT Authentication - Jack signin with PostMan to Backend
JWT Authentication – Jack signin with PostMan to Backend

– Access Protected Resources:

Jack with USER_ROLE retrieves user resources from backend restapi
Jack with USER_ROLE retrieves user resources from backend restapi

– Jack can NOT access Admin or PM resources:

Jack can NOT access PM resources
Jack can NOT access PM resources

– Adam can access User & PM Resources: api/test/user and api/test/pm urls.
Adam can NOT access Admin resources /api/test/admin url.

-> Sign In:

Adam SignIn successfully
Adam SignIn successfully

-> Adam Access Protected Resources:

Adam can retrieve USER resources
Adam can retrieve USER resources
Adam can access PM resources
Adam can access PM resources
Adam can NOT access Admin resources
Adam can NOT access Admin resources

– Thomas with ADMIN_ROLE so he can access all resources.

-> SignIn:

Thomas Signin
Thomas Signin

-> Access Protected Resource:

Thomas access proteced resource
Thomas access proteced resource

SpringBoot JWT Token Authentication RestAPIs Implementation

Below is diagram for Spring Security/JWT (Springboot Token Based Authentication Example) classes that are separated into 3 layers:
– HTTP
– Spring Security
– REST API

Spring Security Jwt Token Authentication Architecture Diagram
Spring Security Jwt Token Authentication Architecture Diagram

You can see details step by step guide at the tutorial link:
Spring Security JWT Implementation Tutorial
– Video guide:

Nodejs JWT Token Authentication RestAPIs Implementation

HTTP request that matches route will be accepted by CORS Middleware before coming to Security layer.

Security layer includes:
– JWT Authentication Middleware: verify SignUp, verify token
– Authorization Middleware: check User’s roles

Main Business Logic Processing interacts with database via Sequelize and send HTTP response (token, user information, data based on roles…) to client.

Nodejs Jwt Authentication Architecture Diagram
Nodejs Jwt Authentication Architecture Diagram

You can see details step by step guide at the tutorial link:
Nodejs Security JWT Token Authentication Implementation Tutorial
– Video guide:

Reactjs JWT Token Authentication Implementation

Step by step to build Reactjs JWT Authentication Application – Reactjs Login Authentication Example

Reactjs JWT Authentication - Layer Diagram
Reactjs JWT Authentication – Layer Diagram

For building the Reactjs JWT Authentication, we do below steps:

  • We create Reactjs Jwt Authentication application
  • We implement React.js Authentication Service. It provides RestAPIs to signin/signup and retrieve user’s login info from Local Storage
  • We implement React.js Backend Service. It provides RestAPIs to retrieve data from Security Backend
  • We implement Reactjs components to signIn/signUp and show data from backend server
  • We define a Reactjs router to navigate between UI components

Setup Reactjs Project

Create React App is a command line utility that generates React projects for you. It’s a convenient tool because it also offers commands that will build and optimize your project for production.

The create-react-app will set up everything you need to run a React application.

– Create a new project in the app directory with Yarn.

yarn create react-app Reactjs-Jwt-Authentication

Project Structure:

Start Setup React project structure
Start Setup React project structure

More details you can see at: Create Reactjs Project

After the app creation process completes, navigate into the app directory and install Bootstrap, React Router, and Reactstrap.

Reactstrap: This library contains React Bootstrap 4 components that favor composition and control. The library does not depend on jQuery or Bootstrap javascript.
– React Router: Components are the heart of React’s powerful, declarative programming model. React Router is a collection of navigational components that compose declaratively with your application.

cd Reactjs-Jwt-Authentication
yarn add bootstrap react-cookie react-router-dom reactstrap

Implement Reactjs JWT Authentication Service

The service AuthenticationService implements 4 main functions to signup/signin/signout and get current login user’s info:

To do http requests with Backend server, the AuthenticationService use Axios (an HttpClient) to interact with Server. AuthenticationService uses localStorage to store user login’s info.

import axios from "axios";

/**
 * @Copyright by https://ozenero.com
 *        youtube ozenero
 */

class AuthenticationService {
  signin = (username, password) => {
      return axios.post("/api/auth/signin", {username, password})
        .then(response => {
          if (response.data.accessToken) {
            localStorage.setItem("user", JSON.stringify(response.data));
          }
          return response.data;
        })
        .catch(err => {
          console.log(err);
          throw err;
        });
  }

  signOut() {
    localStorage.removeItem("user");
  }

  register = async(firstname, lastname, username, email, password) => {
    return axios.post("/api/auth/signup", {
      firstname,
      lastname,
      username,
      email,
      password
    });
  }

  getCurrentUser() {
    return JSON.parse(localStorage.getItem('user'));;
  }
}

export default new AuthenticationService();

Implement Reactjs JWT Backend Service

BackendService is used to get resources from server:
getUserBoard()
getPmBoard()
getAdminBoard()

With each request from BackendService to server, we use axios interceptors to attach the Authorization header with JWT token.

import axios from 'axios';

// Add a request interceptor
axios.interceptors.request.use( config => {
  const user = JSON.parse(localStorage.getItem('user'));

  if(user && user.accessToken){
    const token = 'Bearer ' + user.accessToken;
    config.headers.Authorization =  token;
  }

  return config;
});

class BackendService {
  async getUserBoard() {
    return await axios.get("/api/test/user");
  }

  async getPmBoard() {
    return await axios.get("/api/test/pm");
  }

  async getAdminBoard() {
    return await axios.get("/api/test/admin");
  }
}

export default new BackendService();

Implement Reactjs JWT AppNavbar component

Reactjs jwt authentication - navigation bar
Reactjs jwt authentication – navigation bar
import React, { Component } from 'react';
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavbarText, NavItem, NavLink } from 'reactstrap';
import { Link } from 'react-router-dom';

import { withRouter } from 'react-router-dom';

import AuthenticationService from '../services/AuthenticationService';

class AppNavbar extends Component {
  constructor(props) {
    super(props);
    this.state = {isOpen: false};
    this.toggle = this.toggle.bind(this);

    this.state = {
      showUser: false,
      showPM: false,
      showAdmin: false,
      username: undefined,
      login: false
    };
  }

  componentDidMount() {
    const user = AuthenticationService.getCurrentUser();

    if (user) {
      const roles = [];

      user.authorities.forEach(authority => {
        roles.push(authority.authority)
      });
  
      this.setState({
        showUser: true,
        showPM: roles.includes("ROLE_PM") || roles.includes("ROLE_ADMIN"),
        showAdmin: roles.includes("ROLE_ADMIN"),
        login: true,
        username: user.username
      });
    }
  }

  signOut = () => {
    AuthenticationService.signOut();
    this.props.history.push('/home');
    window.location.reload();
  }

  toggle() {
    this.setState({
      isOpen: !this.state.isOpen
    });
  }

  render() {
    return <Navbar color="dark" dark expand="md">
      <NavbarBrand tag={Link} to="/home">Loizenai.com</NavbarBrand>
      <Nav className="mr-auto">
        <NavLink href="/home">Home</NavLink>
        {this.state.showUser && <NavLink href="/user">User</NavLink>}
        {this.state.showPM && <NavLink href="/pm">PM</NavLink>}
        {this.state.showAdmin && <NavLink href="/admin">Admin</NavLink>}
      </Nav>
      <NavbarToggler onClick={this.toggle}/>
      <Collapse isOpen={this.state.isOpen} navbar>
        {
          this.state.login ? (
            <Nav className="ml-auto" navbar>
              <NavItem>
                  <NavbarText>
                    Signed in as: <a href="/profile">{this.state.username}</a>
                  </NavbarText>
              </NavItem>
              <NavItem>
                <NavLink href="#" onClick={this.signOut}>SignOut</NavLink>
              </NavItem>
            </Nav>                 
          ) : (
            <Nav className="ml-auto" navbar>
              <NavItem>
                <NavLink href="/signin">Login</NavLink>
              </NavItem>
              <NavItem>
                <NavLink href="/signup">SignUp</NavLink>
              </NavItem>
            </Nav>
          )
        }
      </Collapse>
    </Navbar>;
  }
}

export default withRouter(AppNavbar);

– In AppNavbar component, We use componentDidMount() to load user info, and then extracts data from user login info to determine what links would be showed on React.js’s UI.

Implement Reactjs JWT Home component

Reactjs Home Page
Reactjs Home Page
import React, { Component } from 'react';
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';
import { Button, Container } from 'reactstrap';
import { Alert } from "react-bootstrap"

class Home extends Component {

  constructor(props) {
    super(props);
  }

  componentDidMount() {
  }

  render() {
    return (
      <div>
        <AppNavbar/>
        <Container fluid>
          <div style={{marginTop:"20px"}}>
            <Alert variant="primary">
              <h2>Reactjs JWT Authentication Application</h2>
              <Button color="success"><Link to="/signin"><span style={{color:"white"}}>Login</span></Link></Button>
            </Alert>
          </div>
        </Container>
      </div>
    );
  }
}

export default Home;

Implement React.js JWT SignUp component

Reactjs Jwt Authentication - Register Form
Reactjs Jwt Authentication – Register Form

– For posting data from register-form to backend server, SignUp component uses the register(...) function of AuthenticationService service.

SignUp component implements a changeHandler() function to save the values from input fields of Register form to the state object of SignUp component.

– The function changeHandler() also includes segment code to validate input data from register-form:

Reactjs JWT Authentication - Register Form Validation
Reactjs JWT Authentication – Register Form Validation

– Detail Coding:

import React, { Component } from 'react';
import AppNavbar from './AppNavbar';
import { Container } from 'reactstrap';
import { Button, Form, FormGroup, Input, Label, Row, Col } from "reactstrap";
import { Alert } from "react-bootstrap"

import Authentication from '../services/AuthenticationService'

const validEmailRegex = RegExp(/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i);

const validateForm = (errors) => {
  let valid = true;
  Object.values(errors).forEach(
    (val) => val.length > 0 && (valid = false)
  );
  return valid;
}

class SignUp extends Component {
  
  constructor(props) {
    super(props);
    this.state = {
      firstname: "",
      lastname: "",
      username: "",
      email: "",
      password: "",
      message: "",
      successful: false,
      validForm: true,
      errors: {
        firstname: '',
        lastname: '',
        username: '',
        email: '',
        password: ''
      }
    };
  }

  changeHandler = (event) => {
    const { name, value } = event.target;
  
    let errors = this.state.errors;

    switch (name) {
      case 'firstname':
        errors.firstname = 
          value.length < 3
            ? 'FirstName must be 3 characters long!'
            : '';
        break;
      case 'lastname':
        errors.lastname = 
          value.length < 3
            ? 'LastName must be 3 characters long!'
            : '';
        break;
      case 'username':
        errors.username = 
          value.length < 5
            ? 'Username must be 5 characters long!'
            : '';
        break;
      case 'email': 
        errors.email = 
          validEmailRegex.test(value)
            ? ''
            : 'Email is not valid!';
        break;
      case 'password': 
        errors.password = 
          value.length < 8
            ? 'Password must be 8 characters long!'
            : '';
        break;
      default:
        break;
    }
  
    this.setState({errors, [name]: value}, ()=> {
        console.log(errors)
    })  
  }

  signUp = (e) => {
    e.preventDefault();
    const valid = validateForm(this.state.errors);
    this.setState({validForm: valid});
    if(valid){
      Authentication.register(
        this.state.firstname,
        this.state.lastname,
        this.state.username,
        this.state.email,
        this.state.password
      ).then(
        response => {
          this.setState({
            message: response.data.message,
            successful: true
          });
        },
        error => {
          console.log("Fail! Error = " + error.toString());
          
          this.setState({
            successful: false,
            message: error.toString()
          });
        }
      );  
    }
  }

  render() {
    const title = <h2>Register User</h2>;
    const errors = this.state.errors;

    let alert = "";

    if(this.state.message){
      if(this.state.successful){
        alert = (
                  <Alert variant="success">
                    {this.state.message}
                  </Alert>
                );
      }else{
        alert = (
                  <Alert variant="danger">
                    {this.state.message}
                  </Alert>
                );
      }
    }

    return ( 
      <div>
        <AppNavbar/>
        <Container fluid>
          <Row>
          <Col sm="12" md={{ size: 4, offset: 4 }}>
          {title}
            <Form onSubmit={this.signUp}>
              <FormGroup controlId="forFirstname">
                <Label for="firstname">First Name</Label>
                <Input
                  type="text" 
                  placeholder="Enter First Name"
                  name="firstname" id="firstname"
                  value={this.state.firstname}
                  autoComplete="firstname"
                  onChange={this.changeHandler}
                />
                {
                  errors.firstname && ( 
                      <Alert variant="danger">
                        {errors.firstname}
                      </Alert>
                    )
                }
              </FormGroup>

              <FormGroup controlId="forLastname">
                <Label for="lastname">Last Name</Label>
                <Input
                  type="text" 
                  placeholder="Enter Last Name"
                  name="lastname" id="lastname"
                  value={this.state.lastname}
                  autoComplete="lastname"
                  onChange={this.changeHandler}
                />
                {
                  errors.lastname && ( 
                      <Alert variant="danger">
                        {errors.firstname}
                      </Alert>
                    )
                }
              </FormGroup>

              <FormGroup controlId="forUsername">
                <Label for="username">Username</Label>
                <Input
                  type="text" 
                  placeholder="Enter UserName"
                  name="username" id="username"
                  value={this.state.username}
                  autoComplete="username"
                  onChange={this.changeHandler}
                />
                {
                  errors.username && ( 
                      <Alert variant="danger">
                        {errors.username}
                      </Alert>
                    )
                }
              </FormGroup>

              <FormGroup controlId="formEmail">
                <Label for="email">Email</Label>
                <Input required
                  type="text" 
                  placeholder="Enter Email"
                  name="email" id="email"
                  value={this.state.email}
                  autoComplete="email"
                  onChange={this.changeHandler}
                />
                {
                  errors.email && ( 
                      <Alert variant="danger">
                        {errors.email}
                      </Alert>
                    )
                }
              </FormGroup>

              <FormGroup controlId="formPassword">
                <Label for="password">Password</Label>
                <Input required 
                  type="password" 
                  placeholder="Enter Password"
                  name="password" id="password"
                  value={this.state.password}
                  autoComplete="password"
                  onChange={this.changeHandler}
                />
                {
                  errors.password && ( 
                      <Alert key="errorspassword" variant="danger">
                        {errors.password}
                      </Alert>
                    )
                }
              </FormGroup>

              <Button variant="primary" type="submit">
                Create
              </Button>
              {
                !this.state.validForm && (
                  <Alert key="validForm" variant="danger">
                    Please check the inputs again!
                  </Alert>
                )
              }

              {alert}
            </Form>
            </Col>
          </Row>
        </Container>
      </div>);
  }
}

export default SignUp;

Implement Reactjs JWT Login component

Reactjs JWT Token authentication - Login form
Reactjs JWT Token authentication – Login form

Login component implement a function doLogin that uses a function signin() of AuthenticationService service to signin to secured Backend server with Jwt token.

import React, { Component } from 'react';
import AppNavbar from './AppNavbar';
import { Container } from 'reactstrap';
import { Form, Alert, FormGroup, Input, Label, Row, Col } from "reactstrap";
import {Button} from 'react-bootstrap';
import AuthenticationService from "../services/AuthenticationService";
import avatar from '../../avatar.png';

import '../../App.css';

class Login extends Component {

  constructor(props) {
    super(props);

    this.state = {
      username: "",
      password: "",
      error: ""
    };
  }

  changeHandler = (event) => {
    let nam = event.target.name;
    let val = event.target.value;
    this.setState({[nam]: val});
  }

  doLogin = async (event) => {
    event.preventDefault();

    AuthenticationService
        .signin(this.state.username, 
                  this.state.password)
      .then(
        () => {
          this.props.history.push('/profile');
        },
        error => {
          console.log("Login fail: error = { " + error.toString() + " }");
          this.setState({error: "Can not signin successfully ! Please check username/password again"});
        }
    );
  }

  render() {
    return ( 
      <div>
        <AppNavbar/>
        <Container fluid>
          <Row style={{marginTop:"20px"}}>
          <Col sm="12" md={{ size: 3, offset: 4 }}>
            <div style={{marginBottom: "10px"}}>
              <img src={avatar} alt="Avatar" className="avatar center" 
                style={{width: "50%", height: "auto"}}/>
            </div>
            <Form  onSubmit={this.doLogin}>
              <FormGroup>
                <Label for="username"><strong>Username</strong></Label>
                <Input autoFocus 
                  type="text"
                  name="username" id="username"
                  value={this.state.username}
                  placeholder="Enter Username"
                  autoComplete="username"
                  onChange={this.changeHandler}
                />
              </FormGroup>

              <FormGroup>
                <Label for="password"><strong>Password</strong></Label>
                <Input type="password" 
                  name="password" id="password"
                  value={this.state.password}
                  placeholder="Enter Password"
                  autoComplete="password"
                  onChange={this.changeHandler}
                />
              </FormGroup>

              <Button type="submit" variant="primary" size="lg" block>
                Sign In
              </Button>
              {
                this.state.error && (
                  <Alert color="danger">
                    {this.state.error}
                  </Alert>
                )
              }
            </Form>
            </Col>
          </Row>
        </Container>
      </div>);
  }
}

export default Login;

Implement Reactjs JWT Profile component

Profile component just uses a function componentDidMount() that calls a function getCurrentUser() of AuthenticationService service to get the current user login’s info and shows them on UI.

Reactjs jwt authentication - sign in with admin role
Reactjs jwt authentication – sign in with admin role
import React, { Component } from 'react';
import AppNavbar from './AppNavbar';
import { Link } from 'react-router-dom';
import { Button, Container } from 'reactstrap';
import { Alert } from "react-bootstrap"

import AuthenticationService from '../services/AuthenticationService';

class Profile extends Component {

  constructor(props) {
    super(props);
    this.state = {user: undefined};
  }

  componentDidMount() {
    const user = AuthenticationService.getCurrentUser();
    this.setState({user: user});
  }

  render() {
    let userInfo = "";
    const user = this.state.user;

    // login
    if (user && user.accessToken) {

      let roles = "";

      user.authorities.forEach(authority => {
        roles = roles + " " + authority.authority
      });

      userInfo = (
                <div style={{marginTop:"20px"}}>
                  <Alert variant="info">
                    <h2>User Info</h2>
                    <ul>
                      <li>Username: {user.username}</li>
                      <li>Access Token: {user.accessToken}</li>
                      <li>Authorities: {roles}</li>
                    </ul>
                  </Alert>
                </div>
              );
    } else { // not login
      userInfo = <div style={{marginTop:"20px"}}>
                    <Alert variant="primary">
                      <h2>Profile Component</h2>
                      <Button color="success"><Link to="/signin"><span style={{color:"white"}}>Login</span></Link></Button>
                    </Alert>
                  </div>
    }

    return (
      <div>
        <AppNavbar/>
        <Container fluid>
        {userInfo}
        </Container>
      </div>
    );
  }
}

export default Profile;

Implement Reactjs jwt token User Page

Reactjs jwt authentication - User Page Content
Reactjs jwt authentication – User Page Content

In the componentDidMount() function, the component UserPage uses the service BackendService to load user-content from secured backend-server and show it on UI.

import AppNavbar from './AppNavbar';
import React, { Component } from 'react';
import { Container } from 'reactstrap';
import BackendService from '../services/BackendService';
import { Alert } from "react-bootstrap"

class UserPage extends Component {
  constructor(props) {
    super(props);
    this.state={
      content: "",
      error: ""
    }
  }

  componentDidMount() {
    BackendService.getUserBoard()
      .then( response => {
        this.setState({content: response.data})
      } , error => {
        console.log(error);
        this.setState({
          error: error.toString()
        }); 
      });
  }

  render() {
    return (
      <div>
        <AppNavbar/>
        <Container fluid>
            {
              this.state.content ? (
                <div style={{marginTop: "20px"}}>
                  <Alert variant="info">
                    <h2>{this.state.content}</h2>
                  </Alert>
                </div>
              ) : (
                <div style={{marginTop: "20px"}}>
                  <Alert variant="danger">
                    {this.state.error}
                  </Alert>
                </div>
              )
            }
        </Container>
      </div>
    );
  }
}

export default UserPage;

Implement Reactjs jwt token PM Page

Reactjs JWT Authentication - PM Content
Reactjs JWT Authentication – PM Content

In the componentDidMount() function, the component ProjectManagerPage uses the service BackendService to load pm-content from secured backend-server and show it on UI.

import AppNavbar from './AppNavbar';
import React, { Component } from 'react';
import { Container } from 'reactstrap';
import { Alert } from "reactstrap";
import BackendService from '../services/BackendService';

class ProjectManagerPage extends Component {
  constructor(props) {
    super(props);
    this.state={
      content: "",
      error: ""
    }
  }

  componentDidMount() {
    BackendService.getPmBoard()
    .then( response => {
      this.setState({
        content: response.data
      })
    } , error => {
      console.log(error);
      this.setState({
        error: error.toString()
      }); 
    });
  }

  render() {
    return (
      <div>
        <AppNavbar/>
        <Container fluid>
          {
            this.state.content ? (
              <div style={{marginTop: "20px"}}>
                <Alert color="info">
                  <h2>{this.state.content}</h2>
                </Alert>
              </div>
            ) : (
              <div style={{marginTop: "20px"}}>
                <Alert color="danger">
                  {this.state.error}
                </Alert>
              </div>
            )
          }
        </Container>
      </div>
    );
  }
}

export default ProjectManagerPage;

Implement Reactjs jwt token Admin Page

Reactjs jwt authentication - admin page
Reactjs jwt authentication – admin page

In the componentDidMount() function, the component AdminPage uses the service BackendService to load admin-content from secured backend-server and show it on UI.

import AppNavbar from './AppNavbar';
import React, { Component } from 'react';
import { Container } from 'reactstrap';
import { Alert } from "reactstrap";
import BackendService from '../services/BackendService';

class AdminPage extends Component {
  constructor(props) {
    super(props);
    this.state={
      content: "",
      error: ""
    }
  }

  componentDidMount() {
    BackendService.getAdminBoard()
      .then( response => {
        this.setState({
          content: response.data
        })
      } , error => {
        console.log(error);
        this.setState({
          error: error.toString()
        }); 
      });    
  }

  render() {
    return (
      <div>
        <AppNavbar/>
        <Container fluid>
          {
            this.state.content ? (
              <div style={{marginTop: "20px"}}>
                <Alert variant="info">
                  <h2>{this.state.content}</h2>
                </Alert>
              </div>
            ) : (
              <div style={{marginTop: "20px"}}>
                <Alert variant="danger">
                  {this.state.error}
                </Alert>
              </div>
            )
          }
        </Container>
      </div>
    );
  }
}

export default AdminPage;

Define Reactjs Router

App.js uses React Router to navigate between components:

  • path “/” and “/home” is mapped with Home component
  • path “/profile” is mapped with Profile component
  • path “/user” is mapped with UserPage component
  • path “/pm” is mapped with ProjectManagerPage component
  • path “/admin” is mapped with Admin component
  • path “/signin” is mapped with Login component
  • path “/signup” is mapped with SignUp component
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import './App.css';
import Home from './app/components/Home';
import Profile from './app/components/Profile';
import UserPage from './app/components/UserPage';
import ProjectManagerPage from './app/components/ProjectManagerPage';
import SignUp from './app/components/SignUp';
import AdminPage from './app/components/AdminPage';
import Login from './app/components/Login';

class App extends Component {
  render() {
    return (
      <Router>
        <Switch>
          <Route path='/' exact={true} component={Home}/>
          <Route path='/home' exact={true} component={Home}/>
          <Route path='/profile' exact={true} component={Profile}/>
          <Route path='/user' exact={true} component={UserPage}/>
          <Route path='/pm' exact={true} component={ProjectManagerPage}/>
          <Route path='/admin' exact={true} component={AdminPage}/>
          <Route path='/signin' exact={true} component={Login}/>
          <Route path='/signup' exact={true} component={SignUp}/>  
        </Switch>
      </Router>
    )
  }
}

export default App;

Add a Proxy Setting for calling RestAPIs

To proxy from /api to http://localhost:8080/api, add a proxy setting to app/package.json.

"scripts": {...},
"proxy": "http://localhost:8080",

Integrative Testing – Reactjs JWT Authentication with Backend Security

– Start Backend Server at port 8080.
– Start Reactjs application with cmd: yarn start

Testcase 1 – Reactjs JWT SignUp

Reactjs jwt authentication - Jack is create successfully
Reactjs jwt authentication – Jack is create successfully

– Check MySQL database:

Check MySQL database - jack user is registered successfully
Check MySQL database – jack user is registered successfully

Testcase 2 – Reactjs JWT Login with user role

reactjs jwt authentication - wrong login user - validation
reactjs jwt authentication – wrong login user – validation

Then re-login with right username/password: jack-ozenero.com/123456789.

-> after signin successfully, Reactjs application will be redirected to Profile component:

Reactjs jwt authentication - sign in successfully
Reactjs jwt authentication – sign in successfully

– Get User content:

Reactjs jwt authentication - User Page Content
Reactjs jwt authentication – User Page Content

Testcase 3 – Reactjs JWT SignOut

To signout, just click to the signout link at the most right side of Navigation-Bar, after signout successfully, Reactjs application will be redirected to Home page.

Reactjs Home Page
Reactjs Home Page

Testcase 4 – Reactjs JWT SignIn with other roles

1. Register a Adam user, with PM_ROLE and USER_ROLE:

Reactjs jwt authentication - register a user successfully with 2 roles user and pm
Reactjs jwt authentication – register a user successfully with 2 roles user and pm

– Check MySQL:

Check MySQL database - add Adam user with PM roles
Check MySQL database – add Adam user with PM roles

– Adam logins successfully with below user login’s info:

Reatjs jwt authentication - login with a user with PM roles successfully
Reatjs jwt authentication – login with a user with PM roles successfully

2. Register Thomas user, with ADMIN_ROLE:

Reactjs JWT Authentication - register a customer with admin role
Reactjs JWT Authentication – register a customer with admin role

– Check MySQL:

Check MySQL database - add Thomas - admin user
Check MySQL database – add Thomas – admin user

– Access the admin-content:

Reactjs jwt authentication - admin page
Reactjs jwt authentication – admin page

Further Reading

Related posts:


Sourcecode – Reactjs Login Authentication Example

Full sourcecode: “Reactjs JWT Token Authentication Example – Reactjs Login Authentication Example”

reactjs-jwt-token-authentication

Github sourceode:

reactjs-jwt-authentication-github

0 0 votes
Article Rating
Subscribe
Notify of
guest
117 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments