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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//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
1
2
3
4
5
6
7
//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