Login Process

How the login process works

  1. User logs in with username and password

  2. API checks for user in the database

  3. API checks for the users password if user is found

  4. API hashes password provided again

  5. The hashed password provided should match the hashed password in the database

  6. If they match, user receives token

How to code this

  • Fist we will have to set up a auth.py file to keep it separate in the routers folder

    • This makes more sense then having it in a single file

from fastapi import APIRouter, Depends, status, HTTPException, Response
from sqlalchemy.orm import Session

from .. import database 

router = APIRouter(
    tags=['Authentification']
)

@router.post("/login")
def login(db: Session = Depends(database.get_db())):
    pass 
  • We also need to create a schema for the user login

class UserLogin(BaseModel):
    email: EmailStr
    password: str
  • Now we will store this in our function

@router.post("/login")
def login(user_credentials: schemas.UserLogin, db: Session = Depends(database.get_db())):
    pass 
  • We have to make a request to our database, specifically our users table to retrieve the user based on email

from .. import database, schemas, models

@router.post("/login")
def login(user_credentials: schemas.UserLogin, db: Session = Depends(database.get_db())):
    

    user = db.query(models.User).filter(models.User.email == user_credentials.email).first
  • If we do not have a user, we need to raise an exception

@router.post("/login")
def login(user_credentials: schemas.UserLogin, db: Session = Depends(database.get_db())):
    

    user = db.query(models.User).filter(models.User.email == user_credentials.email).first

    if not user:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Invalid Credentials")
  • Now that we have the password, we need to compare this to the hashed password in our database

  • First we need to hash the provided password (we will create this in the utils.py file)

def verify(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

The beauty about CryptContext is that it has the .verify method which allows us to hash the password and compare it directly without additional logic

  • Now we can import this function in our auth.py file and verify the password

  • Additionally raise an exception if the password does not match

from .. import database, schemas, models, utils

@router.post("/login")
def login(user_credentials: schemas.UserLogin, db: Session = Depends(database.get_db())):
    

    user = db.query(models.User).filter(models.User.email == user_credentials.email).first()

    if not user:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Invalid Credentials")

    # Password Verification
    if not utils.verify(user_credentials.password, user.password):
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Invalid Credentials")

Next steps would be:

  • Create Token

  • Return Token

Last updated