Authentication System
Complete JWT authentication with user management, email verification, OAuth integration, and role-based access control
Overview
FastLaunchAPI's authentication system provides everything you need for secure user management:
- JWT Authentication - Stateless tokens with automatic refresh
- OAuth Integration - Google OAuth with extensible provider system
- Email Verification - Secure email verification workflow
- Password Security - Bcrypt hashing with strength validation
- User Management - Complete profile management and updates
- Reset Functionality - Secure password reset with time-limited tokens
The authentication system is production-ready and includes all security best practices like password hashing, token expiration, and email verification.
Quick Start
Get authentication working in your application with these simple steps:
Register a New User
curl -X POST "http://localhost:8000/auth/create-user" \
-H "Content-Type: application/json" \
-d '{
"username": "john_doe",
"email": "john@example.com",
"password": "securepassword123"
}'
Verify Email
User receives an email with verification link. When clicked, redirects to your frontend with confirmation.
Login and Get Tokens
curl -X POST "http://localhost:8000/auth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=john_doe&password=securepassword123"
Returns access and refresh tokens for authenticated requests.
Access Protected Routes
curl -X GET "http://localhost:8000/auth/get-user" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Core Features
🔐 JWT Authentication
Stateless authentication with access and refresh tokens
🌐 OAuth Integration
Google OAuth with support for multiple providers
📧 Email Verification
Secure email verification with HTML templates
🔄 Password Reset
Token-based password reset with time limits
👤 User Management
Complete profile management and updates
🛡️ Security Features
Bcrypt hashing, token expiration, and validation
Database Schema
The authentication system uses a flexible user model that supports both traditional and OAuth authentication:
class User(Base):
"""User model for authentication"""
__tablename__ = "users"
# Core authentication fields
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
username = Column(String, unique=True)
email = Column(String, unique=True)
hashed_password = Column(String)
is_verified = Column(Boolean, default=False)
# OAuth integration
is_oauth = Column(Boolean, default=False)
google_sub = Column(String(100), nullable=True, unique=True, index=True)
# Token management
verification_token = Column(String, nullable=True)
reset_token = Column(String, nullable=True)
# Subscription integration (for payments)
customer_id = Column(String(255), nullable=True)
plan_id = Column(Integer, nullable=True)
subscription_id = Column(String(255), nullable=True)
subscription_status = Column(String(64), nullable=True)
subscription_last_renew = Column(String, nullable=True)
subscription_next_renew = Column(String, nullable=True)
Payment Integration Ready: The user model includes subscription fields for seamless integration with the payment system.
API Reference
User Registration
Create User Account
Creates a new user account and sends verification email.
POST /auth/create-user
Content-Type: application/json
{
"username": "john_doe",
"email": "john@example.com",
"password": "securepassword123"
}
Response:
{
"message": "User created. Check your email to verify."
}
Validation Rules:
- Username must be unique
- Email must be valid and unique
- Password must be at least 8 characters
Error Responses:
400 Bad Request
- Username or email already taken422 Unprocessable Entity
- Invalid data format
Verify Email
Verifies user email address using token from email.
GET /auth/verify-email?token=<verification_token>
Response:
- Redirects to
{FRONTEND_URL}/login?detail=email_verified
on success - Redirects to
{FRONTEND_URL}/login?detail=already_verified
if already verified
Token expires after 30 minutes.
Authentication
Login with Credentials
Authenticates user and returns JWT tokens.
POST /auth/token
Content-Type: application/x-www-form-urlencoded
username=john_doe&password=securepassword123
Response:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer"
}
Error Responses:
401 Unauthorized
- Invalid credentials401 Unauthorized
- Email not verified
Refresh Tokens
Exchanges refresh token for new access and refresh tokens.
POST /auth/refresh
Content-Type: application/json
{
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
Response:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer"
}
Error Responses:
401 Unauthorized
- Refresh token expired or invalid
OAuth Authentication
Setting up Google OAuth
Before using Google OAuth, you need to obtain credentials from Google Cloud Console:
Get Google OAuth Credentials
- Go to the Google Cloud Console
- Create a new project or select an existing one
- Enable the Google+ API (or Google Identity API)
- Go to "Credentials" → "Create Credentials" → "OAuth 2.0 Client ID"
- Configure the consent screen with your app information
- Add authorized redirect URIs:
http://localhost:8000/auth/oauth/callback/google
(development)https://yourdomain.com/auth/oauth/callback/google
(production)
Configure Environment Variables
# Required for Google OAuth
GOOGLE_CLIENT_ID=your_google_client_id_here
GOOGLE_CLIENT_SECRET=your_google_client_secret_here
# URLs for OAuth redirects
BACKEND_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000
Google OAuth Flow
Initiate OAuth
GET /auth/oauth/google
Redirects to Google's OAuth consent screen where users grant permissions.
Handle Callback
GET /auth/oauth/callback/google?code=<authorization_code>
Processes OAuth response and creates/updates user account. If user exists by email, links Google account. Otherwise creates new user.
Receive Tokens
On success, redirects to frontend with tokens:
https://yourapp.com/auth?access_token=<token>&refresh_token=<refresh_token>
OAuth Configuration Required: Google OAuth will only work if
GOOGLE_CLIENT_ID
and GOOGLE_CLIENT_SECRET
environment variables are
properly set.
Adding More OAuth Providers
The system is designed to support multiple OAuth providers. Here's how to add Facebook:
# In oauth_providers.py
oauth_providers.register(
OAuthProviderConfig(
name='facebook',
registration_params={
'api_base_url': 'https://graph.facebook.com/v12.0/',
'authorize_url': 'https://www.facebook.com/v12.0/dialog/oauth',
'access_token_url': 'https://graph.facebook.com/v12.0/oauth/access_token',
'client_kwargs': {'scope': 'email public_profile'}
},
user_model=FacebookUser,
db_field='facebook_id'
)
)
User Management
Get Current User
Returns authenticated user information.
GET /auth/get-user
Authorization: Bearer <access_token>
Response:
{
"id": 1,
"username": "john_doe",
"email": "john@example.com",
"is_verified": true,
"is_oauth": false
}
Update User Profile
Updates user profile information.
PATCH /auth/update-user
Authorization: Bearer <access_token>
Content-Type: application/json
{
"display_name": "John Doe",
"bio": "Software developer",
"niche_preference": "technology",
"avatar_url": "https://example.com/avatar.jpg"
}
Protected Fields: Cannot update id
, created_at
, is_admin
, hashed_password
, google_sub
, or email
.
Error Responses:
400 Bad Request
- Attempting to update protected field404 Not Found
- User not found
Password Reset
Request Password Reset
Sends password reset email if user exists.
POST /auth/request-password-reset
Content-Type: application/json
{
"email": "john@example.com"
}
Response:
{
"detail": "If the email exists, a reset link has been sent."
}
Security Note: Response is the same whether email exists or not to prevent email enumeration.
Reset Password
Resets user's password using valid token.
POST /auth/reset-password
Content-Type: application/json
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"new_password": "newSecurePassword123"
}
Response:
{
"detail": "Password reset successful"
}
Error Responses:
400 Bad Request
- Invalid or expired token422 Unprocessable Entity
- Password doesn't meet requirements
Security Features
Password Security
- Bcrypt Hashing: All passwords are hashed using bcrypt with automatic salt generation
- Password Strength: Minimum 8 characters required (configurable)
- No Plain Text: Passwords are never stored in plain text
Token Security
- JWT Tokens: Stateless authentication with configurable expiration
- Token Refresh: Automatic token refresh prevents session interruption
- Secure Storage: Tokens include user ID and expiration claims
Default Token Expiration:
- Access Token: 7 days (configurable via
ACCESS_TOKEN_EXPIRATION_DAYS
) - Refresh Token: 30 days (configurable via
REFRESH_TOKEN_EXPIRATION_DAYS
)
Email Security
- Token-based Verification: Email verification uses JWT tokens
- Time-limited Tokens: Verification tokens expire after 30 minutes
- Password Reset: Reset tokens expire after 1 hour
Configuration
Environment Variables
# Core Settings
SECRET_KEY=your-secret-key-here
ACCESS_TOKEN_EXPIRATION_DAYS=7
REFRESH_TOKEN_EXPIRATION_DAYS=30
# OAuth Configuration
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# URL Configuration
BACKEND_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000
# Database
DATABASE_URL=postgresql://user:password@localhost/dbname
# Email Configuration (for verification and reset)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
Security Best Practices
- Use Strong Secret Keys: Generate cryptographically secure secret keys
- HTTPS Only: Always use HTTPS in production
- Token Expiration: Set appropriate token expiration times
- Rate Limiting: Implement rate limiting on authentication endpoints
- Input Validation: All inputs are validated using Pydantic models
Error Handling
The authentication system provides consistent error responses:
{
"detail": "Error message description"
}
Common Error Codes
400 Bad Request
- Invalid input data or business logic error401 Unauthorized
- Authentication failed or token invalid403 Forbidden
- Access denied (user doesn't have permission)404 Not Found
- Resource not found422 Unprocessable Entity
- Validation error
Testing
Example Test Cases
def test_create_user():
response = client.post("/auth/create-user", json={
"username": "testuser",
"email": "test@example.com",
"password": "password123"
})
assert response.status_code == 201
def test_login():
response = client.post("/auth/token", data={
"username": "testuser",
"password": "password123"
})
assert response.status_code == 200
assert "access_token" in response.json()
Frontend Integration
JavaScript Example
// Login function
async function login(username, password) {
const response = await fetch("/auth/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `username=${username}&password=${password}`,
});
if (response.ok) {
const data = await response.json();
localStorage.setItem("access_token", data.access_token);
localStorage.setItem("refresh_token", data.refresh_token);
return data;
}
throw new Error("Login failed");
}
// Authenticated request
async function makeAuthenticatedRequest(url) {
const token = localStorage.getItem("access_token");
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.status === 401) {
// Token expired, try to refresh
await refreshToken();
return makeAuthenticatedRequest(url);
}
return response;
}
// Token refresh
async function refreshToken() {
const refresh_token = localStorage.getItem("refresh_token");
const response = await fetch("/auth/refresh", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ refresh_token }),
});
if (response.ok) {
const data = await response.json();
localStorage.setItem("access_token", data.access_token);
localStorage.setItem("refresh_token", data.refresh_token);
} else {
// Refresh failed, redirect to login
window.location.href = "/login";
}
}
Extending the System
Adding Custom User Fields
- Update the User Model: Add new columns to the User model
- Create Migration: Generate and run database migration
- Update Validators: Add fields to
UserUpdateRequest
- Update API: Modify endpoints to handle new fields
Adding New OAuth Providers
- Register Provider: Add provider configuration to
oauth_providers.py
- Create Handler: Implement callback handler function
- Update User Model: Add provider-specific fields if needed
- Configure Environment: Set up required environment variables
Custom Authentication Logic
The system is designed to be extensible. You can:
- Add custom validation rules
- Implement additional security checks
- Add audit logging
- Integrate with external identity providers
Troubleshooting
Common Issues
OAuth Not Working
- Check environment variables are set correctly
- Verify redirect URIs in provider console
- Ensure HTTPS is used in production
Email Verification Not Working
- Check SMTP configuration
- Verify email templates exist
- Check spam folder
Token Errors
- Verify SECRET_KEY is consistent
- Check token expiration settings
- Ensure clocks are synchronized
Debug Mode
Enable debug logging to troubleshoot issues:
import logging
logging.basicConfig(level=logging.DEBUG)
Migration Guide
From Session-based Auth
- Install Dependencies: Add JWT and OAuth dependencies
- Update Database: Run migrations to add new user fields
- Update Frontend: Replace session handling with token storage
- Test Integration: Verify all authentication flows work
Upgrading
When upgrading the authentication system:
- Backup Database: Always backup before migrations
- Run Migrations: Apply database schema changes
- Update Environment: Add any new required variables
- Test Thoroughly: Verify all authentication flows