Choorai
Advanced Topic

Implementing User Authentication

Implement user authentication features including login, signup, and password management. Learn the correct, security-conscious approach.

What You'll Learn in This Guide

  • Authentication method comparison (Session vs JWT)
  • Password hashing (bcrypt)
  • OAuth social login
  • Authentication services (Clerk, Auth0)

Authentication Method Comparison

Session-Based

Stores sessions on the server and passes session ID via cookies

  • Simple implementation
  • Can be invalidated immediately
  • Requires session sharing when scaling servers

JWT (Token-Based)

Client holds a signed token

  • No server state needed
  • Ideal for microservices
  • Difficult to handle token theft

Build Your Own vs Auth Services

Recommended: Use an Auth Service

Authentication is a security-sensitive area. We recommend using a proven auth service, especially when starting out.

Building your own can easily introduce security vulnerabilities and adds significant maintenance burden.

Recommended Auth Services

Looking for Supabase Auth? Check the Supabase Guide for auth integration instructions.

FastAPI + JWT Example (Reference)

If you must build your own, refer to the structure below:

app/auth.py
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta

# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# JWT configuration
SECRET_KEY = "your-secret-key"  # Use environment variables in production!
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

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

def create_access_token(data: dict):
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

async def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        user_id: str = payload.get("sub")
        if user_id is None:
            raise HTTPException(status_code=401, detail="Invalid token")
        return user_id
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")

Caution: Production Requires More Considerations

  • HTTPS is required
  • Manage secret keys with environment variables
  • Implement Refresh Tokens
  • Rate Limiting
  • Login attempt throttling

Which service should you choose?

Last updated: February 22, 2026 · Version: v0.0.1

Send Feedback

Opens a new issue page with your message.

Open GitHub Issue