feat: support apple sso auth (#10563)

This commit is contained in:
YuTengjing
2025-12-03 01:04:54 +08:00
committed by GitHub
parent e50a7b7d30
commit 2e50313986
6 changed files with 67 additions and 4 deletions
+2 -1
View File
@@ -656,7 +656,8 @@ export class SessionModel {
const results = await this.db.query.agents.findMany({
limit: pageSize,
offset,
orderBy: [desc(agents.updatedAt)],
// Keep deterministic ordering for keyword search results
orderBy: [asc(agents.id)],
where: and(
eq(agents.userId, this.userId),
or(
+11 -2
View File
@@ -19,6 +19,8 @@ import { EmailService } from '@/server/services/email';
const VERIFICATION_LINK_EXPIRES_IN = 3600;
const MAGIC_LINK_EXPIRES_IN = 900;
const enableMagicLink = authEnv.NEXT_PUBLIC_ENABLE_MAGIC_LINK;
const APPLE_TRUSTED_ORIGIN = 'https://appleid.apple.com';
const enabledSSOProviders = parseSSOProviders(authEnv.AUTH_SSO_PROVIDERS);
const { socialProviders, genericOAuthProviders } = initBetterAuthSSOProviders();
@@ -56,7 +58,14 @@ const getTrustedOrigins = () => {
normalizeOrigin(process.env.VERCEL_URL),
].filter(Boolean) as string[];
return defaults.length > 0 ? Array.from(new Set(defaults)) : undefined;
const baseTrustedOrigins = defaults.length > 0 ? Array.from(new Set(defaults)) : undefined;
if (!enabledSSOProviders.includes('apple')) return baseTrustedOrigins;
const mergedOrigins = new Set(baseTrustedOrigins || []);
mergedOrigins.add(APPLE_TRUSTED_ORIGIN);
return Array.from(mergedOrigins);
};
export const auth = betterAuth({
@@ -64,7 +73,7 @@ export const auth = betterAuth({
accountLinking: {
allowDifferentEmails: true,
enabled: true,
trustedProviders: parseSSOProviders(authEnv.AUTH_SSO_PROVIDERS),
trustedProviders: enabledSSOProviders,
},
},
+12
View File
@@ -69,6 +69,10 @@ declare global {
AUTH_GOOGLE_ID?: string;
AUTH_GOOGLE_SECRET?: string;
AUTH_APPLE_CLIENT_ID?: string;
AUTH_APPLE_CLIENT_SECRET?: string;
AUTH_APPLE_APP_BUNDLE_IDENTIFIER?: string;
AUTH_GITHUB_ID?: string;
AUTH_GITHUB_SECRET?: string;
@@ -184,6 +188,10 @@ export const getAuthConfig = () => {
AUTH_GOOGLE_ID: z.string().optional(),
AUTH_GOOGLE_SECRET: z.string().optional(),
AUTH_APPLE_CLIENT_ID: z.string().optional(),
AUTH_APPLE_CLIENT_SECRET: z.string().optional(),
AUTH_APPLE_APP_BUNDLE_IDENTIFIER: z.string().optional(),
AUTH_GITHUB_ID: z.string().optional(),
AUTH_GITHUB_SECRET: z.string().optional(),
@@ -301,6 +309,10 @@ export const getAuthConfig = () => {
AUTH_GOOGLE_ID: process.env.AUTH_GOOGLE_ID,
AUTH_GOOGLE_SECRET: process.env.AUTH_GOOGLE_SECRET,
AUTH_APPLE_CLIENT_ID: process.env.AUTH_APPLE_CLIENT_ID,
AUTH_APPLE_CLIENT_SECRET: process.env.AUTH_APPLE_CLIENT_SECRET,
AUTH_APPLE_APP_BUNDLE_IDENTIFIER: process.env.AUTH_APPLE_APP_BUNDLE_IDENTIFIER,
AUTH_GITHUB_ID: process.env.AUTH_GITHUB_ID,
AUTH_GITHUB_SECRET: process.env.AUTH_GITHUB_SECRET,
+7 -1
View File
@@ -2,7 +2,13 @@
* Canonical IDs of Better-Auth built-in social providers.
* Keep this list in sync with provider definitions in `src/libs/better-auth/sso/providers`.
*/
export const BUILTIN_BETTER_AUTH_PROVIDERS = ['google', 'github', 'cognito', 'microsoft'] as const;
export const BUILTIN_BETTER_AUTH_PROVIDERS = [
'apple',
'google',
'github',
'cognito',
'microsoft',
] as const;
/**
* Provider alias → canonical ID mapping.
+2
View File
@@ -5,6 +5,7 @@ import { authEnv } from '@/envs/auth';
import { BUILTIN_BETTER_AUTH_PROVIDERS } from '@/libs/better-auth/constants';
import { parseSSOProviders } from '@/libs/better-auth/utils/server';
import Apple from './providers/apple';
import Auth0 from './providers/auth0';
import Authelia from './providers/authelia';
import Authentik from './providers/authentik';
@@ -23,6 +24,7 @@ import Wechat from './providers/wechat';
import Zitadel from './providers/zitadel';
const providerDefinitions = [
Apple,
Google,
Github,
Cognito,
@@ -0,0 +1,33 @@
import { authEnv } from '@/envs/auth';
import type { BuiltinProviderDefinition } from '../types';
const provider: BuiltinProviderDefinition<
{
AUTH_APPLE_APP_BUNDLE_IDENTIFIER?: string;
AUTH_APPLE_CLIENT_ID: string;
AUTH_APPLE_CLIENT_SECRET: string;
},
'apple'
> = {
build: (env) => {
return {
appBundleIdentifier: env.AUTH_APPLE_APP_BUNDLE_IDENTIFIER,
clientId: env.AUTH_APPLE_CLIENT_ID,
clientSecret: env.AUTH_APPLE_CLIENT_SECRET,
};
},
checkEnvs: () => {
return !!(authEnv.AUTH_APPLE_CLIENT_ID && authEnv.AUTH_APPLE_CLIENT_SECRET)
? {
AUTH_APPLE_APP_BUNDLE_IDENTIFIER: authEnv.AUTH_APPLE_APP_BUNDLE_IDENTIFIER,
AUTH_APPLE_CLIENT_ID: authEnv.AUTH_APPLE_CLIENT_ID,
AUTH_APPLE_CLIENT_SECRET: authEnv.AUTH_APPLE_CLIENT_SECRET,
}
: false;
},
id: 'apple',
type: 'builtin',
};
export default provider;