Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastAPI Template API

⚠️ Note: This is a lightweight, startup-friendly template designed for small to mid-sized apps with a low userbase and authenticated users only. It intentionally keeps things simple — no Redis caching, no advanced queue systems, no heavy load-prevention infrastructure. If you're building an MVP, side project, or internal tool that needs to handle thousands of users, this is a clean and solid starting point. For larger scale, you'll want to layer on caching (Redis), a task queue (Celery/RQ), and a more advanced rate-limiter (e.g., API gateway or slowapi with Redis backend).

A passwordless authentication backend built with FastAPI, SQLAlchemy (async), and PostgreSQL. Supports OTP login via email, Google OAuth, and includes rate limiting with SlowAPI — no passwords, no password reset, just simple and secure authentication.

✨ Features

  • 🔐 Passwordless Auth — OTP via email + Google OAuth (no passwords needed)
  • 📱 Support Both Web/Mobile — One API use anywhere
  • 📧 Email OTP — 6-digit codes sent via Resend
  • 🔑 Google OAuth — One-click sign-in with Google
  • 🍪 Dual Client Support — httpOnly cookies for web, tokens in body for mobile
  • 🛡️ CSRF Protection — Middleware-based CSRF protection for cookie auth
  • 🔄 Refresh Tokens — Long-lived refresh tokens with database-backed revocation
  • 🐘 Async PostgreSQL — SQLAlchemy 2.0 async with asyncpg
  • FastAPI — High-performance async Python API
  • 🐌 Rate LimitingSlowAPI for API abuse prevention
  • 🗄️ Alembic Migrations — Production-ready database migrations
  • 🌍 CORS — Configurable cross-origin resource sharing
  • 🏥 Health Check — Database connectivity monitoring

🏗️ Tech Stack

Layer Technology
Framework FastAPI
Database PostgreSQL (async via asyncpg)
ORM SQLAlchemy 2.0 (async)
Migrations Alembic
Auth JWT (PyJWT) + Google OAuth
Email Resend
Rate Limiting SlowAPI
Validation Pydantic v2
Config pydantic-settings

📁 Project Structure

.
├── app/
│   ├── __init__.py
│   ├── main.py                  # FastAPI app entry point, SlowAPI setup
│   ├── api/
│   │   └── v1/
│   │       ├── __init__.py      # API router aggregation
│   │       ├── auth.py          # Authentication endpoints (rate-limited)
│   │       └── health.py        # Health check endpoint
│   ├── core/
│   │   ├── config.py            # Pydantic settings (env vars)
│   │   └── database.py          # Async SQLAlchemy engine & session
│   ├── deps/
│   │   └── auth.py              # Auth dependencies (get_current_user)
│   ├── helpers/
│   │   ├── google_auth.py       # Google token verification
│   │   └── handle_cookies.py    # Cookie utilities (set/clear auth cookies)
│   ├── middleware/
│   │   └── auth.py              # CSRF protection middleware
│   ├── models/
│   │   ├── app_users.py         # User model (OTP + Google)
│   │   ├── otp_code.py          # OTP codes model
│   │   └── refresh_token.py     # Refresh tokens model
│   ├── schemas/
│   │   └── auth_schema.py       # Pydantic request/response schemas
│   ├── templates/
│   │   ├── otp_email.html       # HTML email template
│   │   └── otp_email.txt        # Plain text email template
│   └── utils/
│       ├── auth_util.py         # JWT creation, hashing, CSRF token
│       ├── device_check.py      # Mobile vs Web client detection
│       ├── email_otp.py         # OTP email sending via Resend
│       └── otp_generator.py     # OTP code generation & hashing
├── alembic/                     # Alembic migration files
│   ├── versions/
│   ├── env.py
│   └── script.py.mako
├── templates/
│   ├── otp_email.html           # HTML email template (legacy)
│   └── otp_email.txt            # Plain text email template (legacy)
├── .env.example                 # Environment variables template
├── .gitignore
├── alembic.ini                  # Alembic configuration
├── requirements.txt
└── README.md

🚀 Quick Start

Prerequisites

  • Python 3.14+
  • PostgreSQL (running locally or remote)
  • Google Cloud Console project (for OAuth)
  • Resend account (for sending OTP emails)

1. Clone the repository

git clone https://github.com/mvish77/fastapi-basic-template.git
cd fastapi-basic-template

2. Create a virtual environment

python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate

3. Install dependencies

pip install -r requirements.txt

4. Set up environment variables

cp .env.example .env

Edit .env with your values (see Environment Variables below).

5. Create the database

# Using psql
createdb your_database

# Or using any PostgreSQL client, create your database

6. Run database migrations

alembic upgrade head

7. Run the server

uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

The API will be available at:

  • API: http://localhost:8000
  • Swagger Docs: http://localhost:8000/docs
  • ReDoc: http://localhost:8000/redoc

🌐 API Endpoints

Authentication

Method Endpoint Description Rate Limit
POST /api/v1/auth/send-otp Send 6-digit OTP to email 5 / 5 min
POST /api/v1/auth/verify-otp Verify OTP & login/signup 5 / 5 min
POST /api/v1/auth/google Google OAuth login/signup 5 / 5 min
POST /api/v1/auth/refresh Refresh access token Default
POST /api/v1/auth/logout Logout & revoke refresh token Default
GET /api/v1/auth/csrf-token Get CSRF token (web only) Default
GET /api/v1/auth/me Get current user info Default

System

Method Endpoint Description
GET / Root endpoint (app info)
GET /api/v1/health Health check (API + DB status)

🔐 Authentication Flow

OTP Login / Signup

1. Client sends email → POST /api/v1/auth/send-otp
2. Server generates 6-digit OTP, sends via Resend email
3. User receives OTP in email (valid for 10 minutes)
4. Client submits email + OTP → POST /api/v1/auth/verify-otp
5. Server verifies OTP (SHA-256 hash comparison):
   - New email → Auto-creates account (signup)
   - Existing email → Logs in (login)
6. Returns JWT tokens:
   - Web: httpOnly cookies (access_token + refresh_token)
   - Mobile: Tokens in response body

Google OAuth Login

1. Client initiates Google OAuth flow (frontend)
2. Google returns ID token to client
3. Client sends ID token → POST /api/v1/auth/google
4. Server verifies token with Google
5. Returns JWT tokens (same as OTP flow)

Token Refresh

1. Access token expires (24 hours)
2. Client sends refresh token → POST /api/v1/auth/refresh
3. Server validates refresh token against database
4. Returns new access token
5. Refresh tokens are long-lived (30 days) and can be revoked on logout

📧 Email (OTP) — Resend

This project uses Resend for sending OTP emails.

Development Mode

When RESEND_API_KEY is not set, OTP codes are logged to the console instead of being sent via email. This allows local development without an email service.

============================================================
📧 DEV MODE: OTP Email
============================================================
To: user@example.com
OTP Code: 482916
Valid for: 10 minutes
============================================================

Production Mode

Set these environment variables to enable email delivery:

RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxxxxxxx
EMAIL_FROM=My App <noreply@your_domain.com>
APP_NAME=My App
APP_URL=https://your_domain.com

You'll need to verify your sending domain in Resend before sending emails in production.

🔑 Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create a project (or select existing)
  3. Navigate to APIs & Services → Credentials
  4. Create OAuth 2.0 Client ID (Web application type)
  5. Add authorized redirect URIs
  6. Copy the Client ID and Client Secret to your .env:
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret

🐌 Rate Limiting — SlowAPI

This project uses SlowAPI for request rate limiting.

Default Limits

  • Global: 100 requests/minute per IP
  • Auth endpoints (send-otp, verify-otp, google): 5 requests per 5 minutes per IP

How It Works

Rate limits are applied per IP address using SlowAPI's @limiter.limit() decorator. When a limit is exceeded, the API returns a 429 Too Many Requests response.

Scaling note: The default in-memory rate limiter works fine for single-server deployments. For distributed setups, configure SlowAPI with a Redis backend.

🗄️ Database Migrations — Alembic

This project uses Alembic for database migrations.

Common Commands

# Apply all migrations
alembic upgrade head

# Rollback one migration
alembic downgrade -1

# Generate a new migration after model changes
alembic revision --autogenerate -m "description of changes"

# View migration history
alembic history

⚙️ Environment Variables

Copy .env.example to .env and configure:

# ─── JWT Authentication ─────────────────────────────────
JWT_SECRET_KEY=your-256-bit-secret     # Generate a secure random key
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=1440   # 24 hours
JWT_REFRESH_TOKEN_EXPIRE_DAYS=30       # 30 days

# ─── CSRF Protection ────────────────────────────────────
CSRF_SECRET_KEY=your-csrf-secret       # Generate a secure random key
CSRF_TOKEN_EXPIRE_MINUTES=60

# ─── Google OAuth ───────────────────────────────────────
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

# ─── Resend Email Service ───────────────────────────────
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxxxxxxx
EMAIL_FROM=My App <noreply@your_domain.com>
APP_NAME=My App
APP_URL=https://your_domain.com

# ─── OTP Settings ───────────────────────────────────────
OTP_EXPIRY_MINUTES=10

# ─── Cookie Domain ──────────────────────────────────────
MY_DOMAIN=localhost               # e.g., .your_domain.com for all subdomains

⚠️ Never commit .env to version control. Always use .env.example as a template.

🛡️ Security Features

Feature Description
Passwordless No passwords to store, leak, or reset
OTP Expiry Codes expire after 10 minutes
OTP Rate Limiting 5 requests per 5 min per IP on auth endpoints
Global Rate Limiting 100 requests/minute per IP (configurable)
OTP Hash Verification OTPs stored and verified using SHA-256 hashing
Previous OTP Invalidation New OTP deletes unused old ones
CSRF Middleware Automatic CSRF protection for cookie-based auth
httpOnly Cookies Tokens stored in httpOnly cookies for web (XSS-safe)
Token Revocation Refresh tokens revoked on logout, stored hashed in DB
Secure Cookies Secure + SameSite flags in production
Docs Disabled Swagger/ReDoc disabled in production

🗄️ Database Models

AppUser

Column Type Description
user_id UUID (PK) Auto-generated user ID
email String(150) Unique, indexed email
display_name String(100) User's display name
avatar_url Text Profile picture URL
auth_provider Enum email_otp or google
google_id String(255) Google OAuth ID (nullable)
status Enum active, suspended, deleted
role Enum user, admin, super_admin
email_verified Boolean Auto-verified via OTP/Google
last_login_at Timestamp Last login time
created_at Timestamp Account creation time
updated_at Timestamp Last update time

OTPCode

Column Type Description
email String Email address
otp_code String 6-digit OTP (plaintext for dev)
otp_hash String SHA-256 hash of OTP
is_verified Boolean Whether OTP was used
attempts Integer Failed verification attempts
expires_at Timestamp OTP expiration time

RefreshToken

Column Type Description
token_hash String SHA-256 hash of refresh token
user_id UUID (FK) Associated user
expires_at Timestamp Token expiration
device_info String User-Agent string
revoked_at Timestamp When token was revoked

📂 Client Type Detection

The API automatically detects whether the client is a web browser or mobile app and responds accordingly:

Web Browser Mobile App
Auth method httpOnly cookies Authorization: Bearer header
Token storage Response cookies Response body
Refresh flow Cookie-based Request body
CSRF Required (middleware-protected) Not required

🧪 Development

Running in Development

uvicorn app.main:app --reload
  • Swagger docs available at /docs
  • OTP codes logged to console (no email required)
  • Rate limits still apply

Production Build

ENV=production uvicorn app.main:app --host 0.0.0.0 --port 8000
  • Swagger/ReDoc/OpenAPI are disabled
  • Secure cookie flags are enabled
  • Use Alembic for database migrations

📋 Checklist: Before Going Live

  • Generate secure JWT_SECRET_KEY and CSRF_SECRET_KEY
  • Set up Resend account and verify sending domain
  • Configure Google OAuth credentials
  • Set ENV=production
  • Configure MY_DOMAIN for your production domain
  • Update CORS_ALLOWED_ORIGINS for your frontend URL
  • Run alembic upgrade head on production database
  • Remove any debug/logging of OTP codes in production

📄 License

This project is open source and available under the MIT License.


Built with ❤️ using FastAPI

About

A production-ready passwordless authentication backend built with FastAPI, SQLAlchemy (async), and PostgreSQL. Supports OTP login via email and Google OAuth - no passwords, no password reset, just simple and secure authentication.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages