better-auth-python

Better Auth Python Integration Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "better-auth-python" with this command: npx skills add naimalarain13/hackathon-ii_the-evolution-of-todo/naimalarain13-hackathon-ii-the-evolution-of-todo-better-auth-python

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

  • Always use HTTPS in production

  • Validate issuer and audience to prevent token substitution

  • Handle token expiration gracefully

  • Refresh JWKS when encountering unknown key IDs

  • 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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

chatkit-python

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

openai-agents-sdk

No summary provided by upstream source.

Repository SourceNeeds Review
General

framer-motion

No summary provided by upstream source.

Repository SourceNeeds Review