✨ feat: add Google and Apple OAuth via better-auth socialProviders
This commit is contained in:
51
src/lib/build-social-providers.ts
Normal file
51
src/lib/build-social-providers.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Builds the `socialProviders` config object for betterAuth().
|
||||
*
|
||||
* Only includes a provider when ALL of its required env vars are present
|
||||
* (non-empty strings). This lets the app start without Google/Apple
|
||||
* credentials and enables providers incrementally via env vars.
|
||||
*/
|
||||
|
||||
type Env = Record<string, string | undefined>;
|
||||
|
||||
export interface SocialProviderConfig {
|
||||
google?: {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
};
|
||||
apple?: {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
appBundleIdentifier?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function buildSocialProviders(env: Env): SocialProviderConfig {
|
||||
const providers: SocialProviderConfig = {};
|
||||
|
||||
// Google — needs clientId + clientSecret
|
||||
if (env.AUTH_GOOGLE_CLIENT_ID && env.AUTH_GOOGLE_CLIENT_SECRET) {
|
||||
providers.google = {
|
||||
clientId: env.AUTH_GOOGLE_CLIENT_ID,
|
||||
clientSecret: env.AUTH_GOOGLE_CLIENT_SECRET,
|
||||
};
|
||||
}
|
||||
|
||||
// Apple — needs clientId, clientSecret (pre-generated JWT), teamId, keyId,
|
||||
// and privateKey. If the caller has already generated the JWT client secret
|
||||
// and stored it in AUTH_APPLE_CLIENT_SECRET, all five vars must be present.
|
||||
if (
|
||||
env.AUTH_APPLE_CLIENT_ID &&
|
||||
env.AUTH_APPLE_CLIENT_SECRET &&
|
||||
env.AUTH_APPLE_TEAM_ID &&
|
||||
env.AUTH_APPLE_KEY_ID &&
|
||||
env.AUTH_APPLE_PRIVATE_KEY
|
||||
) {
|
||||
providers.apple = {
|
||||
clientId: env.AUTH_APPLE_CLIENT_ID,
|
||||
clientSecret: env.AUTH_APPLE_CLIENT_SECRET,
|
||||
};
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
61
src/lib/get-sign-in-providers.ts
Normal file
61
src/lib/get-sign-in-providers.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Returns the ordered list of available sign-in providers based on which
|
||||
* environment variables are configured.
|
||||
*
|
||||
* Used by the sign-in page to render provider buttons.
|
||||
*
|
||||
* signInMethod:
|
||||
* - "social" → call signIn.social({ provider: id, callbackURL })
|
||||
* - "oauth2" → call signIn.oauth2({ providerId: id, callbackURL })
|
||||
*/
|
||||
|
||||
type Env = Record<string, string | undefined>;
|
||||
|
||||
export interface SignInProvider {
|
||||
id: string;
|
||||
label: string;
|
||||
signInMethod: "social" | "oauth2";
|
||||
}
|
||||
|
||||
export function getSignInProviders(env: Env): SignInProvider[] {
|
||||
const providers: SignInProvider[] = [];
|
||||
|
||||
// Authentik (genericOAuth)
|
||||
if (
|
||||
env.AUTH_AUTHENTIK_CLIENT_ID &&
|
||||
env.AUTH_AUTHENTIK_CLIENT_SECRET &&
|
||||
env.AUTH_AUTHENTIK_ISSUER
|
||||
) {
|
||||
providers.push({
|
||||
id: "authentik",
|
||||
label: "Authentik",
|
||||
signInMethod: "oauth2",
|
||||
});
|
||||
}
|
||||
|
||||
// Google (socialProviders)
|
||||
if (env.AUTH_GOOGLE_CLIENT_ID && env.AUTH_GOOGLE_CLIENT_SECRET) {
|
||||
providers.push({
|
||||
id: "google",
|
||||
label: "Google",
|
||||
signInMethod: "social",
|
||||
});
|
||||
}
|
||||
|
||||
// Apple (socialProviders) — all five vars required
|
||||
if (
|
||||
env.AUTH_APPLE_CLIENT_ID &&
|
||||
env.AUTH_APPLE_CLIENT_SECRET &&
|
||||
env.AUTH_APPLE_TEAM_ID &&
|
||||
env.AUTH_APPLE_KEY_ID &&
|
||||
env.AUTH_APPLE_PRIVATE_KEY
|
||||
) {
|
||||
providers.push({
|
||||
id: "apple",
|
||||
label: "Apple",
|
||||
signInMethod: "social",
|
||||
});
|
||||
}
|
||||
|
||||
return providers;
|
||||
}
|
||||
Reference in New Issue
Block a user