OAuth
Google, GitHub, Apple, and how to add another social provider.
Social login is configured in packages/auth/src/index.ts. Enabled providers are listed by getEnabledSocialProviders() in packages/auth/src/social-providers.ts.
Redirect URIs use the SaaS origin that mounts /api/auth:
{SAAS_URL}/api/auth/callback/{provider}
Google (required)
Set in the root .env:
GOOGLE_CLIENT_ID=…
GOOGLE_CLIENT_SECRET=…Redirect URI: {SAAS_URL}/api/auth/callback/google.
GitHub (optional)
GITHUB_CLIENT_ID=…
GITHUB_CLIENT_SECRET=…Include user:email scope / email read permission. Redirect URI: {SAAS_URL}/api/auth/callback/github.
When unset, isGithubOAuthConfigured() is false and the GitHub button stays hidden on the SaaS UI.
Apple (optional)
APPLE_CLIENT_ID=…
APPLE_TEAM_ID=…
APPLE_KEY_ID=…
APPLE_PRIVATE_KEY=… # .p8 contents; use \n for newlinesThe client secret JWT is generated at runtime with jose (generateAppleClientSecret).
Apple does not support http://localhost return URLs — use HTTPS (tunnel) in development. Redirect URI: {SAAS_URL}/api/auth/callback/apple.
When unset, the Apple button is hidden.
trustedOrigins / allowedDevOrigins already include https://appleid.apple.com.
Which providers are enabled?
export function getEnabledSocialProviders(): SocialProviderId[] {
const providers: SocialProviderId[] = ["google"];
if (isGithubOAuthConfigured()) providers.push("github");
if (isAppleOAuthConfigured()) providers.push("apple");
return providers;
}Adding another provider
Example: Facebook.
- Create an app in the Facebook developer console and copy the client ID and secret.
- Add env vars (and wire them through
@repo/envthe same way GitHub/Apple are gated). - Register the provider on the Better Auth instance:
socialProviders.facebook = {
clientId: env.FACEBOOK_CLIENT_ID,
clientSecret: env.FACEBOOK_CLIENT_SECRET,
};- On the SaaS auth UI in the full TurboJet monorepo, add the provider to the OAuth providers map (icon + label) so the login page shows a button.
Learn more in the Better Auth Facebook docs.