fix: auto-redirect to Keycloak login, skip intermediate screen
Since tOS uses Keycloak as sole auth provider, the intermediate login page with the manual "Mit Keycloak anmelden" button was unnecessary. Now unauthenticated users are redirected directly to Keycloak. The error UI with retry button is preserved for failed auth attempts (expired session, unauthorized). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { signIn, useSession } from 'next-auth/react';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Loader2, KeyRound } from 'lucide-react';
|
||||
|
||||
@@ -16,7 +16,7 @@ interface LoginPageProps {
|
||||
|
||||
/**
|
||||
* Login page component
|
||||
* Handles authentication via Keycloak
|
||||
* Automatically redirects to Keycloak. Only shows UI on auth errors.
|
||||
*/
|
||||
export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
const { status } = useSession();
|
||||
@@ -24,6 +24,7 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
const searchParams = useSearchParams();
|
||||
const t = useTranslations('auth');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const autoSignInTriggered = useRef(false);
|
||||
|
||||
const callbackUrl = searchParams.get('callbackUrl') || `/${locale}/dashboard`;
|
||||
const error = searchParams.get('error');
|
||||
@@ -35,6 +36,14 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
}
|
||||
}, [status, router, callbackUrl]);
|
||||
|
||||
// Auto-redirect to Keycloak if no error
|
||||
useEffect(() => {
|
||||
if (status === 'unauthenticated' && !error && !autoSignInTriggered.current) {
|
||||
autoSignInTriggered.current = true;
|
||||
signIn('keycloak', { callbackUrl });
|
||||
}
|
||||
}, [status, error, callbackUrl]);
|
||||
|
||||
const handleLogin = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
@@ -44,8 +53,8 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// Show loading state while checking session
|
||||
if (status === 'loading') {
|
||||
// Show loading spinner during auto-redirect or session check
|
||||
if (!error) {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-background">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||
@@ -53,6 +62,7 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
);
|
||||
}
|
||||
|
||||
// Only show full UI when there's an error (so user can retry)
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-gradient-to-br from-background to-muted p-4">
|
||||
<motion.div
|
||||
@@ -62,7 +72,6 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
>
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="space-y-4 text-center">
|
||||
{/* Logo */}
|
||||
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-2xl bg-primary text-primary-foreground">
|
||||
<span className="text-3xl font-bold">t</span>
|
||||
<span className="text-3xl font-light">OS</span>
|
||||
@@ -73,8 +82,6 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* Error message */}
|
||||
{error && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, height: 0 }}
|
||||
animate={{ opacity: 1, height: 'auto' }}
|
||||
@@ -82,9 +89,7 @@ export default function LoginPage({ params: { locale } }: LoginPageProps) {
|
||||
>
|
||||
{error === 'SessionRequired' ? t('sessionExpired') : t('unauthorized')}
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
{/* Login button */}
|
||||
<Button
|
||||
onClick={handleLogin}
|
||||
disabled={isLoading}
|
||||
|
||||
Reference in New Issue
Block a user