Skip to main content

A simple and robust OTP (One-Time Password) authentication library for FastAPI, backed by Redis and Email.

Project description

FastAPI OTP Auth

PyPI License: MIT

A simple and robust OTP (One-Time Password) authentication library for FastAPI, backed by Redis and Email.

Why OTP?

Passwords are a pain. Users forget them, reuse them, and they are a prime target for attackers. Storing them securely is a liability.

FastAPI OTP Auth solves this by eliminating passwords entirely:

  • 🧠 No Memory Required: Users don't need to remember complex passwords.
  • 💾 Zero Password Storage: You don't have to worry about hashing, salting, or leaking passwords.
  • 🔄 Simplified Flows: No more "Forgot Password" or "Reset Password" complexity.
  • 🛡️ Enhanced Security: OTPs are short-lived and one-time use, mitigating credential stuffing and replay attacks.

Features

  • 🔐 Secure OTP Generation: Cryptographically secure 6-digit codes.
  • 🎫 JWT Support: Auto-generates Access and Refresh tokens upon verification.
  • 🍪 HttpOnly Cookies: Securely stores refresh tokens in HttpOnly cookies.
  • Redis-Backed: Fast and reliable storage for OTPs with automatic expiration.
  • 📧 Email Delivery: Integrated email sending using fastapi-mail.
  • 🔌 Easy Integration: Drop-in APIRouter for quick setup.
  • ⚙️ Configurable: Fully customizable via environment variables.
  • 🚫 Token Blacklisting: Secure logout and immediate token revocation.

Installation

pip install fastapi-otp-auth

Or using uv:

uv add fastapi-otp-auth

Configuration

The library is configured using environment variables. The prefix for all variables is FASTAPI_OTP_AUTH_.

Variable Description Default
FASTAPI_OTP_AUTH_REDIS_URL Connection string for Redis redis://localhost:6379/0
FASTAPI_OTP_AUTH_SMTP_SERVER SMTP server hostname 127.0.0.1
FASTAPI_OTP_AUTH_SMTP_PORT SMTP server port 1025
FASTAPI_OTP_AUTH_SMTP_USERNAME SMTP username user@example.com
FASTAPI_OTP_AUTH_SMTP_PASSWORD SMTP password password
FASTAPI_OTP_AUTH_MAIL_FROM_NAME Sender name for emails FastAPI App
FASTAPI_OTP_AUTH_OTP_EXPIRY_SECONDS OTP validity duration in seconds 300 (5 minutes)
FASTAPI_OTP_AUTH_OTP_KEY_PREFIX Prefix for Redis keys otp_
FASTAPI_OTP_AUTH_JWT_SECRET Secret key for signing JWTs change-me-in-production
FASTAPI_OTP_AUTH_JWT_ALGORITHM Algorithm for JWTs HS256
FASTAPI_OTP_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES Access token lifetime 60 (1 hour)
FASTAPI_OTP_AUTH_REFRESH_TOKEN_EXPIRE_DAYS Refresh token lifetime 7 (7 days)
FASTAPI_OTP_AUTH_BLACKLIST_KEY_PREFIX Prefix for blacklisted tokens in Redis blacklist_
FASTAPI_OTP_AUTH_DISABLE_LOCAL_AUTH Enable "Magic OTP" flow (skips email, accepts 000000) False

Local Development (Magic OTP)

To simplify local development and testing, you can enable the "Magic OTP" flow. This allows you to log in as any user using the fixed OTP code 000000, without sending actual emails with the OTP.

  1. Set FASTAPI_OTP_AUTH_DISABLE_LOCAL_AUTH=true in your local .env file or environment.
  2. Request an OTP for any email (e.g., test@example.com).
  3. Verify using the code 000000.

[!WARNING] Security Risk: Ensure this environment variable is NEVER set to true in production environments.

Usage

Import the auth_router and include it in your FastAPI application:

from fastapi import FastAPI
from fastapi_otp_auth.auth_router import router as auth_router

app = FastAPI()

# Include the router
app.include_router(auth_router, prefix="/auth", tags=["Authentication"])

# The following endpoints will be available:
# POST /auth/request-otp - Request a new OTP
# POST /auth/verify-otp  - Verify a received OTP
# POST /auth/logout      - Logout and blacklist tokens

Requesting an OTP

Send a POST request to /auth/request-otp:

{
  "email": "user@example.com"
}

Verifying an OTP

Send a POST request to /auth/verify-otp:

{
  "email": "user@example.com",
  "otp": "123456"
}

On success, the response will contain the access token, and the refresh token will be set as an HttpOnly cookie:

{
  "message": "OTP verified successfully!",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Protecting Routes

Use the get_current_user dependency to protect routes. This will verify the access token and return the user's email.

from fastapi import Depends
from fastapi_otp_auth.dependencies import get_current_user

@app.get("/protected")
async def protected_route(user: str = Depends(get_current_user)):
    return {"message": f"Hello, {user}!"}

Refreshing Tokens

To get a new access token using the HttpOnly refresh token cookie, send a POST request to /auth/refresh. The browser will automatically include the cookie.

POST /auth/refresh

Response:

{
  "access_token": "new_access_token_here",
  "token_type": "bearer"
}

### Logging Out

To logout, send a POST request to `/auth/logout`. This will blacklist both the access token (provided in the Authorization header) and the refresh token (provided in the cookie).

```bash
POST /auth/logout
Authorization: Bearer <access_token>
Cookie: refresh_token=<refresh_token>

Response:

{
  "message": "Successfully logged out"
}

Development

To run tests locally using Docker (no local environment needed):

make test

This will spin up a Redis container and run the test suite in an isolated environment.

Running Checks

To run linting checks (ruff) using Docker:

docker-compose -f docker-compose.test.yml run --rm app-test uv run ruff check .

Pre-commit Hooks

To automatically run checks before every commit, install the pre-commit hooks:

uv run pre-commit install

You can also run the hooks manually against all files:

uv run pre-commit run --all-files

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_otp_auth-0.1.4.tar.gz (85.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_otp_auth-0.1.4-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_otp_auth-0.1.4.tar.gz.

File metadata

  • Download URL: fastapi_otp_auth-0.1.4.tar.gz
  • Upload date:
  • Size: 85.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastapi_otp_auth-0.1.4.tar.gz
Algorithm Hash digest
SHA256 87a159092e9d438892ecde3893b97d29530ece57c7f6c8efa13cc5569fefafe5
MD5 ee61162cd192582ab6b9d4e1e8642a09
BLAKE2b-256 8c51c2444e2b750dbecc505b6d5ec5a6d1f769d843ee0c63ffa1e3d769b18617

See more details on using hashes here.

File details

Details for the file fastapi_otp_auth-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: fastapi_otp_auth-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastapi_otp_auth-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 76023de95e5d8a93d217c5d0fb11e16a933c0047b3d84512c4525b6fe3c4212f
MD5 74e60e4f9984ae5650a85d877a598400
BLAKE2b-256 287fe2d254238300d834f6abd1c8dec95c1d01cb65f4bb7a96c02794a281b3f2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page