Files
work-club-manager/frontend/src/components/auth-guard.tsx
WorkClub Automation 1322def2ea
Some checks failed
CI Pipeline / Backend Build & Test (pull_request) Successful in 49s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Failing after 26s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 4s
fix(auth): resolve Keycloak OIDC issuer mismatch and API proxy routing
- Bypass NextAuth OIDC discovery with explicit token/userinfo endpoints using internal Docker DNS, avoiding 'issuer string did not match' errors.
- Fix next.config.ts API route interception that incorrectly forwarded NextAuth routes to backend by using 'fallback' rewrites.
- Add 'Use different credentials' button to login page and AuthGuard for clearing stale sessions.
2026-03-09 14:21:03 +01:00

77 lines
2.3 KiB
TypeScript

'use client';
import { useSession, signOut } from 'next-auth/react';
import { useRouter } from 'next/navigation';
import { ReactNode, useEffect } from 'react';
import { useTenant } from '../contexts/tenant-context';
export function AuthGuard({ children }: { children: ReactNode }) {
const { status } = useSession();
const { activeClubId, clubs, setActiveClub, clubsLoading } = useTenant();
const router = useRouter();
useEffect(() => {
if (status === 'unauthenticated') {
router.push('/login');
}
}, [status, router]);
useEffect(() => {
if (status === 'authenticated' && clubs.length > 0) {
if (clubs.length === 1 && !activeClubId) {
setActiveClub(clubs[0].id);
} else if (clubs.length > 1 && !activeClubId) {
router.push('/select-club');
}
}
}, [status, clubs, activeClubId, router, setActiveClub]);
if (status === 'loading') {
return (
<div className="flex items-center justify-center min-h-screen">
<p>Loading...</p>
</div>
);
}
if (status === 'unauthenticated') {
return null;
}
if (status === 'authenticated' && clubsLoading) {
return (
<div className="flex items-center justify-center min-h-screen">
<p>Loading...</p>
</div>
);
}
if (clubs.length === 0 && status === 'authenticated') {
const handleSwitchAccount = () => {
const keycloakLogoutUrl = `${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080/realms/workclub'}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(window.location.origin + '/login')}`;
signOut({ redirect: false }).then(() => {
window.location.href = keycloakLogoutUrl;
});
};
return (
<div className="flex flex-col items-center justify-center min-h-screen gap-4">
<h2 className="text-2xl font-bold">No Clubs Found</h2>
<p>Contact admin to get access to a club</p>
<button
onClick={handleSwitchAccount}
className="mt-4 px-4 py-2 bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-md border border-gray-300 transition-colors"
>
Use different credentials
</button>
</div>
);
}
if (clubs.length > 1 && !activeClubId) {
return null;
}
return <>{children}</>;
}