Login Functionality for FastAPI Webapp

Git Commit: cookie-based authentication in fastapi
In this article, we are going to implement login functionality. Once someone logins into our web app, we would store an HttpOnly cookie in their browser which will be used to identify the user for future requests.
The template would be exactly the same as register.html with only a few modifications in the title, placeholder, and submit button text. templates > auth > login.html

{% extends "base.html" %}


{% block title %}
<title>Login</title>
{% endblock %}


{% block content %}

{% for error in errors %}
<div class="alert alert-danger">
    <li>{{error}}</li>
</div>
{% endfor %}

<div class="container">
    <div class="text-center display-4">Login</div>
    <div class="row mt-3 mb-5">
        <div class="col-3"></div>
        <div class="col-6">
            <form method="POST">
                <label>Email</label>
                <input type="email" required  class="form-control mb-2" name="email" value="{{email}}" placeholder="Enter your email">

                <label>Password</label>
                <input type="password" required placeholder="Enter your password" value="{{password}}" name="password" class="form-control mb-2">

                <button type="submit" class="btn btn-outline-success">Login</button>
            </form>
        </div>
        <div class="col-3"></div>
    </div>
</div>

{% endblock %}

Now, we can resort to implementing the routes responsible for login functionality. The GET route would be super simple, all it does is render a HTML page that has a form. In the POST route, we check whether the user can be authenticated, meaning, does a user exist with the same email and password? If the validation is successful, we create a token and store it in their cookie. To make it even more secure, we set the cookie to be HTTPOnly. So, only our backend can change the cookie. It can not be tampered by frontend javascript.

Finally, we redirect to the homepage with an alert message saying "Successfully Logged In".

import json

from db.repository.user import create_new_user
from db.session import get_db
from fastapi import APIRouter
from fastapi import Depends
from fastapi import Form
from fastapi import Request
from fastapi import responses
from fastapi import status
from fastapi.templating import Jinja2Templates
from pydantic.error_wrappers import ValidationError
from schemas.user import UserCreate
from sqlalchemy.orm import Session

#new imports
from apis.v1.route_login import authenticate_user
from core.security import create_access_token


templates = Jinja2Templates(directory="templates")
router = APIRouter()

## register  routes here 

@router.get("/login")
def login(request: Request):
    return templates.TemplateResponse("auth/login.html", {"request": request})


@router.post("/login")
def login(request: Request,
    email: str = Form(...),
    password: str = Form(...),
    db: Session = Depends(get_db),
):
    errors = []
    user = authenticate_user(email=email,password=password,db=db)
    if not user:
        errors.append("Incorrect email or password")
        return templates.TemplateResponse("auth/login.html", {"request": request,"errors":errors})
    access_token = create_access_token(data={"sub": email})
    response = responses.RedirectResponse(
            "/?alert=Successfully Logged In", status_code=status.HTTP_302_FOUND
        )
    response.set_cookie(key="access_token",value=f"Bearer {access_token}",httponly=True)
    return response


Time to test our implementation. Fingers crossed 🤞 Visit: http://127.0.0.1:8002/auth/login
 

FastAPITutorial

Brige the gap between Tutorial hell and Industry. We want to bring in the culture of Clean Code, Test Driven Development.

We know, we might make it hard for you but definitely worth the efforts.

Contacts

Refunds:

Refund Policy
Social

Follow us on our social media channels to stay updated.

© Copyright 2022-23 Team FastAPITutorial