OAuth Providers
AnvilBase supports social login through eight OAuth providers, configured per
project: github, google, apple, discord, microsoft, facebook,
twitter, and linkedin.
How it works
- You register an OAuth app with the provider and get a client id + client secret.
- You add the provider to your AnvilBase project (client id/secret + scopes).
When the provider is enabled with both credentials, AnvilBase builds the
per-project Better Auth
socialProvidersconfig from it (client secrets are stored encrypted at rest and decrypted only for use). - Your app starts the flow at the GoTrue-compatible
GET /v1/auth/<project_id>/auth/v1/authorize?provider=<p>&redirect_to=<url>— exactly whatsupabase-jssignInWithOAuthhits. AnvilBase302s the browser to the provider’s consent screen. - After consent, the provider redirects back through AnvilBase’s callback,
which mints a project session (JWT pair) and
302s the browser to yourredirect_towith the tokens in the URL fragment:…#access_token=…&refresh_token=…&token_type=bearer&expires_in=3600. Your landing page adopts the session (the SDK’sgetSessionFromUrldoes this).
Security — open-redirect protection.
redirect_tois validated against the full-URL allow-listAUTH_ALLOWED_REDIRECT_URLS(comma-separated; scheme + host + path matched) at both/authorizeand/callback. Aredirect_tothat isn’t on the list is rejected with400. This is mandatory — an unvalidated OAuth redirect is a token-exfiltration hole. Secure-by-default: when the list is empty, no redirect target is allowed.
Register the OAuth app (provider side)
Set the callback / redirect URL at the provider to AnvilBase’s native
Better Auth callback (this is the URL the provider calls, distinct from your
app’s redirect_to):
https://<your-host>/v1/auth/<project_id>/api/project-auth/callback/<provider>(For local testing, swap the host for http://localhost:39001.)
Provider consoles:
- GitHub — Settings → Developer settings → OAuth Apps
- Google — Google Cloud Console → APIs & Services → Credentials
- Apple — Apple Developer → Certificates, Identifiers & Profiles → Services IDs
- Discord — Discord Developer Portal → Applications → OAuth2
- Microsoft — Azure Portal → App registrations
- Facebook — Meta for Developers → My Apps → Facebook Login
- Twitter — X Developer Portal → Projects & Apps → User authentication settings
- LinkedIn — LinkedIn Developers → Apps → Auth
Add the provider to your project
curl -X PUT http://localhost:39001/api/v1/projects/<id>/auth/providers \ -H "Authorization: Bearer $ANVILBASE_TOKEN" -H "Content-Type: application/json" \ -d '{ "provider": "github", "enabled": true, "client_id": "Iv1.abc123", "client_secret": "ghs_…", "scopes": ["read:user", "user:email"] }'- Both
client_idandclient_secretare required. scopesis optional — when empty, the provider’s recommended default scopes are used.- Returns
201when newly added,200when replacing an existing provider.
Discover recommended scopes
curl http://localhost:39001/api/v1/auth/templates -H "Authorization: Bearer $ANVILBASE_TOKEN"Lists each provider’s template and recommended scopes.
Read current configuration
Provider secrets come back masked:
curl http://localhost:39001/api/v1/projects/<id>/auth -H "Authorization: Bearer $ANVILBASE_TOKEN"{ "email_enabled": true, "magic_link_enabled": false, "providers": [ { "provider": "github", "enabled": true, "client_id": "Iv1.abc123", "client_secret_masked": "ghs_…cret", "scopes": ["read:user", "user:email"] } ]}Remove a provider
curl -X DELETE http://localhost:39001/api/v1/projects/<id>/auth/providers/github \ -H "Authorization: Bearer $ANVILBASE_TOKEN"Start the login flow from your app
With the AnvilBase SDK (all 7 clients expose signInWithOAuth):
// signInWithOAuth builds the /authorize URL and (in a browser) navigates to it.await db.auth.signInWithOAuth({ provider: "github", options: { redirectTo: "https://app.example.com/auth/callback" },})
// On your callback page, adopt the session from the URL fragment:db.auth.getSessionFromUrl(window.location.href)Or hit the endpoint directly:
window.location.href = `${HOST}/v1/auth/${PROJECT_ID}/auth/v1/authorize` + `?provider=github&redirect_to=${encodeURIComponent(REDIRECT)}`After the provider redirects back through AnvilBase’s callback, the browser lands
on your redirect_to with the session tokens in the URL fragment. The oauth.callback
audit event fires on a successful sign-in.
Native id-token sign-in
Native mobile apps (Sign-in-with-Apple / Google on iOS/Android) obtain a provider id-token directly from the OS SDK and exchange it server-side — there is no browser redirect. AnvilBase exposes the GoTrue-compatible grant for this:
POST /v1/auth/<project_id>/auth/v1/token?grant_type=id_tokenContent-Type: application/json
{ "provider": "apple", "token": "<provider-id-token>", "nonce": "<optional>", "access_token": "<optional>" }AnvilBase verifies the id-token’s signature, its audience (aud = the provider
client_id you configured for the project), and the nonce when supplied, then
find-or-creates + links the account and returns a project session (JWT pair)
whose app_metadata.provider reflects the real provider.
With the SDK:
await db.auth.signInWithIdToken({ provider: "apple", token: appleIdToken /*, nonce */ })Supported providers. The id-token grant is available only for providers with server-side id-token verification:
apple,microsoft. The provider must also be enabled (client id/secret configured) for the project.github,discord,400 provider_id_token_not_supported— use the redirect flow above for those. A disabled provider returns400 provider_not_enabled; an invalid/expired token returns401 invalid_grant.
In the console
Project → Auth tab → Providers. Toggle each provider, paste the client id/secret, and adjust scopes. Secrets are stored masked and never re-displayed in full.
Tips
- Use different OAuth apps per environment (dev/staging/prod) so callback URLs and secrets don’t bleed across deployments.
- Always request the email scope (
user:email,email) so AnvilBase can create/link the account by email. - Rotate the client secret at the provider and re-
PUTit here if it leaks; the old secret stops working as soon as the provider invalidates it.
Next: Email & Templates.