### Environment Configuration for Better Auth and Database (Bash/Python) Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt Backend environment configuration using a .env file and Pydantic's BaseSettings for FastAPI. This setup includes variables for Better Auth URL, database connection, and a JWT secret key. Ensure the BETTER_AUTH_SECRET is at least 32 characters long for security. ```bash # backend/.env BETTER_AUTH_URL=http://localhost:3000 DATABASE_URL=postgresql://user:password@localhost:5432/todo_db BETTER_AUTH_SECRET=your-super-secret-key-min-32-chars # Production example: # BETTER_AUTH_URL=https://yourdomain.com # DATABASE_URL=postgresql://user:pass@db.neon.tech/production_db # BETTER_AUTH_SECRET= ``` ```python # backend/config.py from pydantic_settings import BaseSettings class Settings(BaseSettings): better_auth_url: str database_url: str better_auth_secret: str class Config: env_file = ".env" settings = Settings() # Usage in auth.py: # jwks_url = f"{settings.better_auth_url}/.well-known/jwks.json" ``` -------------------------------- ### JWKS Client Setup for Better Auth in Python Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Sets up a cached PyJWKClient to fetch and store public keys from Better Auth's JWKS endpoint for efficient JWT verification. It utilizes LRU caching to minimize API calls. ```python from jwt import PyJWKClient from functools import lru_cache from config import settings def get_jwk_client() -> PyJWKClient: """ Get a cached PyJWKClient for JWKS verification. The client fetches public keys from Better Auth's JWKS endpoint and caches them for efficient verification. """ # Better Auth JWKS endpoint jwks_url = f"{settings.better_auth_url}/.well-known/jwks.json" return PyJWKClient(jwks_url) @lru_cache(maxsize=1) def _get_cached_jwk_client() -> PyJWKClient: """Cached version of JWKS client.""" return get_jwk_client() ``` -------------------------------- ### POST /api/{user_id}/tasks Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt Creates a new task for a specific user. This endpoint requires JWT authentication and enforces user isolation. ```APIDOC ## POST /api/{user_id}/tasks ### Description Creates a new task for a specific user. This endpoint requires JWT authentication and enforces user isolation to ensure that users can only access and manage their own tasks. ### Method POST ### Endpoint `/api/{user_id}/tasks` ### Parameters #### Path Parameters - **user_id** (string) - Required - The unique identifier of the user for whom the task is being created. #### Request Body - **title** (string) - Required - The title of the task. - **completed** (boolean) - Optional - The completion status of the task. Defaults to `false`. ### Request Example ```json { "title": "Buy groceries", "completed": false } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the operation was successful. - **data** (object) - Contains the details of the created task. - **id** (integer) - The unique identifier of the created task. - **title** (string) - The title of the task. - **completed** (boolean) - The completion status of the task. - **user_id** (string) - The user ID associated with the task. #### Response Example ```json { "success": true, "data": { "id": 5, "title": "Buy groceries", "completed": false, "user_id": "user-456" } } ``` #### Error Response (403) - **detail** (string) - "Forbidden: user_id mismatch" if the authenticated user's ID does not match the `user_id` in the path. #### Error Response (500) - **detail** (string) - "Server error: [error message]" for any unexpected server-side errors during task creation. ``` -------------------------------- ### Create Task Endpoint with JWT Authentication (Python FastAPI) Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This Python FastAPI endpoint allows creating new tasks for a specific user, enforcing JWT authentication and user ID matching. It uses Pydantic for data validation and SQLAlchemy for database operations. Dependencies include JWT verification and database session management. ```python from pydantic import BaseModel class TaskCreate(BaseModel): title: str completed: bool = False @router.post("/api/{user_id}/tasks") async def create_task( user_id: str, task_data: TaskCreate, current_user: Dict[str, str] = Depends(verify_jwt_token), db: Session = Depends(get_session), ): """Create new task with authentication and user isolation.""" try: # Verify user_id matches token if current_user["user_id"] != user_id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden: user_id mismatch" ) # Create task task = Task( title=task_data.title, completed=task_data.completed, user_id=user_id ) db.add(task) db.commit() db.refresh(task) return { "success": True, "data": { "id": task.id, "title": task.title, "completed": task.completed, "user_id": task.user_id } } except HTTPException: raise except Exception as e: db.rollback() raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Server error: {str(e)}" ) ``` -------------------------------- ### Better Auth Configuration - JWT Token Generation (TypeScript) Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This TypeScript snippet demonstrates the configuration of Better Auth for enabling JWT token generation. It specifies the database provider and enables email and password authentication. The 'jwt' plugin is configured to automatically sign tokens using RS256/EdDSA algorithms, storing keys in a 'jwks' database table. Tokens include user_id in the 'sub' claim and email. It depends on the 'better-auth' library. ```typescript import { betterAuth } from "better-auth"; export const auth = betterAuth({ database: { provider: "postgres", url: process.env.DATABASE_URL, }, emailAndPassword: { enabled: true, }, plugins: [ { id: "jwt", // Automatically generates JWT tokens signed with RS256/EdDSA // Keys stored in 'jwks' database table // Tokens include user_id in 'sub' claim and email }, ], }); ``` -------------------------------- ### GET /api/{user_id}/tasks Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Retrieves all tasks for a specific authenticated user. It ensures that the user can only access their own data through JWT verification and user ID matching. ```APIDOC ## GET /api/{user_id}/tasks ### Description Retrieves all tasks for the authenticated user. Ensures user isolation by matching the `user_id` from the URL with the ID from the JWT. ### Method GET ### Endpoint `/api/{user_id}/tasks` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user whose tasks are to be retrieved. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **success** (bool) - Indicates if the request was successful. - **data** (list) - A list of task objects. #### Response Example ```json { "success": true, "data": [ { "id": 1, "title": "Buy groceries", "description": "Milk, Bread, Eggs", "user_id": "user123" } ] } ``` ``` -------------------------------- ### JWT Token Verification Tests with FastAPI TestClient (Python) Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt Unit tests for JWT token verification and protected endpoints in a FastAPI application. These tests use `pytest` and FastAPI's `TestClient` to simulate requests and verify authentication logic, including valid tokens, expired tokens, and user isolation. ```python # backend/tests/test_auth.py import pytest from utils.auth import verify_jwt_token from fastapi.testclient import TestClient from main import app client = TestClient(app) def test_verify_valid_token(): """Test JWT verification with valid token.""" # Token obtained from Better Auth signin token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xMjMifQ..." user_info = verify_jwt_token(token) assert "user_id" in user_info assert "email" in user_info assert user_info["user_id"] == "user-456" assert user_info["email"] == "user@example.com" def test_verify_expired_token(): """Test JWT verification with expired token.""" expired_token = "eyJhbGciOiJSUzI1NiIs...expired..." with pytest.raises(ValueError, match="Invalid token"): verify_jwt_token(expired_token) def test_protected_endpoint_with_valid_token(): """Test accessing protected endpoint with valid token.""" valid_token = "eyJhbGciOiJSUzI1NiIs..." response = client.get( "/api/user-456/tasks", headers={"Authorization": f"Bearer {valid_token}"} ) assert response.status_code == 200 assert response.json()["success"] is True assert "data" in response.json() def test_protected_endpoint_without_token(): """Test accessing protected endpoint without token.""" response = client.get("/api/user-456/tasks") assert response.status_code == 403 assert "Not authenticated" in response.json()["detail"] def test_protected_endpoint_with_wrong_user_id(): """Test user isolation - accessing another user's data.""" user_456_token = "eyJhbGciOiJSUzI1NiIs...user-456..." response = client.get( "/api/user-789/tasks", # Different user_id headers={"Authorization": f"Bearer {user_456_token}"} ) assert response.status_code == 403 assert response.json()["error"]["code"] == "FORBIDDEN" # Run tests: # pytest backend/tests/test_auth.py -v ``` -------------------------------- ### JWKS Endpoint - Public Key Distribution Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This endpoint exposes public cryptographic keys in JWKS format, which backends use to verify JWT token signatures. ```APIDOC ## GET /.well-known/jwks.json ### Description Exposes public cryptographic keys that backends use to verify JWT token signatures without sharing private keys. ### Method GET ### Endpoint `/.well-known/jwks.json` ### Parameters None ### Request Example None ### Response #### Success Response (200) - **keys** (array) - An array of JWK objects representing public keys. - **kty** (string) - Key type (e.g., "RSA"). - **kid** (string) - Key identifier. - **n** (string) - RSA modulus. - **e** (string) - RSA public exponent. - **alg** (string) - The algorithm intended for use with the key (e.g., "RS256"). #### Response Example ```json { "keys": [ { "kty": "RSA", "kid": "key-123", "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx...", "e": "AQAB", "alg": "RS256" } ] } ``` ``` -------------------------------- ### Better Auth Configuration - JWT Token Generation Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt Configures Better Auth to handle user authentication and automatic JWT token generation, signed with RS256/EdDSA and keys stored in the 'jwks' database table. ```APIDOC ## Better Auth JWT Configuration ### Description Configures Better Auth to handle user authentication and automatic JWT token generation with cryptographic signing. Tokens include user_id in 'sub' claim and email. ### Method Configuration (Implicit) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response #### Success Response (Implicit) Upon successful user sign-in, Better Auth returns a JWT token. #### Response Example ``` eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xMjMifQ.eyJzdWIiOiJ1c2VyLTQ1NiIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTYzMjE1MjAwMCwiZXhwIjoxNjMyNzU2ODAwfQ.signature... ``` **Note**: The frontend should store this token and include it in API requests using the `Authorization: Bearer ` header. ``` -------------------------------- ### Protected API Endpoint - User Isolation Pattern Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This endpoint demonstrates how to protect API endpoints with JWT authentication and enforce user isolation to prevent unauthorized data access. It verifies the JWT and ensures the requested resource belongs to the authenticated user. ```APIDOC ## GET /api/{user_id}/tasks ### Description Get all tasks for the authenticated user, enforcing user isolation. ### Method GET ### Endpoint `/api/{user_id}/tasks` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user whose tasks are to be retrieved. #### Query Parameters None #### Request Body None ### Request Example ```bash curl -H "Authorization: Bearer " http://localhost:8000/api/user-456/tasks ``` ### Response #### Success Response (200) - **success** (Boolean) - True if the request was successful. - **data** (List[Dict]) - A list of task objects, each containing: - **id** (Integer) - The task ID. - **title** (String) - The task title. - **completed** (Boolean) - The completion status of the task. - **user_id** (String) - The ID of the user the task belongs to. #### Response Example ```json { "success": true, "data": [ { "id": 1, "title": "Buy milk", "completed": false, "user_id": "user-456" } ] } ``` #### Error Responses - **403 Forbidden**: If the authenticated user tries to access tasks of another user. - **success** (Boolean) - False - **error** (Dict) - **code** (String) - "FORBIDDEN" - **message** (String) - "You can only access your own data" - **401 Unauthorized**: If the JWT token is missing or invalid (handled by `verify_jwt_token` dependency). ``` -------------------------------- ### FastAPI JWT Middleware Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This FastAPI dependency extracts and verifies JWT tokens from Authorization headers, providing authenticated user information to endpoints. It handles expired and invalid tokens by raising HTTP 401 exceptions. ```APIDOC ## FastAPI JWT Middleware ### Description FastAPI dependency that extracts and verifies JWT tokens from Authorization headers, providing authenticated user information to endpoints. ### Method GET, POST, PUT, DELETE, etc. ### Endpoint N/A (This is a dependency function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```bash curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." http://localhost:8000/api/user-456/tasks ``` ### Response #### Success Response (200) - **user_info** (Dict[str, str]) - Dictionary containing user ID and email. #### Response Example ```json { "user_id": "user-456", "email": "user@example.com" } ``` #### Error Responses - **401 Unauthorized**: If the token is invalid or expired. - **detail** (Dict) - Error details including code and message. - **success** (Boolean) - False - **error** (Dict) - **code** (String) - e.g., "TOKEN_EXPIRED", "INVALID_TOKEN" - **message** (String) - Error message describing the issue. ``` -------------------------------- ### GET /api/{user_id}/tasks/{task_id} Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Retrieves a specific task for a given user. This endpoint enforces user data isolation by checking the `user_id` against the authenticated user's ID. ```APIDOC ## GET /api/{user_id}/tasks/{task_id} ### Description Retrieves a specific task by its ID for a given user. User access is restricted to their own tasks. ### Method GET ### Endpoint `/api/{user_id}/tasks/{task_id}` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user. - **task_id** (int) - Required - The ID of the task to retrieve. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **success** (bool) - Indicates if the request was successful. - **data** (object) - The task object. #### Response Example ```json { "success": true, "data": { "id": 1, "title": "Buy groceries", "description": "Milk, Bread, Eggs", "user_id": "user123" } } ``` ``` -------------------------------- ### FastAPI JWT Middleware for Request Authentication Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This FastAPI dependency extracts and verifies JWT tokens from Authorization headers. It provides authenticated user information to endpoints and raises HTTPExceptions for invalid or expired tokens. It relies on a utility function `utils.auth.verify_jwt_token` for the actual token verification logic. ```python from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from utils.auth import verify_jwt_token as verify_token import jwt from typing import Dict security = HTTPBearer() def verify_jwt_token( credentials: HTTPAuthorizationCredentials = Depends(security) ) -> Dict[str, str]: """ Extract and verify JWT from Authorization header. Returns: {"user_id": str, "email": str} Raises: HTTPException: 401 if token invalid or expired """ token = credentials.credentials try: user_info = verify_token(token) return user_info except jwt.exceptions.ExpiredSignatureError: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "success": False, "error": { "code": "TOKEN_EXPIRED", "message": "Token has expired. Please sign in again." }, }, headers={"WWW-Authenticate": "Bearer"}, ) except jwt.exceptions.PyJWTError: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "success": False, "error": { "code": "INVALID_TOKEN", "message": "Invalid token" }, }, headers={"WWW-Authenticate": "Bearer"}, ) ``` -------------------------------- ### JWT Verification Function - Token Validation Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt Verifies JWT token signatures using JWKS public keys, ensuring tokens are authentic, not expired, and contain valid user information. ```APIDOC ## POST /api/verify_token (Illustrative) ### Description Verifies JWT tokens using JWKS public keys, ensuring tokens are authentic, not expired, and contain valid user information. This is typically handled internally by the backend framework or a middleware. ### Method POST (Illustrative - often part of middleware) ### Endpoint `/api/verify_token` (Illustrative) ### Parameters #### Request Body - **token** (string) - Required - The JWT token from the Authorization header. ### Request Example ```json { "token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImtleS0xMjMifQ.eyJzdWIiOiJ1c2VyLTQ1NiIsImVtYWlsIjoidXNlckBleGFtcGxlLmNvbSIsImlhdCI6MTYzMjE1MjAwMCwiZXhwIjoxNjMyNzU2ODAwfQ.signature..." } ``` ### Response #### Success Response (200) - **user_id** (string) - The unique identifier of the user (from 'sub' claim). - **email** (string) - The email address of the user. #### Response Example ```json { "user_id": "user-456", "email": "user@example.com" } ``` #### Error Response (401/422) - **detail** (string) - A message indicating the reason for verification failure (e.g., "Invalid token: signature mismatch", "Invalid token: expired signature"). **Note**: The Python code provided in the source (`backend/utils/auth.py`) demonstrates the core logic for token verification. This typically would be integrated into a FastAPI dependency or middleware rather than being a direct API endpoint. ``` -------------------------------- ### FastAPI Protected API Endpoint for User Isolation Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This FastAPI router demonstrates protecting API endpoints using JWT authentication and enforcing user isolation. It ensures that users can only access their own data by verifying the JWT and comparing the `user_id` from the token with the `user_id` in the URL path. Database queries are also filtered by `user_id`. ```python # backend/routes/tasks.py from fastapi import APIRouter, Depends, HTTPException, status from middleware.jwt import verify_jwt_token from sqlmodel import Session, select from typing import Dict # Assume get_session and Task models are defined elsewhere # from your_db_module import get_session, Task router = APIRouter() @router.get("/api/{user_id}/tasks") async def get_tasks( user_id: str, current_user: Dict[str, str] = Depends(verify_jwt_token), db: Session = Depends(get_session), ): """ Get all tasks for authenticated user with user isolation. Security: 1. JWT verified automatically via dependency 2. user_id from token must match URL path 3. Database queries filtered by user_id """ # Enforce user isolation if current_user["user_id"] != user_id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail={ "success": False, "error": { "code": "FORBIDDEN", "message": "You can only access your own data" } } ) # Query database with user isolation statement = select(Task).where(Task.user_id == user_id) tasks = db.exec(statement).all() return { "success": True, "data": [ { "id": task.id, "title": task.title, "completed": task.completed, "user_id": task.user_id } for task in tasks ] } ``` -------------------------------- ### JWKS Endpoint - Public Key Distribution (TypeScript) Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This TypeScript code snippet exposes a JWKS endpoint that distributes public cryptographic keys used for verifying JWT token signatures. It fetches keys from a database and formats them according to the standard JWKS response structure. The endpoint includes caching for improved performance. It requires database access and JWKS schema definition. ```typescript import { db } from "@/lib/db-drizzle"; import { jwks } from "@/drizzle/schema"; export async function GET() { // Fetch all public keys from database const keys = await db.select().from(jwks); // Format as standard JWKS response const jwksResponse = { keys: keys.map((key) => { const publicKey = JSON.parse(key.publicKey); return { ...publicKey, kid: key.id, // Key identifier }; }), }; return new Response(JSON.stringify(jwksResponse), { status: 200, headers: { "Content-Type": "application/json", "Cache-Control": "public, max-age=3600", }, }); } ``` -------------------------------- ### JWT Verification Function - Token Validation (Python) Source: https://context7.com/hamza123545/how-to-use-better-auth-with-python-fast-api/llms.txt This Python function, `verify_jwt_token`, validates JWT tokens using JWKS public keys fetched from a URL. It utilizes `PyJWKClient` for JWKS interaction and `jwt.decode` for token verification, supporting EdDSA and RS256 algorithms. The function is cached for efficiency and extracts user ID and email from the token payload. It handles JWT-related errors by raising a ValueError. Dependencies include `PyJWT` and `functools.lru_cache`. ```python import jwt from jwt import PyJWKClient from functools import lru_cache from typing import Dict # Assuming 'settings' object is available with 'better_auth_url' # from your_settings_module import settings class MockSettings: better_auth_url = "http://localhost:3000" settings = MockSettings() @lru_cache(maxsize=1) def _get_cached_jwk_client() -> PyJWKClient: """Get cached JWKS client to fetch public keys.""" jwks_url = f"{settings.better_auth_url}/.well-known/jwks.json" return PyJWKClient(jwks_url) def verify_jwt_token(token: str) -> Dict[str, str]: """ Verify JWT token signature and extract user information. Args: token: JWT token from Authorization header Returns: {"user_id": "user-456", "email": "user@example.com"} Raises: ValueError: If token invalid, expired, or malformed """ try: # Get JWKS client and fetch signing key jwk_client = _get_cached_jwk_client() signing_key = jwk_client.get_signing_key_from_jwt(token) # Verify signature and decode payload payload = jwt.decode( token, signing_key.key, algorithms=["EdDSA", "RS256"], options={"verify_aud": False} ) # Extract user information user_id: str = payload.get("sub") or payload.get("user_id") email: str = payload.get("email", "") if not user_id: raise ValueError("Invalid token: missing user_id (sub claim)") return {"user_id": user_id, "email": email} except jwt.exceptions.PyJWTError as e: raise ValueError(f"Invalid token: {str(e)}") from e ``` -------------------------------- ### Backend Environment Variables Configuration Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This `.env` file demonstrates the backend configuration for Better Auth and database connection. It includes `BETTER_AUTH_URL` pointing to the frontend, `DATABASE_URL` for database access, and `BETTER_AUTH_SECRET` which must match the frontend's configuration for secure communication. ```bash # Better Auth URL (points to frontend) BETTER_AUTH_URL=http://localhost:3000 # Database (shared with Better Auth) DATABASE_URL=postgresql://user:pass@db.neon.tech/todo_db # Shared secret (must match frontend) BETTER_AUTH_SECRET=your-secret-key-here ``` -------------------------------- ### Frontend Environment Variables Configuration Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This `.env.local` file shows the frontend configuration for Better Auth and database connection. It mirrors the backend settings with `BETTER_AUTH_URL` and `BETTER_AUTH_SECRET`, emphasizing the importance of matching `BETTER_AUTH_SECRET` for secure authentication between the frontend and backend. ```bash # Better Auth configuration BETTER_AUTH_URL=http://localhost:3000 BETTER_AUTH_SECRET=your-secret-key-here # Database (shared with backend) DATABASE_URL=postgresql://user:pass@db.neon.tech/todo_db ``` -------------------------------- ### Frontend Better Auth Configuration (TypeScript) Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Configures the Better Auth library on the frontend, enabling email/password authentication and the JWT plugin for token generation. It specifies the database provider and URL, and indicates that the JWT plugin will generate tokens using RS256/EdDSA algorithms. ```typescript import { betterAuth } from "better-auth"; export const auth = betterAuth({ database: { provider: "postgres", url: process.env.DATABASE_URL, }, emailAndPassword: { enabled: true, }, plugins: [ { id: "jwt", // JWT plugin generates tokens with RS256/EdDSA algorithm }, ], }); ``` -------------------------------- ### Python FastAPI Endpoint with Alternative User Access Verification Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This Python code presents an alternative method for securing a FastAPI endpoint by using a `verify_user_access` dependency, which likely encapsulates both JWT verification and user ID matching. This simplifies the endpoint logic, as user authorization is handled upstream, allowing the endpoint to directly proceed with database queries. ```python @router.get("/api/{user_id}/tasks") async def get_tasks( user_id: str, current_user: Dict[str, str] = Depends(verify_user_access), # Auto-verifies user_id match db: Session = Depends(get_session), ): # User is already verified, proceed with query statement = select(Task).where(Task.user_id == user_id) tasks = db.exec(statement).all() return {"success": True, "data": tasks} ``` -------------------------------- ### SQL Schema for JWKS Table Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This SQL statement defines the schema for the `jwks` table, which is automatically created by Better Auth. It stores JSON Web Key Set information, including a unique `id` (key ID), `publicKey`, `privateKey`, and `createdAt` timestamp, essential for JWT encryption and decryption. ```sql CREATE TABLE jwks ( id TEXT PRIMARY KEY, # Key ID (kid) publicKey TEXT NOT NULL, # Public key (JSON format) privateKey TEXT NOT NULL, # Private key (used by Better Auth) createdAt TIMESTAMP NOT NULL # Key creation time ); ``` -------------------------------- ### Python FastAPI Endpoint for Task Creation with Error Handling Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This Python code defines a FastAPI endpoint for creating tasks, incorporating robust error handling. It uses `verify_jwt_token` to authenticate the user and checks if the `user_id` from the token matches the one in the request path. It includes a try-except block to catch potential HTTPExceptions and other exceptions, returning appropriate status codes. ```python from middleware.jwt import verify_jwt_token @router.post("/api/{user_id}/tasks") async def create_task( user_id: str, task_data: TaskCreate, current_user: Dict[str, str] = Depends(verify_jwt_token), ): try: # Verify user_id if current_user["user_id"] != user_id: raise HTTPException(status_code=403, detail="Forbidden") # Create task... return {"success": True} except HTTPException: raise except Exception as e: raise HTTPException(status_code=500, detail=str(e)) ``` -------------------------------- ### POST /api/{user_id}/tasks Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Creates a new task for the authenticated user. It verifies the user's identity using JWT and ensures they are creating the task for themselves. ```APIDOC ## POST /api/{user_id}/tasks ### Description Creates a new task for the authenticated user. Requires JWT verification and ensures the `user_id` in the path matches the authenticated user. ### Method POST ### Endpoint `/api/{user_id}/tasks` ### Parameters #### Path Parameters - **user_id** (str) - Required - The ID of the user for whom the task is being created. #### Query Parameters None #### Request Body - **title** (str) - Required - The title of the task. - **description** (str) - Optional - The description of the task. ### Request Example ```json { "title": "Schedule meeting", "description": "Discuss project roadmap" } ``` ### Response #### Success Response (200) - **success** (bool) - Indicates if the task creation was successful. #### Response Example ```json { "success": true } ``` ``` -------------------------------- ### Python Project Dependencies for JWT and Cryptography Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This `pyproject.toml` snippet specifies the backend project's Python dependencies. It requires `pyjwt` version 2.8.0 or higher for JWT handling and `cryptography` version 41.0.0 or higher to support cryptographic algorithms like EdDSA and RS256 used in JWT. ```toml [project] dependencies = [ "pyjwt>=2.8.0", # JWT library "cryptography>=41.0.0", # For EdDSA/RS256 support ] ``` -------------------------------- ### Python FastAPI Endpoint with User Isolation and DB Access Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This Python code snippet illustrates how to fetch a specific task for a user in a FastAPI application, ensuring user isolation. It utilizes `verify_jwt_token` for authentication and then queries the database using a `get_session` dependency. The code verifies that the requested task belongs to the authenticated user before returning it, raising a 404 error if not found. ```python @router.get("/api/{user_id}/tasks/{task_id}") async def get_task( user_id: str, task_id: int, current_user: Dict[str, str] = Depends(verify_jwt_token), db: Session = Depends(get_session), ): # 1. Verify JWT token (automatic via dependency) # 2. Verify user_id matches if current_user["user_id"] != user_id: raise HTTPException(status_code=403, detail="Forbidden") # 3. Query with user isolation task = db.get(Task, task_id) if not task or task.user_id != user_id: raise HTTPException(status_code=404, detail="Task not found") return {"success": True, "data": task} ``` -------------------------------- ### JWKS Endpoint Implementation (TypeScript) Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md An API endpoint that exposes public keys in JWKS format for JWT verification. It fetches keys from the database, formats them according to JWKS specifications including the key ID (kid), and returns them with appropriate caching headers for performance. ```typescript export async function GET() { // 1. Import database and schema const { db } = await import("@/lib/db-drizzle"); const { jwks } = await import("@/drizzle/schema"); // 2. Fetch all JWKS keys from database const keys = await db.select().from(jwks); // 3. Format as JWKS (JSON Web Key Set) const jwksResponse = { keys: keys.map((key) => { const publicKey = JSON.parse(key.publicKey); return { ...publicKey, kid: key.id, // Key ID }; }), }; // 4. Return with caching headers return new Response(JSON.stringify(jwksResponse), { status: 200, headers: { "Content-Type": "application/json", "Cache-Control": "public, max-age=3600", // Cache for 1 hour }, }); } ``` -------------------------------- ### Test Protected Endpoint with FastAPI Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This Python snippet illustrates how to test protected API endpoints in a FastAPI application using pytest and the TestClient. It includes tests for accessing an endpoint with a valid JWT token and for attempting to access it without a token, verifying the expected status codes (200 and 401 respectively) and error responses. ```python # backend/tests/test_tasks.py import pytest from fastapi.testclient import TestClient def test_get_tasks_with_valid_token(client: TestClient, valid_token: str): response = client.get( "/api/user123/tasks", headers={"Authorization": f"Bearer {valid_token}"} ) assert response.status_code == 200 assert response.json()["success"] is True def test_get_tasks_without_token(client: TestClient): response = client.get("/api/user123/tasks") assert response.status_code == 401 assert response.json()["error"]["code"] == "INVALID_TOKEN" ``` -------------------------------- ### Python FastAPI Endpoint with JWT Verification Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This Python code demonstrates how to protect a FastAPI endpoint using JWT verification via a `verify_jwt_token` dependency. It ensures that only authenticated users can access the endpoint and performs user ID matching for data isolation. It raises an HTTPException if the user ID from the token does not match the user ID in the path. ```python from fastapi import APIRouter, Depends, HTTPException from middleware.jwt import verify_jwt_token from typing import Dict router = APIRouter() @router.get("/api/{user_id}/tasks") async def get_tasks( user_id: str, current_user: Dict[str, str] = Depends(verify_jwt_token), # JWT verification ): # Verify user_id matches if current_user["user_id"] != user_id: raise HTTPException(status_code=403, detail="Forbidden") # Process request... return {"success": True, "data": []} ``` -------------------------------- ### Test JWT Verification with FastAPI Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md This Python snippet demonstrates how to test JWT token verification using pytest in a FastAPI backend. It utilizes a utility function `verify_jwt_token` to validate a token and asserts the presence and correctness of user information like 'user_id' and 'email'. ```python # backend/tests/test_auth.py import pytest from utils.auth import verify_jwt_token def test_verify_valid_token(): # Get token from Better Auth (after signin) token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." # Verify token user_info = verify_jwt_token(token) assert "user_id" in user_info assert "email" in user_info assert user_info["user_id"] == "expected-user-id" ``` -------------------------------- ### JWT Token Verification using JWKS in Python Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Verifies a JWT token using a JWKS client and decodes it to extract user information like user ID and email. It supports EdDSA and RS256 algorithms and handles token validation errors. ```python import jwt from typing import Dict def verify_jwt_token(token: str) -> Dict[str, str]: """ Verify JWT token and extract user information using JWKS. Args: token: JWT token string to verify Returns: dict: {"user_id": str, "email": str} Raises: ValueError: If token is invalid or expired """ try: # 1. Get JWKS client and signing key jwk_client = _get_cached_jwk_client() signing_key = jwk_client.get_signing_key_from_jwt(token) # 2. Verify and decode the JWT # Better Auth uses EdDSA (Ed25519) or RS256 by default payload = jwt.decode( token, signing_key.key, algorithms=["EdDSA", "RS256"], options={"verify_aud": False} # Better Auth doesn't use audience claim ) # 3. Extract user information from token user_id: str = payload.get("sub") or payload.get("user_id") email: str = payload.get("email", "") if not user_id: raise ValueError("Invalid token: missing user_id (sub claim)") return {"user_id": user_id, "email": email} except jwt.exceptions.PyJWTError as e: raise ValueError(f"Invalid token: {str(e)}") from e ``` -------------------------------- ### FastAPI Middleware for JWT Token Verification Source: https://github.com/hamza123545/how-to-use-better-auth-with-python-fast-api/blob/main/README.md Implements a FastAPI dependency function that uses HTTP Bearer authentication to extract and verify JWT tokens. It raises HTTPExceptions for invalid or expired tokens, providing clear error messages. ```python from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from utils.auth import verify_jwt_token as verify_token import jwt from typing import Dict # HTTP Bearer token scheme security = HTTPBearer() def verify_jwt_token( credentials: HTTPAuthorizationCredentials = Depends(security) ) -> Dict[str, str]: """ Verify JWT token and extract user information. This dependency function extracts the JWT token from the Authorization header, verifies it using JWKS, and returns the user information. Returns: dict: {"user_id": str, "email": str} Raises: HTTPException: 401 if token is invalid, expired, or missing """ token = credentials.credentials try: # Verify token and extract user information (uses JWKS) user_info = verify_token(token) return user_info except jwt.exceptions.ExpiredSignatureError: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "success": False, "error": {"code": "TOKEN_EXPIRED", "message": "Token has expired. Please sign in again."}, }, headers={"WWW-Authenticate": "Bearer"}, ) except jwt.exceptions.PyJWTError: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail={ "success": False, "error": {"code": "INVALID_TOKEN", "message": "Invalid token"}, }, headers={"WWW-Authenticate": "Bearer"}, ) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.