Implement frontend user login

This commit is contained in:
2021-12-20 13:04:55 +01:00
parent dea9fd0bde
commit 774032a9fe
7 changed files with 229 additions and 10 deletions

74
backend/auth.py Normal file
View File

@@ -0,0 +1,74 @@
import os
import json
from fastapi import APIRouter, Depends, HTTPException, status, Header
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from passlib.context import CryptContext as PasswordContext
from cryptography.fernet import Fernet, InvalidToken, InvalidSignature
from models import User
AUTH_ERROR = HTTPException(status.HTTP_400_BAD_REQUEST)
password_context = PasswordContext(schemes=["bcrypt"], deprecated="auto")
SECRET_KEY = os.environ["SECRET_KEY"]
crypto_context = Fernet(SECRET_KEY)
users_db = {
"kai": {
"username": "kai",
"hashed_password": "$2b$12$mh5hSniE.1SqxK3IDDTIO.1jDKgU0KX2eZev3yFu4Z1ZUPXWMw2Xa",
}
}
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login")
class UserInDb(User):
hashed_password: str
def get_current_user(token: str = Depends(oauth2_scheme)):
try:
token_data = json.loads(crypto_context.decrypt(token.encode()))
except (InvalidToken, InvalidSignature):
raise AUTH_ERROR
return User(username=token_data["username"])
auth_router = APIRouter()
class TokenLoginResponse(BaseModel):
access_token: str
token_type: str
@auth_router.post(
"/login",
tags=["auth"],
responses={
status.HTTP_400_BAD_REQUEST: {},
status.HTTP_200_OK: {
"model": TokenLoginResponse,
},
},
)
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
if form_data.username not in users_db:
raise AUTH_ERROR
user = UserInDb(**users_db[form_data.username])
if not password_context.verify(form_data.password, user.hashed_password):
raise AUTH_ERROR
token = crypto_context.encrypt(json.dumps({"username": user.username}).encode())
return {
"access_token": token,
"token_type": "bearer",
}

View File

@@ -1,7 +1,9 @@
from fastapi import FastAPI, Response
from pydantic import BaseSettings
from fastapi import FastAPI, Depends, Response
from fastapi.staticfiles import StaticFiles
from pydantic import BaseSettings, BaseModel
from models import User
from auth import get_current_user, auth_router
class Settings(BaseSettings):
@@ -11,6 +13,19 @@ class Settings(BaseSettings):
settings = Settings()
app = FastAPI()
app.include_router(
auth_router,
prefix="/auth",
tags=["auth"]
)
@app.get("/test")
async def read_test(user = Depends(get_current_user)):
return {"name": user.username, "foo": "bar"}
if settings.dev_mode:
import httpx

4
backend/models.py Normal file
View File

@@ -0,0 +1,4 @@
from pydantic import BaseModel
class User(BaseModel):
username: str

View File

@@ -1,16 +1,22 @@
anyio==3.4.0
asgiref==3.4.1
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.9
click==8.0.3
cryptography==36.0.1
fastapi==0.70.1
h11==0.12.0
httpcore==0.14.3
httpx==0.21.1
idna==3.3
passlib==1.7.4
pycparser==2.21
pydantic==1.8.2
python-multipart==0.0.5
rfc3986==1.5.0
six==1.16.0
sniffio==1.2.0
starlette==0.16.0
typing-extensions==4.0.1
uvicorn==0.16.0
uvicorn==0.15.0