React JS Authentication Boilerplate

Build Status Coverage Status Coverage Status

Summary

About

This repository was created to assist in the authentication implementation process in React JS applications with JWT and refresh token. All components and contexts have unit tests and a basic HTML structure without CSS. The project has features to secure routes and control the visibility of components based on permissions, the entire implementation process is in this document.

Feel free to clone the project or use it as a template and make any changes you deem necessary.

Built using

Getting started

Prerequisites

You need to install on your machine Node.js or Yarn.

Installing dependencies

npm install
# or
yarn install

Project setup

Compiles and hot-reloads for development

# start app open development mode
yarn start
# or
npm run start

Compiles and minifies for production

yarn build
# or
npm run build

Lints and fixes files

# show errors
yarn lint
# or
npm run lint

# fix errors
yarn lint:fix
# or
npm run lint:fix

Run your unit tests

# run tests
yarn test
# or
npm run test

# run tests on watch mode
yarn test:watch
# or
npm run test:watch

# run tests on coverage mode
yarn test:coverage
# or
npm run test:coverage

# run tests on coverage with watch mode
yarn test:coverage:watch
# or
npm run test:coverage:watch

Test users

The app is integrated with the node-api-refresh-token.herokuapp.com API, configured in the .env file. There are two users with different accesses so that the tests can be performed:

Administrator

  • Email: admin@site.com
  • Password: password@123
  • Permissions: users.list, users.create, metrics.list

Client

Route types

The route components are based on <Route /> component of react-router-dom and receive same props.

Public route

The route can only be accessed if a user is not authenticated. If accessed after authentication, the user will be redirected / route.

import { Switch } from 'react-router-dom'
import { PublicRoute } from 'src/routes/PublicRoute'

const SampleComponent = () => <div>Sample component</div>

export const Routes = () => (
  <Switch>
    <PublicRoute
      path="/login"
      component={SampleComponent}
    />
  </Switch>
)

Hybrid route

The route can be accessed whether a user is authenticated or not.

import { Switch } from 'react-router-dom'
import { HybridRoute } from 'src/routes/HybridRoute'

const SampleComponent = () => <div>Sample component</div>

export const Routes = () => (
  <Switch>
    <HybridRoute
      path="/register"
      component={SampleComponent}
    />
  </Switch>
)

Private route

The route can only be accessed if a user is authenticated. Use permission props to access control.

import { Switch } from 'react-router-dom'
import { PrivateRoute } from 'src/routes/PrivateRoute'

const SampleComponent = () => <div>Sample component</div>

export const Routes = () => (
  <Switch>
    {/*
      allow route access if the user has the permissions
      `users.list` and `users.create`
    */}
    <PrivateRoute
      path="/users"
      component={SampleComponent}
      permissions={['users.list', 'users.create']}
    />
  </Switch>
)

Control visibility of components

Use the CanAccess component and pass permissions props to control the visibility of a component.

import { CanAccess } from 'src/components/CanAccess'

export function NavBar () {
  return (
    <>
      {/*
        the component is shown if the user has the permissions
        `users.list` and `metrics.list`
      */}
      <CanAccess permissions={['users.list', 'metrics.list']}>
        {/* YOUR COMPONENT HERE */}
      </CanAccess>
    </>
  )
}

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE.md file for details


Develop by Eder Sampaio 👋  See my linkedin.