import { EntraSignInButton } from "@/components/auth/EntraSignInButton"; import { logout, signInWithEntra } from "@/actions/auth"; // The query string is attacker-controlled, so the login page renders a message // looked up by code rather than whatever text ?error= carries. Reflecting the // raw parameter let anyone put arbitrary wording ("Ihr Konto wurde gesperrt, // rufen Sie …") on the real, correctly-branded sign-in screen. Dasselbe gilt // für die Fehlertexte, die Entra im Rückweg mitschickt. const ERROR_MESSAGES = { no_hr_access: { title: "Kein HR-Zugriff", body: "Ihr Firmenkonto ist bekannt, aber nicht für die Personalverwaltung freigeschaltet. Bitte wenden Sie sich an eine:n bestehende:n HR-Benutzer:in.", }, sso_failed: { title: "Anmeldung fehlgeschlagen", body: "Die Anmeldung über das Firmenkonto konnte nicht abgeschlossen werden. Bitte versuchen Sie es erneut.", }, } as const; type ErrorCode = keyof typeof ERROR_MESSAGES; type LoginPageProps = { searchParams: Promise<{ error?: string }>; }; export default async function LoginPage({ searchParams }: LoginPageProps) { const params = await searchParams; // Ein unbekannter Code wird nicht verschluckt, sondern auf die allgemeine // Meldung abgebildet: Auth.js schickt bei einem Fehlschlag seine eigenen // Codes („Configuration", „AccessDenied", „OAuthCallbackError" …), und ohne // diese Abbildung stünde man vor einer Anmeldeseite, die so tut, als wäre // nichts gewesen. Angezeigt wird trotzdem nur eigener Text — der Parameter // selbst kommt nie auf die Seite. const code = params.error ? Object.hasOwn(ERROR_MESSAGES, params.error) ? (params.error as ErrorCode) : "sso_failed" : null; const error = code ? ERROR_MESSAGES[code] : null; return ( // dvh statt vh: auf iOS zählt vh die Adressleiste mit, wodurch die Karte // im ersten Moment unter dem Faltenrand sitzt.

Anmelden

Der Zugang läuft über Ihr Firmenkonto. Ein eigenes Passwort gibt es nicht.

{error && (

{error.title}

{error.body}

{code === "no_hr_access" && (
)}
)}

Die Anmeldung allein erteilt keinen Zugriff. HR-Rechte vergibt die Personalabteilung — bis dahin bleiben alle Personaldaten verschlossen.

); } function BrandPanel() { return ( ); } function Wordmark({ className = "" }: { className?: string }) { return (
{/* Vier Quadrate wie ein Organigramm-Ausschnitt: eine Wurzel, darunter drei Einheiten. */} Alpenwerk HR
); }