How It Works
The authentication flow follows these steps:User Authentication
Users sign in via email/password or OAuth (Google) through Better Auth. Better Auth manages the session securely.
JWT Token Issuance
When your frontend needs to call your backend API, it requests a JWT from Better Auth via the
/api/auth/token endpoint. The JWT is signed with the server’s private key (Ed25519 by default).Token Transmission
The frontend includes the JWT in the
Authorization: Bearer <token> header when making API requests to your backend.Why JWKS?
JWKS (JSON Web Key Set) provides several advantages over traditional shared secret approaches:No Shared Secrets
Your backend never needs to know the private signing key. It only uses public keys to verify signatures.
Key Rotation
Better Auth can rotate signing keys without requiring backend redeployment. New keys are automatically discovered via the JWKS endpoint.
Multiple Backends
Multiple backend services can all verify tokens using the same JWKS endpoint without sharing credentials.
Industry Standard
JWKS is a widely adopted standard (RFC 7517) with robust library support across all major programming languages.
Authentication Flow Diagram
Token Structure
Better Auth issues JWTs with the following standard claims:| Claim | Description | Example |
|---|---|---|
sub | User ID (subject) | "abc123def456" |
iss | Issuer (Better Auth URL) | "http://localhost:3000" |
aud | Audience (Better Auth URL) | "http://localhost:3000" |
exp | Expiration timestamp | 1234567890 |
iat | Issued at timestamp | 1234567800 |
email | User’s email address | "[email protected]" |
name | User’s display name | "John Doe" |
JWTs are short-lived by default (typically 1 hour). The frontend automatically refreshes tokens when they’re close to expiration (within 10 seconds).
API Client Integration
The boilerplate includes two ready-to-use API clients with automatic JWT injection:- Cache JWTs and refresh them automatically when close to expiration
- Add a 10-second buffer to prevent using tokens about to expire
- Include the token in the
Authorization: Bearer <token>header - Handle token errors gracefully
Backend Implementation Guides
Choose your backend language to see complete integration examples:Go
JWT verification with
github.com/lestrrat-go/jwxPython
Flask middleware with
PyJWT and PyJWKClientExpress
Express middleware with
jose librarySecurity Best Practices
Always Use HTTPS in Production
JWTs transmitted over HTTP can be intercepted. Always use TLS/HTTPS for both your frontend and backend in production.Verify Signatures, Don’t Just Decode
Never trust the JWT payload without verifying the signature against the JWKS public keys. Simply decoding a JWT doesn’t prove authenticity.Validate Token Claims
Always validate theiss (issuer), aud (audience), and exp (expiration) claims:
Respect Token Expiration
Always check theexp claim and reject expired tokens. Most JWT libraries do this automatically during verification.
Cache JWKS Keys Appropriately
Fetching JWKS keys on every request is inefficient. Cache them with a reasonable TTL (e.g., 1 hour), but be prepared to refresh if verification fails with an unknown key ID.Next Steps
JWKS Endpoint Details
Learn how the JWKS endpoint works and how to implement key rotation