Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    syedaashnaghazanfar

    better-auth-python

    syedaashnaghazanfar/better-auth-python
    Security
    3
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Better Auth JWT verification for Python/FastAPI backends. Use when integrating Python APIs with a Better Auth TypeScript server via JWT tokens...

    SKILL.md

    Better Auth Python Integration Skill

    Integrate Python/FastAPI backends with Better Auth (TypeScript) authentication server using JWT verification.

    Architecture

    ┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
    │   Next.js App   │────▶│  Better Auth    │────▶│   PostgreSQL    │
    │   (Frontend)    │     │  (Auth Server)  │     │   (Database)    │
    └────────┬────────┘     └────────┬────────┘     └─────────────────┘
             │                       │
             │ JWT Token             │ JWKS Endpoint
             ▼                       ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │                     FastAPI Backend                              │
    │                   (Verifies JWT tokens)                          │
    └─────────────────────────────────────────────────────────────────┘
    

    Quick Start

    Installation

    # pip
    pip install fastapi uvicorn pyjwt cryptography httpx
    
    # poetry
    poetry add fastapi uvicorn pyjwt cryptography httpx
    
    # uv
    uv add fastapi uvicorn pyjwt cryptography httpx
    

    Environment Variables

    DATABASE_URL=postgresql://user:password@localhost:5432/mydb
    BETTER_AUTH_URL=http://localhost:3000
    

    ORM Integration (Choose One)

    ORM Guide
    SQLModel reference/sqlmodel.md
    SQLAlchemy reference/sqlalchemy.md

    Basic JWT Verification

    # app/auth.py
    import os
    import httpx
    import jwt
    from dataclasses import dataclass
    from typing import Optional
    from fastapi import HTTPException, Header, status
    
    BETTER_AUTH_URL = os.getenv("BETTER_AUTH_URL", "http://localhost:3000")
    
    @dataclass
    class User:
        id: str
        email: str
        name: Optional[str] = None
    
    _jwks_cache: dict = {}
    
    async def get_jwks() -> dict:
        global _jwks_cache
        if not _jwks_cache:
            async with httpx.AsyncClient() as client:
                response = await client.get(f"{BETTER_AUTH_URL}/.well-known/jwks.json")
                response.raise_for_status()
                _jwks_cache = response.json()
        return _jwks_cache
    
    async def verify_token(token: str) -> User:
        if token.startswith("Bearer "):
            token = token[7:]
    
        jwks = await get_jwks()
        public_keys = {}
        for key in jwks.get("keys", []):
            public_keys[key["kid"]] = jwt.algorithms.RSAAlgorithm.from_jwk(key)
    
        unverified_header = jwt.get_unverified_header(token)
        kid = unverified_header.get("kid")
    
        if not kid or kid not in public_keys:
            raise HTTPException(status_code=401, detail="Invalid token key")
    
        payload = jwt.decode(token, public_keys[kid], algorithms=["RS256"])
    
        return User(
            id=payload.get("sub"),
            email=payload.get("email"),
            name=payload.get("name"),
        )
    
    async def get_current_user(
        authorization: str = Header(..., alias="Authorization")
    ) -> User:
        return await verify_token(authorization)
    

    Protected Route

    from fastapi import Depends
    from app.auth import User, get_current_user
    
    @app.get("/api/me")
    async def get_me(user: User = Depends(get_current_user)):
        return {"id": user.id, "email": user.email, "name": user.name}
    

    Examples

    Pattern Guide
    Protected Routes examples/protected-routes.md
    JWT Verification examples/jwt-verification.md

    Templates

    Template Purpose
    templates/auth.py JWT verification module
    templates/main.py FastAPI app template
    templates/database_sqlmodel.py SQLModel database setup
    templates/models_sqlmodel.py SQLModel models

    Quick SQLModel Example

    from sqlmodel import SQLModel, Field, Session, select
    from typing import Optional
    from datetime import datetime
    
    class Task(SQLModel, table=True):
        id: Optional[int] = Field(default=None, primary_key=True)
        title: str = Field(index=True)
        completed: bool = Field(default=False)
        user_id: str = Field(index=True)  # From JWT 'sub' claim
    
    @app.get("/api/tasks")
    async def get_tasks(
        user: User = Depends(get_current_user),
        session: Session = Depends(get_session),
    ):
        statement = select(Task).where(Task.user_id == user.id)
        return session.exec(statement).all()
    

    Frontend Integration

    Getting JWT from Better Auth

    import { authClient } from "./auth-client";
    
    const { data } = await authClient.token();
    const jwtToken = data?.token;
    

    Sending to FastAPI

    async function fetchAPI(endpoint: string) {
      const { data } = await authClient.token();
    
      return fetch(`${API_URL}${endpoint}`, {
        headers: {
          Authorization: `Bearer ${data?.token}`,
          "Content-Type": "application/json",
        },
      });
    }
    

    Security Considerations

    1. Always use HTTPS in production
    2. Validate issuer and audience to prevent token substitution
    3. Handle token expiration gracefully
    4. Refresh JWKS when encountering unknown key IDs
    5. Don't log tokens - they contain sensitive data

    Troubleshooting

    JWKS fetch fails

    • Ensure Better Auth server is running
    • Check JWKS endpoint is accessible
    • Verify network connectivity

    Token validation fails

    • Check issuer/audience match exactly
    • Verify token hasn't expired
    • Check algorithm compatibility (RS256)

    CORS errors

    • Configure CORS middleware properly
    • Allow credentials if using cookies
    • Check origin is in allowed list
    Recommended Servers
    Codeinterpreter
    Codeinterpreter
    Vercel Grep
    Vercel Grep
    WorkOS
    WorkOS
    Repository
    syedaashnaghazanfar/full-stack-todo-app
    Files