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 holds the providers you chose at init (it may be empty), and only those buttons render;.env.exampleseeds credentials for those same providers.- 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 seeds placeholders for the providers you selected at init; vars for any other provider are still valid, just not listed - 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.