Provider Integration
Two-Layer Model
Section titled “Two-Layer Model”Provider configuration has two layers. They are independent and both must be in place for a provider to be usable.
| Layer | Where | Scope | Configuration Method |
|---|---|---|---|
| Credentials | .env file | Global (all applications) | Environment variables |
| Toggle | Admin Console | Per application | Auth Policy → allowed_providers |
A provider must have its credentials configured in .env first. Once
configured, it becomes globally available and can be toggled on or off
per application in the Auth Policy section.
Credential Flow
Section titled “Credential Flow”.env GOOGLE_CLIENT_ID=xxx GOOGLE_CLIENT_SECRET=xxx
| ▼
betterAuth({ socialProviders: { google: { clientId: xxx, clientSecret: xxx } }})
| ▼
Better Auth registers OAuth routes: GET /api/auth/oauth2/callback/google
| ▼
User clicks "Sign in with Google" on any SaaS → Redirected to accounts.google.com → Google calls back to /api/auth/callback/google → Better Auth verifies the code → User is authenticatedPer-Application Control
Section titled “Per-Application Control”Once a provider is configured globally, each application’s Auth Policy controls whether the provider is available for that specific application:
Application A (Acme) allowed_providers: ["email", "google"] → "Sign in with Google" appears on Acme's login page
Application B (gamma) allowed_providers: ["email"] → "Sign in with Google" does NOT appear on niche's login pageThis is enforced by the AllowedProviders policy in the SignupPolicyChain.
Even if a user somehow reaches /api/auth/sign-in/social for a disabled
provider, the policy engine rejects the request.
Supported Providers
Section titled “Supported Providers”| Provider | Requires | Status |
|---|---|---|
| Email + Password | Nothing | Always enabled |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | Configurable | |
| Apple Sign In | APPLE_CLIENT_ID, APPLE_TEAM_ID, APPLE_KEY_ID, APPLE_PRIVATE_KEY | Configurable |
| GitHub | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET | Configurable |