This article explains how to integrate OAuth2PasswordRequestForm in FastAPI for handling user login credentials via form data instead of JSON.
In this lesson, we will modify our login route to retrieve user credentials from form data using FastAPI’s built-in dependency—OAuth2PasswordRequestForm. This change means that instead of sending credentials in the JSON body, the form data will include the default fields “username” and “password”. As a result, our code must reference “username” (which can be your email) rather than “email”.
Below is the initial version of the login endpoint that uses a custom schema (schemas.UserLogin):
Copy
Ask AI
from fastapi import APIRouter, Depends, status, HTTPException, Responsefrom sqlalchemy.orm import Sessionfrom .. import database, schemas, models, utils, oauth2router = APIRouter(tags=['Authentication'])@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: # Additional logic would go here pass
When running this code, you might see output similar to:
Copy
Ask AI
SyntaxError: invalid syntaxWARNING: WatchGodReload detected file change in ['C:\\Users\\sanje\\Documents\\Courses\\fastapi\\app\\routers\\auth.py', 'C:\\Users\\sanje\\Documents\\Courses\\fastapi\\app\\routers\\auth.py']. Reloading...WARNING: WatchGodReload detected file change in ['C:\\Users\\sanje\\Documents\\Courses\\fastapi\\app\\routers\\auth.py', 'C:\\Users\\sanje\\Documents\\Courses\\fastapi\\app\\routers\\auth.py']. Reloading...Database expansion was successfulINFO: Started server process [11820]INFO: Waiting for application startup.INFO: Application startup complete.INFO: 127.0.0.1:63905 - "POST /login HTTP/1.1" 200 OK
Updating the Login Endpoint with OAuth2PasswordRequestForm
To leverage FastAPI’s built-in support, import OAuth2PasswordRequestForm from fastapi.security. This dependency automatically extracts the credentials from form data. Note that the form now expects a field named “username” instead of “email”. Therefore, update the database query to filter using user_credentials.username.Below is the updated version of the login endpoint:
Copy
Ask AI
from fastapi import APIRouter, Depends, status, HTTPExceptionfrom fastapi.security import OAuth2PasswordRequestFormfrom sqlalchemy.orm import Sessionfrom .. import database, models, utilsrouter = APIRouter(tags=['Authentication'])@router.post('/login')def login(user_credentials: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(database.get_db)): user = db.query(models.User).filter( models.User.email == user_credentials.username ).first() if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Invalid Credentials" ) if not utils.verify(user_credentials.password, user.password): raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Invalid Credentials" ) # Additional token generation logic can be implemented here.
When testing this endpoint, ensure that the credentials are sent as form data. The expected form fields are “username” (which can be an email) and “password”.
FastAPI now correctly expects the credentials in form data rather than JSON. When submitting the correct form data with “username” and “password”, the login endpoint should work as intended.An example successful response might look like:
Using OAuth2PasswordRequestForm simplifies handling credentials by automating the extraction of form data. This built-in functionality is aligned with FastAPI’s recommended practices and reduces the need for custom parsing.