This commit is contained in:
alma 2026-01-18 14:31:10 +01:00
parent 6414e85a78
commit ba59d266e3
8 changed files with 81 additions and 59 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
app/.DS_Store vendored

Binary file not shown.

View File

@ -84,7 +84,7 @@ export default function SignIn() {
return ( return (
<div <div
className="min-h-screen flex items-center justify-center" className="min-h-screen flex flex-col"
style={{ style={{
backgroundImage: "url('/SignIn.jpg')", backgroundImage: "url('/SignIn.jpg')",
backgroundSize: 'cover', backgroundSize: 'cover',
@ -92,45 +92,48 @@ export default function SignIn() {
backgroundRepeat: 'no-repeat' backgroundRepeat: 'no-repeat'
}} }}
> >
<div className="w-full max-w-md space-y-8 bg-white/90 backdrop-blur-sm p-8 rounded-xl shadow-xl"> {/* Header with login button in top right */}
<div> <header className="w-full flex justify-end p-6">
<h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900"> {status === "unauthenticated" && !isLoggingIn && (
{isLogoutRedirect <button
? "Vous avez été déconnecté avec succès. Veuillez vous reconnecter." onClick={() => {
: initializationStatus === "initializing" console.log('[SignIn] Login button clicked');
? "Initialisation de votre espace..." setIsLoggingIn(true);
: initializationStatus === "success" signIn("keycloak", { callbackUrl: "/" });
? "Initialisation réussie, redirection..." }}
: initializationStatus === "failed" className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-semibold shadow-lg hover:shadow-xl"
? "Échec de l'initialisation. Veuillez réessayer." >
: isLoggingIn Se connecter
? "Connexion en cours..." </button>
: status === "loading" )}
? "Chargement..." </header>
: "Bienvenue"}
</h2> {/* Main content centered */}
<div className="flex-1 flex items-center justify-center">
{/* Show login button when user is not authenticated and not currently logging in */} <div className="w-full max-w-md space-y-8 bg-white/90 backdrop-blur-sm p-8 rounded-xl shadow-xl">
{status === "unauthenticated" && !isLoggingIn && ( <div>
<div className="mt-8 text-center"> <h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900">
<button {isLogoutRedirect
onClick={() => { ? "Vous avez été déconnecté avec succès. Veuillez vous reconnecter."
console.log('[SignIn] Login button clicked'); : initializationStatus === "initializing"
setIsLoggingIn(true); ? "Initialisation de votre espace..."
signIn("keycloak", { callbackUrl: "/" }); : initializationStatus === "success"
}} ? "Initialisation réussie, redirection..."
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-semibold text-lg shadow-lg hover:shadow-xl" : initializationStatus === "failed"
> ? "Échec de l'initialisation. Veuillez réessayer."
Se connecter : isLoggingIn
</button> ? "Connexion en cours..."
</div> : status === "loading"
)} ? "Chargement..."
: ""}
{(initializationStatus === "initializing" || isLoggingIn || status === "loading") && ( </h2>
<div className="flex justify-center mt-4">
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div> {(initializationStatus === "initializing" || isLoggingIn || status === "loading") && (
</div> <div className="flex justify-center mt-4">
)} <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
</div>
)}
</div>
</div> </div>
</div> </div>
</div> </div>

BIN
components/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -66,16 +66,14 @@ export function SignOutHandler() {
}); });
// If we have Keycloak ID token and issuer, call Keycloak logout // If we have Keycloak ID token and issuer, call Keycloak logout
// Note: We don't use post_logout_redirect_uri to avoid "Invalid redirect uri" error
// Instead, we'll redirect manually after logout
if (keycloakIssuer && idToken) { if (keycloakIssuer && idToken) {
const keycloakLogoutUrl = new URL( const keycloakLogoutUrl = new URL(
`${keycloakIssuer}/protocol/openid-connect/logout` `${keycloakIssuer}/protocol/openid-connect/logout`
); );
// Add required parameters - include logout=true in redirect URI // Add id_token_hint to identify the session
keycloakLogoutUrl.searchParams.append(
'post_logout_redirect_uri',
window.location.origin + '/signin?logout=true'
);
keycloakLogoutUrl.searchParams.append( keycloakLogoutUrl.searchParams.append(
'id_token_hint', 'id_token_hint',
idToken idToken
@ -86,8 +84,17 @@ export function SignOutHandler() {
'LOGOUT' 'LOGOUT'
); );
// Immediate redirect to Keycloak logout (prevents widget rendering) // Use a hidden iframe to logout from Keycloak without redirect
window.location.replace(keycloakLogoutUrl.toString()); // This avoids the "Invalid redirect uri" error
const logoutIframe = document.createElement('iframe');
logoutIframe.style.display = 'none';
logoutIframe.src = keycloakLogoutUrl.toString();
document.body.appendChild(logoutIframe);
// Wait a bit for logout to process, then redirect
setTimeout(() => {
window.location.replace('/signin?logout=true');
}, 500);
} else { } else {
// Fallback: just redirect to signin if we don't have Keycloak info // Fallback: just redirect to signin if we don't have Keycloak info
window.location.replace('/signin?logout=true'); window.location.replace('/signin?logout=true');

View File

@ -169,10 +169,6 @@ export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: Layou
const keycloakLogoutUrl = new URL( const keycloakLogoutUrl = new URL(
`${keycloakIssuer}/protocol/openid-connect/logout` `${keycloakIssuer}/protocol/openid-connect/logout`
); );
keycloakLogoutUrl.searchParams.append(
'post_logout_redirect_uri',
window.location.origin + '/signin?logout=true'
);
keycloakLogoutUrl.searchParams.append( keycloakLogoutUrl.searchParams.append(
'id_token_hint', 'id_token_hint',
idToken idToken
@ -182,7 +178,18 @@ export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: Layou
'kc_action', 'kc_action',
'LOGOUT' 'LOGOUT'
); );
window.location.replace(keycloakLogoutUrl.toString());
// Use a hidden iframe to logout from Keycloak without redirect
// This avoids the "Invalid redirect uri" error
const logoutIframe = document.createElement('iframe');
logoutIframe.style.display = 'none';
logoutIframe.src = keycloakLogoutUrl.toString();
document.body.appendChild(logoutIframe);
// Wait a bit for logout to process, then redirect
setTimeout(() => {
window.location.replace('/signin?logout=true');
}, 500);
} else { } else {
// Fallback: redirect to signin // Fallback: redirect to signin
window.location.replace('/signin?logout=true'); window.location.replace('/signin?logout=true');

View File

@ -406,11 +406,7 @@ export function MainNav() {
`${keycloakIssuer}/protocol/openid-connect/logout` `${keycloakIssuer}/protocol/openid-connect/logout`
); );
// Add required parameters - include logout=true in redirect URI // Add id_token_hint to identify the session
keycloakLogoutUrl.searchParams.append(
'post_logout_redirect_uri',
window.location.origin + '/signin?logout=true'
);
keycloakLogoutUrl.searchParams.append( keycloakLogoutUrl.searchParams.append(
'id_token_hint', 'id_token_hint',
idToken idToken
@ -421,8 +417,17 @@ export function MainNav() {
'LOGOUT' 'LOGOUT'
); );
// Immediate redirect to Keycloak logout (prevents widget rendering) // Use a hidden iframe to logout from Keycloak without redirect
window.location.replace(keycloakLogoutUrl.toString()); // This avoids the "Invalid redirect uri" error
const logoutIframe = document.createElement('iframe');
logoutIframe.style.display = 'none';
logoutIframe.src = keycloakLogoutUrl.toString();
document.body.appendChild(logoutIframe);
// Wait a bit for logout to process, then redirect
setTimeout(() => {
window.location.replace('/signin?logout=true');
}, 500);
} else { } else {
// Fallback: just redirect to signin if we don't have Keycloak info // Fallback: just redirect to signin if we don't have Keycloak info
window.location.replace('/signin?logout=true'); window.location.replace('/signin?logout=true');

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 KiB

After

Width:  |  Height:  |  Size: 493 KiB