diff --git a/superset-frontend/src/pages/Login/index.tsx b/superset-frontend/src/pages/Login/index.tsx index 9bb10dfd1d0..67552a316de 100644 --- a/superset-frontend/src/pages/Login/index.tsx +++ b/superset-frontend/src/pages/Login/index.tsx @@ -27,7 +27,7 @@ import { Typography, Icons, } from '@superset-ui/core/components'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; import { capitalize } from 'lodash/fp'; import { addDangerToast } from 'src/components/MessageToasts/actions'; import { useDispatch } from 'react-redux'; @@ -82,6 +82,26 @@ export default function Login() { const dispatch = useDispatch(); const bootstrapData = getBootstrapData(); + const nextUrl = useMemo(() => { + try { + const params = new URLSearchParams(window.location.search); + return params.get('next') || ''; + } catch (_error) { + return ''; + } + }, []); + + const loginEndpoint = useMemo( + () => (nextUrl ? `/login/?next=${encodeURIComponent(nextUrl)}` : '/login/'), + [nextUrl], + ); + + const buildProviderLoginUrl = (providerName: string) => { + const base = `/login/${providerName}`; + return nextUrl + ? `${base}${base.includes('?') ? '&' : '?'}next=${encodeURIComponent(nextUrl)}` + : base; + }; const authType: AuthType = bootstrapData.common.conf.AUTH_TYPE; const providers: Provider[] = bootstrapData.common.conf.AUTH_PROVIDERS; @@ -109,7 +129,7 @@ export default function Login() { sessionStorage.setItem('login_attempted', 'true'); // Use standard form submission for Flask-AppBuilder compatibility - SupersetClient.postForm('/login/', values, ''); + SupersetClient.postForm(loginEndpoint, values, ''); }; const getAuthIconElement = ( @@ -146,7 +166,7 @@ export default function Login() { {providers.map((provider: OIDProvider) => ( >