Simple email/password authentication for Django, FastAPI, and Flask
Project description
auth101
auth101 is a small Python package to provide email/password authentication with a pluggable user schema and pluggable user storage backends. It uses Argon2 via passlib for password hashing by default and includes JWT token generation for authenticated sessions.
Features
- Email/password authentication
- Secure password hashing with Argon2
- JWT token generation and verification
- Pluggable user schema and storage backends
- In-memory storage for development
- SQLAlchemy support for SQL database persistence
- Django ORM support for Django projects
Quick usage
Basic Authentication
from auth101 import Authenticator
from auth101.models import User
# default in-memory store
auth = Authenticator()
user = auth.register("alice@example.com", "s3cr3t", full_name="Alice")
assert auth.authenticate("alice@example.com", "s3cr3t")
# provide your own factory to accept a different user schema
def my_user_factory(**kwargs):
return User(**kwargs)
auth2 = Authenticator(user_factory=my_user_factory)
JWT Token Authentication
from auth101 import Authenticator
# Configure authenticator with JWT support
auth = Authenticator(
jwt_secret_key="your-secret-key-change-in-production",
jwt_expires_in_minutes=60, # Token expires in 60 minutes
jwt_algorithm="HS256" # Optional, defaults to HS256
)
# Register a new user and get JWT token
user, token = auth.register_with_token("bob@example.com", "password123")
print(f"Token: {token}")
# Authenticate existing user and get JWT token
result = auth.authenticate_with_token("bob@example.com", "password123")
if result:
user, token = result
print(f"User authenticated: {user.email}")
print(f"Token: {token}")
Token Verification
from auth101.core.security import verify_token, get_user_id_from_token
# Verify a token
payload = verify_token(token, "your-secret-key")
if payload:
print(f"Token valid, user_id: {payload['sub']}")
else:
print("Token invalid or expired")
# Extract user_id from token
user_id = get_user_id_from_token(token, "your-secret-key")
if user_id:
print(f"User ID: {user_id}")
Configuration Options
When initializing the Authenticator, you can configure:
Simplified configuration:
db_url: Database connection string for SQLAlchemy (e.g., "postgresql://user:pass@localhost/db")django_model: Django model class for DjangoUserStoreauto_create_tables: Automatically create database tables (for SQLAlchemy, default: False)
Advanced configuration:
store: User storage backend (default:MemoryUserStore)user_factory: Factory function to create user instancespwd_ctx: Password hashing context (default: Argon2)
JWT token configuration:
jwt_secret_key: Secret key for JWT signing (required for JWT features)jwt_algorithm: JWT algorithm (default: "HS256")jwt_expires_in_minutes: Token expiration time in minutes (default: 60)
Note: You can only provide one of store, db_url, or django_model. If none are provided, an in-memory store is used by default.
Database Persistence
SQLAlchemy Support
Install SQLAlchemy support:
pip install auth101[sqlalchemy]
Simplified approach - just pass a connection string:
from auth101 import Authenticator
# Simply pass your database URL!
auth = Authenticator(
db_url="postgresql://user:pass@localhost/mydb",
auto_create_tables=True # Automatically create tables
)
user = auth.register("alice@example.com", "password123")
Advanced approach - for custom engine configuration:
from sqlalchemy import create_engine
from auth101 import Authenticator
from auth101.core.persistence import SQLAlchemyUserStore
# Create engine with custom options
engine = create_engine(
"postgresql://user:pass@localhost/mydb",
pool_size=10,
max_overflow=20
)
# Create store and tables
store = SQLAlchemyUserStore(engine)
store.create_tables()
# Use with authenticator
auth = Authenticator(store=store)
user = auth.register("alice@example.com", "password123")
Works with any SQLAlchemy-supported database: PostgreSQL, MySQL, SQLite, etc.
Django Support
Install for Django:
pip install auth101[django]
- Add model to your Django app:
from django.db import models
import uuid
class AuthUser(models.Model):
id = models.CharField(max_length=36, primary_key=True,
default=lambda: str(uuid.uuid4()))
email = models.EmailField(unique=True, db_index=True)
password_hash = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
class Meta:
db_table = 'auth_users'
- Run migrations:
python manage.py makemigrations
python manage.py migrate
- Use in your Django views:
Simplified approach:
from auth101 import Authenticator
from myapp.models import AuthUser
# Just pass your Django model!
auth = Authenticator(django_model=AuthUser)
# In your view:
user = auth.register(email, password)
authenticated = auth.authenticate(email, password)
Advanced approach - if you need explicit store control:
from auth101 import Authenticator
from auth101.core.persistence import DjangoUserStore
from myapp.models import AuthUser
store = DjangoUserStore(AuthUser)
auth = Authenticator(store=store)
# In your view:
user = auth.register(email, password)
authenticated = auth.authenticate(email, password)
Framework Integration Examples
FastAPI
from fastapi import FastAPI, HTTPException, Depends
from auth101 import Authenticator
from auth101.core.security import get_user_id_from_token
# Initialize with database
auth = Authenticator(
db_url="postgresql://user:pass@localhost/db",
auto_create_tables=True,
jwt_secret_key="your-secret-key",
jwt_expires_in_minutes=60
)
app = FastAPI()
@app.post("/register")
async def register(email: str, password: str):
try:
user, token = auth.register_with_token(email, password)
return {"user_id": user.id, "token": token}
except ValueError as e:
raise HTTPException(400, str(e))
@app.post("/login")
async def login(email: str, password: str):
result = auth.authenticate_with_token(email, password)
if not result:
raise HTTPException(401, "Invalid credentials")
user, token = result
return {"token": token}
# Protected route
def get_current_user(token: str):
user_id = get_user_id_from_token(token, auth.jwt_secret_key)
if not user_id:
raise HTTPException(401, "Invalid token")
return user_id
@app.get("/protected")
async def protected(user_id: str = Depends(get_current_user)):
return {"message": f"Hello user {user_id}"}
Flask
from flask import Flask, request, jsonify
from auth101 import Authenticator
from auth101.core.security import get_user_id_from_token
from functools import wraps
# Initialize with database
auth = Authenticator(
db_url="sqlite:///auth.db",
auto_create_tables=True,
jwt_secret_key="your-secret-key"
)
app = Flask(__name__)
# Protected route decorator
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get('Authorization', '').replace('Bearer ', '')
user_id = get_user_id_from_token(token, auth.jwt_secret_key)
if not user_id:
return jsonify({"error": "Invalid token"}), 401
return f(user_id, *args, **kwargs)
return decorated
@app.route('/register', methods=['POST'])
def register():
data = request.json
try:
user, token = auth.register_with_token(data['email'], data['password'])
return jsonify({"user_id": user.id, "token": token})
except ValueError as e:
return jsonify({"error": str(e)}), 400
@app.route('/login', methods=['POST'])
def login():
data = request.json
result = auth.authenticate_with_token(data['email'], data['password'])
if not result:
return jsonify({"error": "Invalid credentials"}), 401
user, token = result
return jsonify({"token": token})
@app.route('/protected')
@token_required
def protected(user_id):
return jsonify({"message": f"Hello user {user_id}"})
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auth101-0.2.0.tar.gz.
File metadata
- Download URL: auth101-0.2.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
76dcc4e16837e5d33cdb4cf35aa23116ceaf4d9025121b3ada9c9d37b01f0f14
|
|
| MD5 |
49ae53caed15743bdf473695c2eae798
|
|
| BLAKE2b-256 |
13045aa442183e55049eebf579e73a159aa87ba4ab96827f9e2ad4013f2ae4d6
|
File details
Details for the file auth101-0.2.0-py3-none-any.whl.
File metadata
- Download URL: auth101-0.2.0-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a38ec9a0929e089d3a5013e6ebf498b00215a01a95c70d7a59022915c916c09
|
|
| MD5 |
33e2e52f0d4d07c90d792e31c7b052fa
|
|
| BLAKE2b-256 |
70786871867cec1be120cc5750ef23d05ef0535f4d11afb8790de7c543e5633a
|