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/
