From c7a06a4b62536994c9271067eab6d6a6f83cf2c2 Mon Sep 17 00:00:00 2001 From: YuTengjing Date: Mon, 2 Feb 2026 11:29:35 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20use=20oauth2.link=20for?= =?UTF-8?q?=20generic=20OIDC=20provider=20account=20linking=20(#12024)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../features/SSOProvidersList/index.tsx | 24 +++++++++++++++---- src/libs/better-auth/auth-client.ts | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/app/[variants]/(main)/settings/profile/features/SSOProvidersList/index.tsx b/src/app/[variants]/(main)/settings/profile/features/SSOProvidersList/index.tsx index fdb46f47cb..eff3d93e4a 100644 --- a/src/app/[variants]/(main)/settings/profile/features/SSOProvidersList/index.tsx +++ b/src/app/[variants]/(main)/settings/profile/features/SSOProvidersList/index.tsx @@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'; import { modal, notification } from '@/components/AntdStaticMethods'; import AuthIcons from '@/components/AuthIcons'; +import { isBuiltinProvider, normalizeProviderId } from '@/libs/better-auth/utils/client'; import { useServerConfigStore } from '@/store/serverConfig'; import { serverConfigSelectors } from '@/store/serverConfig/selectors'; import { useUserStore } from '@/store/user'; @@ -33,8 +34,11 @@ export const SSOProvidersList = memo(() => { }, [providers]); // Get available providers for linking (filter out already linked) + // Normalize provider IDs when comparing to handle aliases (e.g. microsoft-entra-id → microsoft) const availableProviders = useMemo(() => { - return (oAuthSSOProviders || []).filter((provider) => !linkedProviderIds.has(provider)); + return (oAuthSSOProviders || []).filter( + (provider) => !linkedProviderIds.has(normalizeProviderId(provider)), + ); }, [oAuthSSOProviders, linkedProviderIds]); const handleUnlinkSSO = async (provider: string) => { @@ -63,14 +67,24 @@ export const SSOProvidersList = memo(() => { }; const handleLinkSSO = async (provider: string) => { - if (enableAuthActions) { - // Use better-auth native linkSocial API - const { linkSocial } = await import('@/libs/better-auth/auth-client'); + if (!enableAuthActions) return; + + const normalizedProvider = normalizeProviderId(provider); + const { linkSocial, oauth2 } = await import('@/libs/better-auth/auth-client'); + + if (isBuiltinProvider(normalizedProvider)) { + // Use better-auth native linkSocial API for built-in providers await linkSocial({ callbackURL: '/profile', - provider: provider as any, + provider: normalizedProvider as any, }); + return; } + + await oauth2.link({ + callbackURL: '/profile', + providerId: normalizedProvider, + }); }; // Dropdown menu items for linking new providers diff --git a/src/libs/better-auth/auth-client.ts b/src/libs/better-auth/auth-client.ts index dcea736c4e..a72eb078e7 100644 --- a/src/libs/better-auth/auth-client.ts +++ b/src/libs/better-auth/auth-client.ts @@ -10,6 +10,7 @@ import type { auth } from '@/auth'; export const { linkSocial, + oauth2, accountInfo, listAccounts, requestPasswordReset,