article

Monday, September 4, 2023

React JS Node Express Login Register using bcrypt and jsonwebtoken | Mysql

React JS Node Express Login Register using bcrypt and jsonwebtoken | Mysql

https://expressjs.com/
Express JS
Fast, unopinionated, minimalist web framework for Node.js

Install
$ npm install express --save
PS C:\nodeproject> npm install express --save
https://expressjs.com/en/starter/hello-world.html

run PS C:\nodeproject> node index.js
//C:\nodeproject> node index.js
const express = require("express");
const mysql = require("mysql");
const cors = require("cors");

const bcrypt = require('bcrypt'); // https://www.npmjs.com/package/bcrypt npm i bcrypt
var jwt = require('jsonwebtoken'); //https://github.com/auth0/node-jsonwebtoken npm install jsonwebtoken

const app = express();
const port = 3001

app.use(express.json());
app.use(cors());

const con = mysql.createConnection({
    user: "root",
    host: "localhost",
    password: "",
    database: "nodejsdb"
})

con.connect(function(err) {
    if(err) {
        console.log("Error in Connection");
    } else {
        console.log("Connected");
    }
})

app.get('/hash', (req, res) => {	
    bcrypt.hash("123456", 10, (err, hash) => {
        if(err) return res.json({Error: "Error in hashing password"});
        const values = [
            hash
        ]
        return res.json({result: hash});
    } )
})

app.post('/login', (req, res) => {
    const sql = "SELECT * FROM users Where email = ?";
    con.query(sql, [req.body.email], (err, result) => {
        if(err) return res.json({Status: "Error", Error: "Error in runnig query"});
        if(result.length > 0) {
            bcrypt.compare(req.body.password.toString(), result[0].password, (err, response)=> {
                if(err) return res.json({Error: "password error"});
                if(response) {
					const token = jwt.sign({role: "admin"}, "jwt-secret-key", {expiresIn: '1d'});
					return res.json({Status: "Success", Token: token})
                } else {
                    return res.json({Status: "Error", Error: "Wrong Email or Password"});
                }
            })
        } else {
            return res.json({Status: "Error", Error: "Wrong Email or Password"});
        }
    })
})

app.post('/register',(req, res) => {
    const sql = "INSERT INTO users (`name`,`email`,`password`) VALUES (?)"; 
    bcrypt.hash(req.body.password.toString(), 10, (err, hash) => {
        if(err) return res.json({Error: "Error in hashing password"});
        const values = [
            req.body.name,
            req.body.email,
            hash,
        ]
        con.query(sql, [values], (err, result) => {
            if(err) return res.json({Error: "Error query"});
            return res.json({Status: "Success"});
        })
    } )
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})
Install Requirements

mysql
https://github.com/mysqljs/mysql
$ npm install mysql
PS C:\nodeproject>npm install mysql

cors
CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
https://www.npmjs.com/package/cors
PS C:\nodeproject>npm i cors

bcrypt
A library to help you hash passwords.
https://www.npmjs.com/package/bcrypt
$ npm i bcrypt
PS C:\nodeproject>npm i bcrypt

jsonwebtoken
An implementation of JSON Web Tokens.
https://github.com/auth0/node-jsonwebtoken
$ npm install jsonwebtoken
PS C:\nodeproject>npm install jsonwebtoken

React JS
https://create-react-app.dev/

Create Project
C:\react-js>npx create-react-app my-app

Run
C:\react-js\my-app> npm start

C:\react-js\my-app\src\App.js

//C:\react-js\my-app\src\App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Navbar from "./components/navbar";
import Login from "./components/login";
import SignUp from "./components/signup";
import Profile from "./components/profile";
import {RequireToken} from './components/Auth.js'

function App() {
  return (
    <div className="app">
        <Navbar/>
        <BrowserRouter>
            <Routes>
              <Route path="/login" element={<Login />} />
              <Route path="/signup" element={<SignUp />} />
              <Route path="/profile"
                element={
                  <RequireToken>
                    <Profile />
                  </RequireToken>
                }
              />
            </Routes>
        </BrowserRouter>
    </div>
  );
}
  
export default App;
C:\react-js\my-app\src\components\navbar.js
//C:\react-js\my-app\src\components\navbar.js
import React, {  } from "react";
import {fetchToken} from './Auth.js'

const Navbar = () => {
  return (
    <nav className="navbar navbar-expand-lg navbar-light bg-light">
      <div className="container">
        <a className="navbar-brand" href="#">Cairocoders</a>
        <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span className="navbar-toggler-icon" />
        </button>
        <div className="collapse navbar-collapse" id="navbarSupportedContent">
          <ul className="navbar-nav me-auto mb-2 mb-lg-0">
            <li className="nav-item">
              <a className="nav-link active" aria-current="page" href="#">Home</a>
            </li>
            <li className="nav-item">
              <a className="nav-link" href="#">Link</a>
            </li>
          </ul>
          <div className="d-flex">
            {
                fetchToken() 
                ? (
                    <p>You are logged in!</p>
                )
                : (
                  <a className="btn btn-outline-primary" href="signup">Sign Up</a>
                )
            }
          </div>
        </div>
      </div>
    </nav>
  
  );
};
  
export default Navbar;
C:\react-js\my-app\src\components\signup.js
//C:\react-js\my-app\src\components\signup.js
import { useState } from "react";
import Axios from "axios";

const SignUp = () => {
   
    const [email, setEmail] = useState("");
    const [name, setName] = useState("");
    const [password, setPassword] = useState("");
    const [registerStatus, setRegisterStatus] = useState("");

    const register = (e) => {
        e.preventDefault();
        Axios.post("http://localhost:3001/register", {
          email: email,
          name: name,
          password: password,
        }).then((response) => {
          console.log(response);
          if(response.data.message){
            setRegisterStatus(response.data.message);
          }else{
            setRegisterStatus("ACCOUNT CREATED SUCCESSFULLY");
          }
        })
    }

  let imgs = [
    'https://as2.ftcdn.net/v2/jpg/03/39/70/91/1000_F_339709132_H9HSSTtTmayePcbARkTSB2qoZTubJ6bR.jpg',
  ];
  return (
        <div className="container" style={{paddingTop: 60}}>
          <div className="container-fluid h-custom">
            <div className="row d-flex justify-content-center align-items-center h-100">
              <div className="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
                <form>
                  <div className="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
                    <p className="lead fw-normal mb-0 me-3">Create Your Account</p>
                  </div>
                  <p><h1 style={{fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{registerStatus}</h1></p>
                  <div className="form-outline mb-4">
                    <input
                        type="text"
                        className="form-control form-control-lg"
                        placeholder="Enter Name"
                        onChange={(e) => {setName(e.target.value)}} placeholder="Enter your Name" required
                    />
                    <label className="form-label">Name</label>
                  </div>
                  <div className="form-outline mb-4">
                    <input
                      type="email"
                      className="form-control form-control-lg"
                      onChange={(e) => {setEmail(e.target.value)}} placeholder="Enter your Email Address" required
                    />
                    <label className="form-label">Email address</label>
                  </div>
                  <div className="form-outline mb-3">
                    <input
                      type="password"
                      className="form-control form-control-lg"
                      onChange={(e) => {setPassword(e.target.value)}} placeholder="Enter your Password" required
                    />
                    <label className="form-label">Password</label>
                  </div>
   
                  <div className="d-flex justify-content-between align-items-center">
                    <div className="form-check mb-0">
                      <input className="form-check-input me-2" type="checkbox" value=""/>
                      <label className="form-check-label">
                        Remember me
                      </label>
                    </div>
                    <a href="#" className="text-body">Forgot password?</a>
                  </div>
   
                  <div className="text-center text-lg-start mt-4 pt-2">
                    <button type="button" className="btn btn-primary btn-lg" onClick={register}>Sign Up</button>
                    <p className="small fw-bold mt-2 pt-1 mb-0">Login to your account <a href="login" className="link-danger">Login</a></p>
                  </div>
   
                </form>
              </div>
              <div className="col-md-9 col-lg-6 col-xl-5">
                <img src={imgs[0]} className="img-fluid"/>
              </div>
            </div>
          </div>
        </div>
  );
};
  
export default SignUp;
C:\react-js\my-app\src\components\login.js
//C:\react-js\my-app\src\components\login.js
import React, {useState} from "react";
import axios from "axios";
import { useNavigate } from 'react-router-dom'
import loginimg from './login.png';
import {setToken} from './Auth.js'

const Login = () => {
	const [email, setEmail] = useState("");
	const [password, setPassword] = useState("");
   
	const [error, setError] = useState('')
	const navigate = useNavigate()
	
	const login = (e) => {
		e.preventDefault();
		axios.post("http://localhost:3001/login", {
		  email: email,
		  password: password,
		})
		.then(res => {
			console.log(res);
			if(res.data.Status === 'Success') {
        console.log(res.data.Token);
        setToken(res.data.Token)
				navigate('/profile');
			} else {
				setError(res.data.Error);
			}
		})
		.catch(err => console.log(err));
	}
   
  return (
        <div className="container" style={{paddingTop: 60}}>
          <div className="container-fluid h-custom">
            <div className="row d-flex justify-content-center align-items-center h-100">
              <div className="col-md-9 col-lg-6 col-xl-5">
                <img src={loginimg} className="img-fluid"/>
              </div>
              <div className="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
                <form>
                  <div className="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
                    <p className="lead fw-normal mb-0 me-3">Login to your account</p>
                  </div>
                    <h1 style={{color: 'red', fontSize: '15px', textAlign: 'center', marginTop: '20px'}}>{error && error}</h1>
                  <div className="form-outline mb-4">
                    <input
                      type="email"
                      className="form-control form-control-lg"
                      placeholder="Enter a valid email address"
                      onChange={(e) => {setEmail(e.target.value)}} required
                    />
                    <label className="form-label">Email address</label>
                  </div>
                  <div className="form-outline mb-3">
                    <input
                      type="password"
                      className="form-control form-control-lg"
                      placeholder="Enter password"
                      onChange={(e) => {setPassword(e.target.value)}} required
                    />
                    <label className="form-label">Password</label>
                  </div>
   
                  <div className="d-flex justify-content-between align-items-center">
                    <div className="form-check mb-0">
                      <input className="form-check-input me-2" type="checkbox" value=""/>
                      <label className="form-check-label">
                        Remember me
                      </label>
                    </div>
                    <a href="#" className="text-body">Forgot password?</a>
                  </div>
   
                  <div className="text-center text-lg-start mt-4 pt-2">
                    <button type="button" className="btn btn-primary btn-lg" onClick={login}>Login</button>
                    <p className="small fw-bold mt-2 pt-1 mb-0">Login to your account <a href="signup" className="link-danger">Sign Up</a></p>
                  </div>
   
                </form>
              </div>
            </div>
          </div>
        </div>
  );
};
  
export default Login;
C:\react-js\my-app\src\components\Auth.js
//C:\react-js\my-app\src\components\Auth.js
import React, { } from "react";
 
import {
    Navigate ,
    useLocation
  } from "react-router-dom";
export const setToken = (token) =>{
    // set token in localStorage
    localStorage.setItem('Token', token)
}
export const fetchToken = (token) =>{
    // fetch the token
    return localStorage.getItem('Token')
}
export function RequireToken({children}) {
     
    let auth = fetchToken()
    let location = useLocation();
   
    if (!auth) {
       
      return <Navigate to="/login" state={{ from: location }} />;
    }
   
    return children;
}
C:\react-js\my-app\src\components\profile.js
//C:\react-js\my-app\src\components\profile.js
import React, { } from "react";
import {useNavigate} from "react-router-dom";
 
export default function Profile(){
    const navigate = useNavigate();
    const signOut = () => {
        localStorage.removeItem('Token')
        navigate("/login");
    }
    return(
      <div className="container" style={{paddingTop: 60}}>
        <div className="row">
            <div style = {{minHeight: 800, marginTop: 20 }}>
                <h1>Profile Page</h1>
                <p>Hi, this is your profile</p>
                <div>
                    <button type = 'button' className="btn btn-success btn-lg" onClick= {signOut}>Sign Out</button>
                </div>
            </div>
        </div>  
      </div>
    )
}
Install axios
https://github.com/axios/axios

Installing the Axios Client
$ npm install axios
C:\reactdev\myreactdev>npm install axios

Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save

//react-js\my-app\public\index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css">
  </head>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>
Run C:\react-j\my-app>npm start
http://localhost:3000/

Related Post