article

Tuesday, March 21, 2023

React and FastAPI Login with PyJWT token authentication

React and FastAPI Login with PyJWT token authentication

Install Fastapi

https://github.com/tiangolo/fastapi

pip install fastapi
C:\fastAPI\react>pip install fastapi
C:\fastAPI\react>pip install "uvicorn[standard]"


Create main.py
react/main.py
 
#react/main.py
from fastapi import FastAPI
import jwt #pip install pyjwt https://pypi.org/project/PyJWT/
from pydantic import BaseModel
from fastapi.encoders import jsonable_encoder

SECRET_KEY = "cairocoders123456789"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 800

dummy_user = {
    "username": "cairocoders",
    "password": "123456ednalan",
}

from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_methods=["*"],
    allow_headers=["*"],
    allow_credentials=True,
    allow_origins=["http://localhost:3000"])

class Loginclass(BaseModel):
    username: str
    password: str
@app.get("/")
def read_root():
    return {"Hello": "World"}

@app.post("/login")
async def login_user(login_item: Loginclass):
    data = jsonable_encoder(login_item)
    if dummy_user['username'] == data['username'] and dummy_user['password'] == data['password']:
        encoded_jwt = jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
        return {'token': encoded_jwt }
    else:
        return {'message': 'Login failed'}
install PyJWT
https://github.com/jpadilla/pyjwt

pip install PyJWT
C:\fastAPI\react>pip install PyJWT

Rn C:\fastAPI\react>uvicorn main:app --reload 

http://127.0.0.1:8000/docs

React JS
Create Project
C:\react-js>npx create-react-app myreactdev

Run
C:\react-js\myreactdev> npm start

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

Install Axios
https://www.npmjs.com/package/axios
C:\react-js\myreactdev>npm install axios --save

C:\react-js\myreactdev\src\App.js
//C:\react-js\myreactdev\src\App.js
import React, { } from 'react';
import './App.css';

import {BrowserRouter, Routes, Route, Link} from 'react-router-dom';

import Login from './components/Login.js'
import Profile from './components/Profile.js'
import {RequireToken} from './components/Auth.js'

function App() {
  return (
    <div className="vh-100 gradient-custom">
    <div className="container">
      <h1 className="page-header text-center">React and FastAPI Login with PyJWT token authentication</h1>
 
      <BrowserRouter>
        <p><Link to="/" className="btn btn-success">Login</Link> | <Link to="profile" className="btn btn-success">Profile</Link> </p>
 
        <Routes>
			<Route path="/" element={<Login />} />
			<Route
			  path="/profile"
			  element={
				<RequireToken>
				  <Profile />
				</RequireToken>
			  }
			/>
        </Routes>
      </BrowserRouter>
    </div>
    </div>
  );
}
 
export default App;
open index.html C:\react-js\myreactdev\public\index.html add bootstrap 5 <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
Login.js
C:\react-js\myreactdev\src\components\Login.js
//C:\react-js\myreactdev\src\components\Login.js
import React, { useState } from 'react';
import axios from 'axios';
import {useNavigate} from "react-router-dom";
import {setToken, fetchToken} from './Auth.js'

export default function Login(){
	const navigate = useNavigate();
	const [username,setUsername] = useState('');
	const [password,setPassword] = useState('');
 
	const handleSubmit = () => {
		if(username.length === 0){
		  alert("Username has left Blank!");
		}
		else if(password.length === 0){
		  alert("password has left Blank!");
		}
		else{
			console.log('axios')
			axios.post('http://localhost:8000/login', {
				username: username,
				password: password
			})
			.then(function (response) {
				console.log(response);
				//console.log(response.data);
				alert(response.data["message"])
				if (response.data["message"]=="Login failed") {
					alert("Login failed");
				}else {	
					if(response.data.token){
						setToken(response.data.token)
						navigate("/profile");
					}
				}
			})
			.catch(function (error) {
				console.log(error, 'error');
			});
		}
	}
  return (
    <div>
      <div className="mask d-flex align-items-center h-100 gradient-custom-3">
        <div className="container h-100">
            <div className="row d-flex justify-content-center align-items-center h-100">
            <div className="col-12 col-md-9 col-lg-7 col-xl-6">
            <div className="card">
              <div className="card-body p-5">
			  {
                fetchToken() 
                ? (
                    <p>You are logged in!</p>
                )
				: (
					<p>Login Account!</p>
				)
			  }	
                <form>
                  
				  <div className="form-outline mb-4">
                    <label className="form-label">Your User Name</label>
                    <input type="text" className="form-control form-control-lg" name="username" id="username" value={username} onChange={(e) => setUsername(e.target.value)} />
                  </div>
				  
                  <div className="form-outline mb-4">
                    <label className="form-label">Your Password</label>
                    <input type="text" className="form-control form-control-lg" name="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} />
                  </div>
				  

                  <div className="d-flex justify-content-center">
                  <input type="button" className="btn btn-success btn-lg" name="submit" id="submit" value="Login" onClick={handleSubmit} />
                  </div>
 
                </form>
            </div>
            </div>
            </div>
            </div>
        </div>
      </div>
    </div>
  );
}
Profile.js
C:\react-js\myreactdev\src\components\Profile.js
//C:\react-js\myreactdev\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('cairocodersToken')
        navigate("/");
    }
    return(
        <>
            <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>
            
        </>
    )
}
Auth.js
C:\react-js\myreactdev\src\components\Auth.js
//C:\react-js\myreactdev\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('cairocodersToken', token)
}
export const fetchToken = (token) =>{
    // fetch the token
    return localStorage.getItem('cairocodersToken')
}
export function RequireToken({children}) {
    
    let auth = fetchToken()
    let location = useLocation();
  
    if (!auth) {
      
      return <Navigate to="/" state={{ from: location }} />;
    }
  
    return children;
}
react-js\myreactdev\src\App.css
//react-js\myreactdev\src\App.css
.card {
  border-radius: 15px;
}
.gradient-custom {
  background: linear-gradient(to bottom right, rgba(240, 147, 251, 1), rgba(245, 87, 108, 1));
}
Run C:\react-j\myreactdev>npm start
http://localhost:3000/

Related Post