This section describe how to implement authentication in React.
First, we need to create React app using this command:
Create file
This class will handle authentication.
isAuthentication() function will return boolean value whether user has been authenticated.
checkCredentials() function will check whether given credential is valid. For this example, checkCredentials() function use static user data. We need to change this function to use programmatic user data using user service.
setUserDetails() function is used to store user details. In this example, user details will saved to local storage.
Create file
Use this class on pages that can only be visited by users who have not been authenticated, like login and reset password. If someone has been authenticated try to enter login page, this component will redirect user to root page. So, authenticated user will not face that page.
Create file
Use this class on pages that can only be visited by users who have been authenticated, like profile page etc. If someone has not been authenticated try to enter protected resource/page, this component will redirect user to login page. This class will hold return url (actual user requested url before redirect to login) on state and will redirect user to requested url if authentication is success.
Create file
This class will render Home Page that contain navigation to profile page and logout button if user has been authenticated, login page if user has not been authenticated.
views/Login.js
This class will render login page.
Create file
This class will render profil page, and displays the name of the user who has logged in.
Create file
In this class, we use AnonymousRoute and ProtectedRoute components. Login page use AnonymousRoute, can only be seen by users who have not been authenticated. Profile page use ProtectedRoute, can only be seen by users who have been authenticated.
To run app, we can execute command:
Source code can be found here: GitHub
React Version : 16.7.0
First, we need to create React app using this command:
npx create-react-app my-appWe also need to install React Router DOM using command:
npm install --save react-router-dom
Create file
src/AppComponent/Authentication.js
This class will handle authentication.
isAuthentication() function will return boolean value whether user has been authenticated.
checkCredentials() function will check whether given credential is valid. For this example, checkCredentials() function use static user data. We need to change this function to use programmatic user data using user service.
setUserDetails() function is used to store user details. In this example, user details will saved to local storage.
class Authentication { static isAuthenticated = () => { return Authentication.getUser() !== null; } static authenticate = (credentials) => { if(credentials && credentials.username && credentials.password) { const isValidCredentials = Authentication.checkCredentials(credentials); if(isValidCredentials) { Authentication.setUserDetails(credentials); } return isValidCredentials; } return false; } static checkCredentials = (credentials) => { return credentials.username == "admin" && credentials.password == "123"; } static getUsername = (userDetails) => { return Authentication.getUser().username; } static setUserDetails = (userDetails) => { localStorage.setItem("user", JSON.stringify(userDetails)); } static getUser = () => { return JSON.parse(localStorage.getItem("user")); } static logOut = () => { localStorage.removeItem("user"); } } export default Authentication;
Create file
src/AppComponent/AnonymousRoute.js
Use this class on pages that can only be visited by users who have not been authenticated, like login and reset password. If someone has been authenticated try to enter login page, this component will redirect user to root page. So, authenticated user will not face that page.
import React, { Component } from 'react'; import { Route, Redirect } from 'react-router-dom'; import Authentication from './Authentication'; class AnonymousRoute extends Component { render() { const {component: Component, ...others} = this.props; const renderRoute = props => { if (Authentication.isAuthenticated()) { return ( <Redirect to={ { pathname: '/' } } /> ); } return ( <Component {...props} /> ); } return ( <Route {...others} render={renderRoute}/> ); } } export default AnonymousRoute;
Create file
src/AppComponent/ProtectedRoute.js
Use this class on pages that can only be visited by users who have been authenticated, like profile page etc. If someone has not been authenticated try to enter protected resource/page, this component will redirect user to login page. This class will hold return url (actual user requested url before redirect to login) on state and will redirect user to requested url if authentication is success.
import React, { Component } from 'react'; import { Route, Redirect } from 'react-router-dom'; import Authentication from './Authentication'; class ProtectedRoute extends Component { render() { const {component: Component, ...others} = this.props; const renderRoute = props => { if (Authentication.isAuthenticated()) { return ( <Component {...props} /> ); } return ( <Redirect to={ { pathname: '/login', state: { returnUrl: props.location } } } /> ); } return ( <Route {...others} render={renderRoute}/> ); } } export default ProtectedRoute;
Create file
src/views/Home.js
This class will render Home Page that contain navigation to profile page and logout button if user has been authenticated, login page if user has not been authenticated.
import React, { Component } from 'react'; import Authentication from '../AppComponent/Authentication'; import { Link } from 'react-router-dom'; class Home extends Component { constructor(props) { super(props); } logout =(e) => { Authentication.logOut(); this.props.history.push('/login'); } render() { const navigation = Authentication.isAuthenticated() ? (<div><Link to="/profile">Profile Page</Link><br /><button onClick={() => this.logout() }>Logout</button></div>) : <Link to="/login">Login Page</Link>; return ( <React.Fragment> <div>This is Home Page</div> { navigation } </React.Fragment> ); } } export default Home;
views/Login.js
This class will render login page.
import React, { Component } from 'react'; import Authentication from '../AppComponent/Authentication'; class Login extends Component { constructor(props) { super(props); this.loginForm = React.createRef(); this.state = { isLoginSuccess: true } } doLogin = () => { const form = this.loginForm.current; const credentials = { username: form.username.value, password: form.password.value } const isLoginSuccess = Authentication.authenticate(credentials); this.setState({ isLoginSuccess }); if(!isLoginSuccess){ return; } let successUrl = this.props.location.state ? this.props.location.state.returnUrl : '/'; this.props.history.push(successUrl); } render() { return ( <React.Fragment> <div> This is Login Page </div> <div> <form ref={this.loginForm} onSubmit={(e)=> { e.preventDefault(); this.doLogin() }} > <input type="text" name="username" placeholder="username" /><br /> <input type="password" name="password" placeholder="password" /><br /> <input type="submit" value="Submit" /> </form> <div>{this.state.isLoginSuccess ? '' : 'Login fail.'}</div> </div> </React.Fragment> ); } } export default Login;
Create file
sec/views/Profile.js
This class will render profil page, and displays the name of the user who has logged in.
import React, { Component } from 'react'; import Authentication from '../AppComponent/Authentication'; class Profile extends Component { constructor(props) { super(props); } render() { return ( <div> This is Profile Page.<br /> Login as { Authentication.getUsername() } </div> ); } } export default Profile;
Create file
src/App.js
In this class, we use AnonymousRoute and ProtectedRoute components. Login page use AnonymousRoute, can only be seen by users who have not been authenticated. Profile page use ProtectedRoute, can only be seen by users who have been authenticated.
import React, { Component } from 'react'; import { Route, BrowserRouter, Switch } from 'react-router-dom'; import Login from './views/Login'; import Profile from './views/Profile'; import Home from './views/Home'; import ProtectedRoute from './AppComponent/ProtectedRoute'; import AnonymousRoute from './AppComponent/AnonymousRoute'; class App extends Component { render() { return ( <BrowserRouter> <Switch> <AnonymousRoute exact path="/login" name="Login" component={Login} /> <ProtectedRoute path="/profile" name="Profile" component={Profile} /> <Route exact path="/" name="Home" component={Home} /> </Switch> </BrowserRouter> ); } } export default App;
To run app, we can execute command:
npm start
Source code can be found here: GitHub
React Version : 16.7.0