feat(ui): Microsoft-Anmeldung nur wenn eingerichtet, in der Anmelde-Spalte

Der Knopf stand unter beiden Spalten (Anmelden und Konto erstellen),
obwohl er zur Anmeldung gehoert, und erschien auch ohne eingerichtete
Entra-Konfiguration - der Klick endete dann in der Meldung "SSO ist noch
nicht konfiguriert". Jetzt steht er unter dem Anmeldeformular und nur,
wenn isEntraConfigured() zutrifft. Die serverseitige Pruefung in der
Login-Route bleibt als zweite Absicherung.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-09-26 02:13:19 +02:00
1 parent 774bc9cf00
commit 0fb176add8
1 file changed
+27 -29
+27 -29
View File
@@ -8,6 +8,7 @@ import { ConfirmForm } from "@/components/confirm-form";
import { getLocale } from "@/i18n/locale"; import { getLocale } from "@/i18n/locale";
import { getDictionary } from "@/i18n/get-dictionary"; import { getDictionary } from "@/i18n/get-dictionary";
import { getCurrentCustomer } from "@/lib/auth"; import { getCurrentCustomer } from "@/lib/auth";
import { isEntraConfigured } from "@/lib/entra";
import { prisma } from "@/lib/prisma"; import { prisma } from "@/lib/prisma";
import { import {
registerAction, registerAction,
@@ -32,7 +33,8 @@ export default async function KontoPage() {
<Container className="max-w-3xl"> <Container className="max-w-3xl">
<SectionHeading title={t.account.loginRegisterTitle} /> <SectionHeading title={t.account.loginRegisterTitle} />
<div className="mt-10 grid md:grid-cols-2 md:divide-x md:divide-ink/10 gap-12 md:gap-0"> <div className="mt-10 grid md:grid-cols-2 md:divide-x md:divide-ink/10 gap-12 md:gap-0">
<form action={loginAction} className="space-y-4 md:pr-12"> <div className="md:pr-12">
<form action={loginAction} className="space-y-4">
<h2 className="text-3xl text-forest">{t.account.login}</h2> <h2 className="text-3xl text-forest">{t.account.login}</h2>
<Field name="email" label={t.account.emailLabel} type="email" required autoComplete="email" /> <Field name="email" label={t.account.emailLabel} type="email" required autoComplete="email" />
<PasswordField name="password" label={t.account.passwordLabel} required autoComplete="current-password" /> <PasswordField name="password" label={t.account.passwordLabel} required autoComplete="current-password" />
@@ -53,6 +55,30 @@ export default async function KontoPage() {
</Link> </Link>
</div> </div>
</form> </form>
{/* Microsoft-Anmeldung nur, wenn sie eingerichtet ist (ENTRA_*,
siehe .env.example) — ein Knopf, der nur "SSO ist noch nicht
konfiguriert" meldet, ist fuer Kundschaft schlechter als keiner.
Sie gehoert zur Anmeldung, steht deshalb in dieser Spalte.
Bewusst ein einfaches <a> statt next/link: der Klick muss eine
echte Top-Level-Navigation ausloesen, die dem Redirect bis zu
login.microsoftonline.com folgt; ein clientseitiger fetch()
wuerde von der connect-src-CSP in proxy.ts blockiert. */}
{isEntraConfigured() ? (
<>
<div className="mt-8 flex items-center gap-4 text-xs text-ink/70">
<span className="h-px flex-1 bg-ink/10" />
{t.account.ssoDivider}
<span className="h-px flex-1 bg-ink/10" />
</div>
<a
href="/api/auth/entra/login"
className="mt-6 inline-flex items-center justify-center gap-2 px-7 py-3 text-sm tracking-wide-caps transition-[color,background-color,border-color,transform] duration-300 active:scale-[0.97] bg-transparent text-forest border border-forest hover:bg-forest hover:text-cream"
>
{t.account.ssoButton}
</a>
</>
) : null}
</div>
<form action={registerAction} className="space-y-4 md:pl-12"> <form action={registerAction} className="space-y-4 md:pl-12">
<h2 className="text-3xl text-forest">{t.account.register}</h2> <h2 className="text-3xl text-forest">{t.account.register}</h2>
@@ -80,34 +106,6 @@ export default async function KontoPage() {
</form> </form>
</div> </div>
<div className="mt-10 flex items-center gap-4 text-xs text-ink/70">
<span className="h-px flex-1 bg-ink/10" />
{t.account.ssoDivider}
<span className="h-px flex-1 bg-ink/10" />
</div>
<div className="mt-6">
{/*
Bewusst ein einfaches <a> statt LinkButton/next/link: der Klick
muss eine ECHTE Browser-Top-Level-Navigation ausloesen, die dem
302-Redirect dieser Route bis zu login.microsoftonline.com
folgt. Next.js' <Link> navigiert clientseitig per fetch() —
dieser Cross-Origin-Redirect-Sprung wuerde dann von der
connect-src-CSP in proxy.ts blockiert (die nur "self" u.ae.
erlaubt), waehrend eine echte Top-Level-Navigation von CSP
connect-src gar nicht erst betroffen ist.
Bewusst immer sichtbar, auch ohne konfiguriertes SSO (siehe
.env.example, ENTRA_*) — der Link fuehrt in dem Fall zu einer
klaren Fehlermeldung auf dieser Seite statt eines defekten
Buttons (src/app/api/auth/entra/login/route.ts prueft die
Konfiguration server-seitig, bevor irgendetwas passiert).
*/}
<a
href="/api/auth/entra/login"
className="inline-flex items-center justify-center gap-2 px-7 py-3 text-sm tracking-wide-caps transition-[color,background-color,border-color,transform] duration-300 active:scale-[0.97] bg-transparent text-forest border border-forest hover:bg-forest hover:text-cream"
>
{t.account.ssoButton}
</a>
</div>
</Container> </Container>
</div> </div>
); );