SSO login fix (#5167)

Fixes bug where SSO login with custom providers caused an
`InvalidClientRegistrationIdException: Invalid Client Registration with
Id: oidc` errors.

  Root Cause:
- Backend: Redirect URI was hardcoded to `/login/oauth2/code/oidc`
regardless of provider registration ID
- Frontend: Unknown providers were mapped back to 'oidc' instead of
using actual provider ID

Closes #5141

---------

Co-authored-by: Anthony Stirling <[email protected]>
Co-authored-by: Keon Chen <[email protected]>
This commit is contained in:
Dario Ghunney Ware
2025-12-05 23:19:41 +00:00
committed by GitHub
co-authored by Anthony Stirling Keon Chen
parent 9fd8fd89ed
commit 82dbcfbb9b
12 changed files with 961 additions and 55 deletions
+7 -14
View File
@@ -10,6 +10,7 @@ import AuthLayout from '@app/routes/authShared/AuthLayout';
import { useBackendProbe } from '@app/hooks/useBackendProbe';
import apiClient from '@app/services/apiClient';
import { BASE_PATH } from '@app/constants/app';
import { type OAuthProvider } from '@app/auth/oauthTypes';
// Import login components
import LoginHeader from '@app/routes/login/LoginHeader';
@@ -31,7 +32,7 @@ export default function Login() {
const [showEmailForm, setShowEmailForm] = useState(false);
const [email, setEmail] = useState(() => searchParams.get('email') ?? '');
const [password, setPassword] = useState('');
const [enabledProviders, setEnabledProviders] = useState<string[]>([]);
const [enabledProviders, setEnabledProviders] = useState<OAuthProvider[]>([]);
const [hasSSOProviders, setHasSSOProviders] = useState(false);
const [_enableLogin, setEnableLogin] = useState<boolean | null>(null);
const backendProbe = useBackendProbe();
@@ -226,25 +227,17 @@ export default function Login() {
);
}
// Known OAuth providers that have dedicated backend support
const KNOWN_OAUTH_PROVIDERS = ['github', 'google', 'apple', 'azure', 'keycloak', 'oidc'] as const;
type KnownOAuthProvider = typeof KNOWN_OAUTH_PROVIDERS[number];
const signInWithProvider = async (provider: string) => {
const signInWithProvider = async (provider: OAuthProvider) => {
try {
setIsSigningIn(true);
setError(null);
// Map unknown providers to 'oidc' for the backend redirect
const backendProvider: KnownOAuthProvider = KNOWN_OAUTH_PROVIDERS.includes(provider as KnownOAuthProvider)
? (provider as KnownOAuthProvider)
: 'oidc';
console.log(`[Login] Signing in with provider: ${provider}`);
console.log(`[Login] Signing in with ${provider} (backend: ${backendProvider})`);
// Redirect to Spring OAuth2 endpoint
// Redirect to Spring OAuth2 endpoint using the actual provider ID from backend
// The backend returns the correct registration ID (e.g., 'authentik', 'oidc', 'keycloak')
const { error } = await springAuth.signInWithOAuth({
provider: backendProvider,
provider: provider,
options: { redirectTo: `${BASE_PATH}/auth/callback` }
});