Table of Contents
Features
- OAuth2 and JWT authentication built-in
- Role-based authorization system
- Cookie-based authentication option
- Token refresh mechanism for extended sessions
- SQLModel integration for easy database operations
- CLI utilities for database initialization and management (new in v0.3.0)
- Ready-to-use authentication routes with minimal setup
- Password hashing with bcrypt
- Modular architecture for better code organization and extensibility
Installation
pip install fastauth_iq
Or install from source:
git clone https://github.com/hu55ain3laa/fastauth.git
cd fastauth
pip install -e .
Quick Start
1. Create a User Model
FastAuth works with SQLModel's user model. You can use the built-in User model or create your own:
from sqlmodel import SQLModel, Field
class User(SQLModel, table=True):
id: int = Field(primary_key=True)
username: str = Field(unique=True)
email: str = Field(unique=True)
hashed_password: str
disabled: bool = Field(default=False)
2. Initialize FastAuth in Your Application
from fastapi import FastAPI, Depends
from sqlmodel import create_engine, Session, SQLModel
from fastauth import FastAuth, User
# Create FastAPI app
app = FastAPI()
# Setup database
engine = create_engine("sqlite:///./app.db")
# Session dependency
def get_session():
with Session(engine) as session:
yield session
# Initialize FastAuth with your configuration
auth = FastAuth(
secret_key="your-secure-secret-key", # Use strong secret in production
algorithm="HS256",
user_model=User,
engine=engine,
use_cookie=True, # Enable cookie-based auth (optional)
token_url="/token",
access_token_expires_in=30, # minutes
refresh_token_expires_in=7 # days
)
# Initialize database (choose ONE of these approaches):
# Option 1: Using the CLI tool before starting the application (new in v0.3.0)
# fastauth app.py # Auto-detect settings from your app file
# # Or use explicit parameters
# fastauth --db-url="sqlite:///./app.db" --secret-key="your-secret-key"
#
# Option 2: Initializing during application startup
INIT_DB_ON_STARTUP = True # Set to False to disable
@app.on_event("startup")
def on_startup():
if INIT_DB_ON_STARTUP:
auth.initialize_db(
create_tables=True, # Create database tables
init_roles=True, # Initialize standard roles
create_admin=True, # Create superadmin if needed
admin_username="superadmin", # Default username
admin_password="admin123" # Default password
)
# Add all authentication routes automatically
auth_router = auth.get_auth_router(get_session)
app.include_router(auth_router, tags=["authentication"])
# Add role management routes (new in v0.2.2)
role_router = auth.get_role_router()
app.include_router(role_router, tags=["roles"])
3. Protect Your Routes
# Require authentication only
@app.get("/protected")
def protected_route(current_user = Depends(auth.get_current_active_user_dependency())):
return {"message": f"Hello, {current_user.username}!"}
# Require specific roles (any of the listed roles)
@app.get("/admin-or-moderator")
def admin_or_mod_route(current_user = Depends(auth.require_roles(["admin", "moderator"]))):
return {"message": f"Hello privileged user, {current_user.username}!"}
# Require all listed roles
@app.get("/admin-and-verified")
def admin_and_verified_route(current_user = Depends(auth.require_all_roles(["admin", "verified"]))):
return {"message": f"Hello admin with verification, {current_user.username}!"}
# Shortcut for admin-only routes
@app.get("/admin-only")
def admin_only_route(current_user = Depends(auth.is_admin())):
return {"message": f"Hello admin, {current_user.username}!"}
Authentication
Login and Token Management
FastAuth implements JWT-based authentication with both access tokens and refresh tokens:
- Access tokens are short-lived (default: 30 minutes) and used for regular API access
- Refresh tokens are long-lived (default: 7 days) and used to obtain new access tokens
User authentication flow:
-
User submits credentials to
/token
endpoint - Server validates credentials and returns access + refresh tokens
- Client uses access token for API requests (via header or cookie)
-
When access token expires, client uses refresh token to get a
new one from
/token/refresh
Protected Routes
To protect a route, use FastAuth's dependencies:
# Basic authentication - any valid user
@app.get("/protected")
def protected_route(user = Depends(auth.get_current_active_user_dependency())):
return {"message": "Protected content", "user": user.username}
Database Initialization
FastAuth includes tools for initializing the database with tables, standard roles, and a superadmin user.
CLI Initialization (enhanced in v0.3.3)
Use the command-line interface for database setup with flexible configuration detection:
# Auto-detect settings from your app file
fastauth app.py
# Or use explicit parameters
fastauth --db-url="sqlite:///./app.db" --secret-key="your-secret-key"
# The CLI will automatically find settings from:
# - .env files
# - Environment variables
# - Imported modules
# - Database engine objects
Configuration Auto-Detection
FastAuth CLI can now detect database URLs and secret keys from multiple sources:
1. Environment Variables
# Set these environment variables before running FastAuth CLI
export DATABASE_URL="sqlite:///./app.db"
export SECRET_KEY="your-secret-key-here"
2. .env Files
Create a .env
file in your project directory:
DATABASE_URL=sqlite:///./app.db
SECRET_KEY=your-secret-key-here
3. Python Modules
# FastAuth will detect these patterns in your Python files
DATABASE_URL = "sqlite:///./app.db"
secret_key = "your-secret-key-here"
engine = create_engine("sqlite:///./app.db")
4. Imported Modules
# FastAuth will detect imported engines and variables
from database import engine # Where database.py contains an engine definition
from config import DATABASE_URL, SECRET_KEY
The CLI will search common configuration files in your project, including config.py
, settings.py
, db.py
, and more.
Programmatic Initialization
Initialize the database programmatically during application startup:
@app.on_event("startup")
def on_startup():
auth.initialize_db(
create_tables=True, # Create database tables
init_roles=True, # Initialize standard roles
create_admin=True, # Create superadmin if needed
admin_username="superadmin", # Default username
admin_password="admin123" # Default password
)
Advanced Usage
Custom User Models
You can extend the default User model with additional fields:
class CustomUser(SQLModel, table=True):
id: int = Field(primary_key=True)
username: str = Field(unique=True)
email: str = Field(unique=True)
hashed_password: str
disabled: bool = Field(default=False)
first_name: str = Field(default="")
last_name: str = Field(default="")
created_at: datetime = Field(default_factory=datetime.now)
# Use custom model when initializing FastAuth
auth = FastAuth(
# ... other parameters ...
user_model=CustomUser
)
Security Best Practices
-
Always use a strong, randomly generated
secret_key
in production - Store sensitive configuration in environment variables, not in code
- Use HTTPS in production to protect tokens in transit
-
Enable
use_cookie=True
andsecure_cookies=True
in production - Change default admin credentials immediately after setup
- Regularly rotate refresh tokens
- Implement rate limiting for authentication endpoints
API Reference
Authentication Endpoints
-
POST /token
- Authenticate a user and return access and refresh tokens -
POST /token/refresh
- Refresh an access token using a valid refresh token -
POST /register
- Register a new user -
GET /users/me
- Get the current authenticated user's profile -
POST /logout
- (With cookie auth) Clear authentication cookies
Role Management Endpoints
-
GET /roles
- List all roles -
POST /roles
- Create a new role -
GET /roles/{role_id}
- Get a specific role -
PUT /roles/{role_id}
- Update a role -
DELETE /roles/{role_id}
- Delete a role -
POST /users/{user_id}/roles/{role_id}
- Assign a role to a user -
DELETE /users/{user_id}/roles/{role_id}
- Remove a role from a user
Error Handling
FastAuth provides a comprehensive error handling system that delivers consistent, informative error responses across all endpoints (new in v0.3.4).
Custom Exceptions
The library includes specialized exception classes for different error scenarios:
from fastauth import (
CredentialsException, # Authentication failures
TokenException, # Token verification issues
RefreshTokenException, # Refresh token problems
InactiveUserException, # User account is disabled
UserNotFoundException, # User doesn't exist
UserExistsException, # Username already taken
RoleNotFoundException, # Role doesn't exist
RoleExistsException, # Role already exists
PermissionDeniedException # Insufficient permissions
)
Standardized Error Responses
All FastAuth exceptions return a consistent JSON structure:
{
"error": {
"code": "FASTAUTH_ERROR_CODE",
"message": "Human-readable error description",
"status_code": 401 // HTTP status code
}
}
Enabling error handling is simple:
app = FastAPI()
auth = FastAuth(...)
# Register exception handlers with your FastAPI app
auth.setup_exception_handlers(app)
This makes debugging easier and allows clients to handle errors in a consistent way. Each exception type has its own specific error code, making it straightforward to identify and respond to different error scenarios.
Project Structure
fastauth/
├── __init__.py # Package initialization
├── cli.py # Command-line interface utilities
├── core/ # Core functionality
│ ├── __init__.py # Core initialization
│ └── auth.py # Authentication core functionality
├── dependencies/ # Dependency providers
│ ├── __init__.py # Dependencies initialization
│ ├── auth.py # Authentication dependencies
│ └── roles.py # Role-based authorization dependencies
├── exceptions.py # Custom exceptions and error handling
├── models/ # Database models
│ ├── __init__.py # Models initialization
│ ├── user.py # User model
│ ├── role.py # Role model
│ └── tokens.py # Token model
├── routers/ # API endpoints
│ ├── __init__.py # Routers initialization
│ ├── auth.py # Authentication endpoints
│ └── roles.py # Role management endpoints
├── security/ # Security utilities
│ ├── __init__.py # Security initialization
│ ├── password.py # Password handling utilities
│ └── tokens.py # Token handling utilities
└── utils/ # Utility functions
├── __init__.py # Utils initialization
└── session.py # Session management utilities
The library is designed with a clean, modular architecture making it easy to extend or customize various components.