How to Create a Login Endpoint in FastAPI Quickly
To create a login endpoint in
FastAPI, define a POST route that accepts user credentials, verifies them, and returns an access token. Use OAuth2PasswordRequestForm to handle form data and fastapi.security utilities for token creation and validation.Syntax
The login endpoint in FastAPI typically uses a POST method with OAuth2PasswordRequestForm to receive username and password. You verify credentials, then return a token for authentication.
@app.post("/login"): Defines the login route.OAuth2PasswordRequestForm: Parses form data for username and password.Depends: Injects dependencies like the form data.return: Sends back an access token and token type.
python
from fastapi import FastAPI, Depends from fastapi.security import OAuth2PasswordRequestForm app = FastAPI() @app.post("/login") async def login(form_data: OAuth2PasswordRequestForm = Depends()): username = form_data.username password = form_data.password # Verify username and password here access_token = "token_example" return {"access_token": access_token, "token_type": "bearer"}
Example
This example shows a complete login endpoint that checks a hardcoded user and password, then returns a JWT token if valid. It uses passlib to hash passwords and PyJWT to create tokens.
python
from fastapi import FastAPI, Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm from passlib.context import CryptContext import jwt from datetime import datetime, timedelta app = FastAPI() pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") SECRET_KEY = "your_secret_key" ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 fake_user_db = { "johndoe": { "username": "johndoe", "hashed_password": pwd_context.hash("secret123") } } def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) def authenticate_user(username: str, password: str): user = fake_user_db.get(username) if not user: return False if not verify_password(password, user["hashed_password"]): return False return user def create_access_token(data: dict, expires_delta: timedelta = None): to_encode = data.copy() expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15)) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt @app.post("/login") async def login(form_data: OAuth2PasswordRequestForm = Depends()): user = authenticate_user(form_data.username, form_data.password) if not user: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}, ) access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token( data={"sub": user["username"]}, expires_delta=access_token_expires ) return {"access_token": access_token, "token_type": "bearer"}
Output
When you POST username and password to /login, you get a JSON response with an access_token string and token_type "bearer".
Common Pitfalls
- Not hashing passwords before storing or verifying them, which is insecure.
- Returning plain passwords or sensitive info in responses.
- Not setting proper HTTP status codes like 401 for failed login.
- Ignoring token expiration and refresh mechanisms.
- Using GET instead of POST for login, which exposes credentials in URLs.
python
from fastapi import FastAPI, Depends from fastapi.security import OAuth2PasswordRequestForm app = FastAPI() # Wrong: Accepting password as plain text without hashing @app.post("/login_wrong") async def login_wrong(form_data: OAuth2PasswordRequestForm = Depends()): if form_data.username == "user" and form_data.password == "pass": return {"token": "fake-token"} return {"error": "Invalid credentials"} # Right: Use hashed passwords and proper error handling from fastapi import HTTPException, status @app.post("/login_right") async def login_right(form_data: OAuth2PasswordRequestForm = Depends()): # Imagine verify_password is implemented if form_data.username != "user" or form_data.password != "pass": raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials") return {"access_token": "real-token", "token_type": "bearer"}
Quick Reference
Remember these key points when creating a login endpoint in FastAPI:
- Use
POSTmethod withOAuth2PasswordRequestFormto get username and password. - Always hash passwords before storing or verifying.
- Return a JWT or similar token with expiration for authentication.
- Use proper HTTP status codes like 401 for unauthorized access.
- Keep your
SECRET_KEYsafe and never expose it.
Key Takeaways
Use POST with OAuth2PasswordRequestForm to securely receive login data.
Always hash and verify passwords; never store or compare plain text passwords.
Return a JWT token with expiration to authenticate users after login.
Handle failed logins with HTTP 401 Unauthorized status.
Keep your secret keys private and use secure token algorithms.