Social OAuth
Enable Google, GitHub, Facebook, Discord, and X sign-in via config.auth.socialProviders.
Social login is powered by Better Auth in the @repo/auth package and gated entirely by config.auth.socialProviders. Each id you list renders a sign-in button; list nothing and the whole social block disappears.
How it works
config.auth.socialProvidersis an array of provider ids (google,github,facebook,discord,x). It starts empty ([]); add provider ids here to render their buttons, and only those buttons render.- A provider registers server-side only when both its env vars are set - the
socialProvidersblock inpackages/auth/src/config.tsspreads each one in conditionally. - The Nuxt
AuthSocialButtons.vuecomponent reads the same array and renders one button per id, labelled fromSOCIAL_PROVIDERS_METAvia$t. - Clicking a button signs in through
authClient.signIn.social.
Supported providers
Each provider needs a client ID + secret in your environment. Ids and env vars come from SOCIAL_PROVIDERS_META (packages/config/src/social-providers.ts):
| Provider | Id | Env vars |
|---|---|---|
google | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | |
| GitHub | github | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET |
facebook | FACEBOOK_CLIENT_ID, FACEBOOK_CLIENT_SECRET | |
| Discord | discord | DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET |
| X | x | TWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET |
The X provider uses the legacy TWITTER_* env prefix, not X_*. Set TWITTER_CLIENT_ID / TWITTER_CLIENT_SECRET.
Enable a provider
Add the id to config.auth.socialProviders:
auth: {
socialProviders: ["google", "github"], // buttons render in this order
},Set the matching env vars. .env.example doesn't seed social OAuth placeholders - copy the names from the table above.
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...Set the OAuth app's redirect URL in the provider's developer console to <API_URL>/auth/callback/<provider> - Better Auth's baseURL is ${API_URL}/auth, and API_URL already ends in /api. With the default API_URL=http://localhost:3000/api that resolves to http://localhost:3000/api/auth/callback/google.
For X, the callback <provider> segment is twitter (Better Auth's underlying provider name), e.g. <API_URL>/auth/callback/twitter - not .../callback/x.
An id can be in config.auth.socialProviders but missing its env vars - the button still renders, yet sign-in fails because the provider was never registered server-side. Keep the array and your env in sync.
Removing a provider
- Drop the id from
config.auth.socialProvidersand its button disappears instantly - no component changes needed. - The array order is the display order of the buttons.
- An empty array hides the entire social-login section, leaving only email/password (and any enabled passkey button).
Frequently asked questions
Why does my button do nothing / error on click?
Its env vars are unset, so the provider never registered server-side. The button renders off the config array, but registration needs both *_CLIENT_ID and *_CLIENT_SECRET set.
Why is the X provider using TWITTER_* env vars?
The provider id is x, but Better Auth's underlying provider is still named twitter - so the credentials use the TWITTER_CLIENT_ID / TWITTER_CLIENT_SECRET names.
Can I add a provider not in the list?
The five ids in SOCIAL_PROVIDERS_META are wired end-to-end. Adding others means extending that metadata plus the socialProviders block in packages/auth/src/config.ts.