- Official demo to showcase better-auth. features and capabilities.
+ Official demo to showcase{" "}
+
+ better-auth.
+ {" "}
+ features and capabilities.
@@ -22,14 +37,17 @@ export default async function Home() {
- All features on this demo are Implemented with better auth without any custom backend code
+ All features on this demo are Implemented with better auth
+ without any custom backend code
-
- {features.map(feature => (
-
+ {features.map((feature) => (
+
{feature}.
))}
diff --git a/demo/nextjs/lib/auth.ts b/demo/nextjs/lib/auth.ts
index 106e6ad3..646312d6 100644
--- a/demo/nextjs/lib/auth.ts
+++ b/demo/nextjs/lib/auth.ts
@@ -75,14 +75,14 @@ export const auth = betterAuth({
}),
passkey(),
],
- socialProvider: [
- github({
+ socialProviders: {
+ github: {
clientId: process.env.GITHUB_CLIENT_ID || "",
clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
- }),
- google({
+ },
+ google: {
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
- }),
- ],
+ },
+ },
});
diff --git a/docs/content/docs/authentication/apple.mdx b/docs/content/docs/authentication/apple.mdx
index 11a306ba..bd286952 100644
--- a/docs/content/docs/authentication/apple.mdx
+++ b/docs/content/docs/authentication/apple.mdx
@@ -33,18 +33,12 @@ description: Apple
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- apple({ // [!code highlight]
+ socialProvider: { // [!code highlight]
+ apple: { // [!code highlight]
clientId: process.env.APPLE_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.APPLE_CLIENT_SECRET as string, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ } // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/discord.mdx b/docs/content/docs/authentication/discord.mdx
index bc75ceb7..668fdf60 100644
--- a/docs/content/docs/authentication/discord.mdx
+++ b/docs/content/docs/authentication/discord.mdx
@@ -29,18 +29,12 @@ description: Discord Provider
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- discord({ // [!code highlight]
+ socialProvider: { // [!code highlight]
+ discord: { // [!code highlight]
clientId: process.env.DISCORD_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.DISCORD_CLIENT_SECRET as string, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ }, // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/facebook.mdx b/docs/content/docs/authentication/facebook.mdx
index 16a3501b..004110cf 100644
--- a/docs/content/docs/authentication/facebook.mdx
+++ b/docs/content/docs/authentication/facebook.mdx
@@ -29,18 +29,12 @@ description: Facebook Provider
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- facebook({ // [!code highlight]
+ socialProvider: { // [!code highlight]
+ facebook: { // [!code highlight]
clientId: process.env.FACEBOOK_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.FACEBOOK_CLIENT_SECRET as string, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ }, // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/github.mdx b/docs/content/docs/authentication/github.mdx
index 5b223efd..9056656c 100644
--- a/docs/content/docs/authentication/github.mdx
+++ b/docs/content/docs/authentication/github.mdx
@@ -30,16 +30,10 @@ description: Github Provider
url: "./db.sqlite",
},
socialProvider: [ // [!code highlight]
- github({ // [!code highlight]
+ github: { // [!code highlight]
clientId: process.env.GITHUB_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.GITHUB_CLIENT_SECRET as string, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
+ }, // [!code highlight]
], // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/google.mdx b/docs/content/docs/authentication/google.mdx
index 065b980f..90eae9bd 100644
--- a/docs/content/docs/authentication/google.mdx
+++ b/docs/content/docs/authentication/google.mdx
@@ -29,8 +29,8 @@ description: Google Provider
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- google({ // [!code highlight]
+ socialProvider: { // [!code highlight]
+ google: { // [!code highlight]
clientId: process.env.GOOGLE_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, // [!code highlight]
/** // [!code highlight]
@@ -39,8 +39,8 @@ description: Google Provider
* or if you're using a custom domain. // [!code highlight]
*/ // [!code highlight]
redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ }, // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/spotify.mdx b/docs/content/docs/authentication/spotify.mdx
index 6f93b4b9..52380b4a 100644
--- a/docs/content/docs/authentication/spotify.mdx
+++ b/docs/content/docs/authentication/spotify.mdx
@@ -29,18 +29,12 @@ description: Spotify Provider
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- spotify({ // [!code highlight]
+ socialProvider: { // [!code highlight]
+ spotify: { // [!code highlight]
clientId: process.env.SPOTIFY_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.SPOTIFY_CLIENT_SECRET as string, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ }, // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/twitch.mdx b/docs/content/docs/authentication/twitch.mdx
index 8714f719..061c8724 100644
--- a/docs/content/docs/authentication/twitch.mdx
+++ b/docs/content/docs/authentication/twitch.mdx
@@ -29,18 +29,12 @@ description: Twitch Provider
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- twitch({ // [!code highlight]
+ socialProvider: { // [!code highlight]
+ twitch: { // [!code highlight]
clientId: process.env.TWITCH_CLIENT_ID as string, // [!code highlight]
clientSecret: process.env.TWITCH_CLIENT_SECRET as string, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ }, // [!code highlight]
+ } // [!code highlight]
})
```
diff --git a/docs/content/docs/authentication/twitter.mdx b/docs/content/docs/authentication/twitter.mdx
index 398d5fd9..5d585ab7 100644
--- a/docs/content/docs/authentication/twitter.mdx
+++ b/docs/content/docs/authentication/twitter.mdx
@@ -29,18 +29,12 @@ description: Twitter Provider
provider: "sqlite",
url: "./db.sqlite",
},
- ocialProvider: [ // [!code highlight]
- twitter({ // [!code highlight]
+ socialProvider: {// [!code highlight]
+ twitter: { // [!code highlight]
clientId: process.env.TWITTER_CLIENT_ID, // [!code highlight]
clientSecret: process.env.TWITTER_CLIENT_SECRET, // [!code highlight]
- /** // [!code highlight]
- * this is optional. // [!code highlight]
- * only needed if you passed a custom basePath from `/api/auth` to `betterAuth` // [!code highlight]
- * or if you're using a custom domain. // [!code highlight]
- */ // [!code highlight]
- redirectURI: "https://example.com/api/auth/callback/apple", // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ }, // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/basic-usage.mdx b/docs/content/docs/basic-usage.mdx
index 77523703..3b6baa40 100644
--- a/docs/content/docs/basic-usage.mdx
+++ b/docs/content/docs/basic-usage.mdx
@@ -97,12 +97,12 @@ export const auth = betterAuth({
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- github({ // [!code highlight]
- clientId: GITHUB_CLIENT_ID, // [!code highlight]
- clientSecret: GITHUB_CLIENT_SECRET, // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ socialProvider: { // [!code highlight]
+ github: { // [!code highlight]
+ clientId: GITHUB_CLIENT_ID, // [!code highlight]
+ clientSecret: GITHUB_CLIENT_SECRET, // [!code highlight]
+ } // [!code highlight]
+ }, // [!code highlight]
})
```
diff --git a/docs/content/docs/installation.mdx b/docs/content/docs/installation.mdx
index 14105644..61958889 100644
--- a/docs/content/docs/installation.mdx
+++ b/docs/content/docs/installation.mdx
@@ -123,12 +123,12 @@ export const auth = betterAuth({
provider: "sqlite",
url: "./db.sqlite",
},
- socialProvider: [ // [!code highlight]
- github({ // [!code highlight]
- clientId: process.env.GITHUB_CLIENT_ID as string, // [!code highlight]
- clientSecret: process.env.GITHUB_CLIENT_SECRET as string, // [!code highlight]
- }), // [!code highlight]
- ], // [!code highlight]
+ socialProvider: { // [!code highlight]
+ github: { // [!code highlight]
+ clientId: GITHUB_CLIENT_ID, // [!code highlight]
+ clientSecret: GITHUB_CLIENT_SECRET, // [!code highlight]
+ } // [!code highlight]
+ }, // [!code highlight]
emailAndPassword: { // [!code highlight]
enabled: true // [!code highlight]
}// [!code highlight]
diff --git a/packages/better-auth/src/api/routes/callback.ts b/packages/better-auth/src/api/routes/callback.ts
index 15c03d20..020e20a8 100644
--- a/packages/better-auth/src/api/routes/callback.ts
+++ b/packages/better-auth/src/api/routes/callback.ts
@@ -31,7 +31,7 @@ export const callbackOAuth = createAuthEndpoint(
);
}
- const provider = c.context.options.socialProvider?.find(
+ const provider = c.context.socialProviders.find(
(p) => p.id === c.params.id,
);
if (!provider) {
diff --git a/packages/better-auth/src/api/routes/sign-in.ts b/packages/better-auth/src/api/routes/sign-in.ts
index 06c739ca..730282e2 100644
--- a/packages/better-auth/src/api/routes/sign-in.ts
+++ b/packages/better-auth/src/api/routes/sign-in.ts
@@ -37,7 +37,7 @@ export const signInOAuth = createAuthEndpoint(
}),
},
async (c) => {
- const provider = c.context.options.socialProvider?.find(
+ const provider = c.context.socialProviders.find(
(p) => p.id === c.body.provider,
);
if (!provider) {
diff --git a/packages/better-auth/src/init.ts b/packages/better-auth/src/init.ts
index 245aaa22..8284b4fd 100644
--- a/packages/better-auth/src/init.ts
+++ b/packages/better-auth/src/init.ts
@@ -4,7 +4,7 @@ import { createKyselyAdapter } from "./adapters/kysely";
import { getAdapter } from "./adapters/utils";
import { hashPassword, verifyPassword } from "./crypto/password";
import { createInternalAdapter } from "./db";
-import type { BetterAuthOptions } from "./types";
+import type { BetterAuthOptions, OAuthProvider } from "./types";
import { getBaseURL } from "./utils/base-url";
import { DEFAULT_SECRET } from "./utils/constants";
import {
@@ -13,6 +13,7 @@ import {
getCookies,
} from "./utils/cookies";
import { createLogger } from "./utils/logger";
+import { oAuthProviderList, oAuthProviders } from "./social-providers";
export const init = (options: BetterAuthOptions) => {
const adapter = getAdapter(options);
@@ -30,8 +31,19 @@ export const init = (options: BetterAuthOptions) => {
const cookies = getCookies(options);
const tables = getAuthTables(options);
+
+ const socialProviders = Object.keys(options.socialProviders || {})
+ .map((key) => {
+ const value = options.socialProviders?.[key as "github"]!;
+ if (value.enabled === false) {
+ return null;
+ }
+ return oAuthProviders[key as (typeof oAuthProviderList)[number]](value);
+ })
+ .filter((x) => x !== null);
return {
appName: options.appName || "Better Auth",
+ socialProviders,
options: {
...options,
baseURL: baseURL ? new URL(baseURL).origin : "",
@@ -63,6 +75,7 @@ export type AuthContext = {
options: BetterAuthOptions;
appName: string;
baseURL: string;
+ socialProviders: OAuthProvider[];
authCookies: BetterAuthCookies;
logger: ReturnType;
db: Kysely;
diff --git a/packages/better-auth/src/social-providers/index.ts b/packages/better-auth/src/social-providers/index.ts
index 594f176f..54037c12 100644
--- a/packages/better-auth/src/social-providers/index.ts
+++ b/packages/better-auth/src/social-providers/index.ts
@@ -1,3 +1,4 @@
+import type { Prettify } from "../types";
import { apple } from "./apple";
import { discord } from "./discord";
import { facebook } from "./facebook";
@@ -23,6 +24,14 @@ export const oAuthProviderList = Object.keys(oAuthProviders) as [
...(keyof typeof oAuthProviders)[],
];
+export type SocialProviders = typeof oAuthProviders extends {
+ [key in infer K]: infer V;
+}
+ ? V extends (options: infer V) => any
+ ? Partial>>
+ : never
+ : never;
+
export * from "./github";
export * from "./google";
export * from "./apple";
diff --git a/packages/better-auth/src/test-utils/test-instance.ts b/packages/better-auth/src/test-utils/test-instance.ts
index a8a1523e..7f981e81 100644
--- a/packages/better-auth/src/test-utils/test-instance.ts
+++ b/packages/better-auth/src/test-utils/test-instance.ts
@@ -1,14 +1,12 @@
import fs from "fs/promises";
import { alphabet, generateRandomString } from "oslo/crypto";
-import { afterAll, beforeAll } from "vitest";
+import { afterAll } from "vitest";
import { betterAuth } from "../auth";
import { createAuthClient } from "../client/vanilla";
-import { github, google } from "../social-providers";
import type { BetterAuthOptions } from "../types";
import { getMigrations } from "../cli/utils/get-migration";
import { parseSetCookieHeader } from "../utils/cookies";
import type { SuccessContext } from "@better-fetch/fetch";
-import { createKyselyAdapter } from "../adapters/kysely";
import { getAdapter } from "../adapters/utils";
export async function getTestInstance>(
@@ -22,16 +20,16 @@ export async function getTestInstance>(
const randomStr = generateRandomString(4, alphabet("a-z"));
const dbName = `./.db/test-${randomStr}.db`;
const opts = {
- socialProvider: [
- github({
+ socialProviders: {
+ github: {
clientId: "test",
clientSecret: "test",
- }),
- google({
+ },
+ google: {
clientId: "test",
clientSecret: "test",
- }),
- ],
+ },
+ },
secret: "better-auth.secret",
database: {
provider: "sqlite",
diff --git a/packages/better-auth/src/types/options.ts b/packages/better-auth/src/types/options.ts
index 495b6bc0..d47376cc 100644
--- a/packages/better-auth/src/types/options.ts
+++ b/packages/better-auth/src/types/options.ts
@@ -2,7 +2,8 @@ import type { Dialect } from "kysely";
import type { User } from "../adapters/schema";
import type { FieldAttribute } from "../db/field";
import type { BetterAuthPlugin } from "./plugins";
-import type { OAuthProvider, OAuthProviderList } from "./provider";
+import type { OAuthProviderList } from "./provider";
+import type { SocialProviders } from "../social-providers";
export interface BetterAuthOptions {
/**
@@ -57,9 +58,9 @@ export interface BetterAuthOptions {
/**
* list of social providers
*/
- socialProvider?: OAuthProvider[];
+ socialProviders?: SocialProviders;
/**
- * Plugins
+ * List of Better Auth plugins
*/
plugins?: BetterAuthPlugin[];
/**