fix: SSO umging die Admin-2FA; perf: Dashboard und fehlende Indizes
SICHERHEIT — "Mit Microsoft anmelden" uebersprang die eigene 2FA auch bei
Admin-Konten.
requireAdmin (admin/actions/_shared.ts) laesst eine Admin-Aktion nur zu,
wenn am Konto twoFactorEnabled steht. Das Flag soll zusichern, dass hinter
jeder Rueckerstattung und jedem Blick in die Kundendaten tatsaechlich ein
zweiter Faktor stand. Der SSO-Rueckweg legte aber direkt eine
vollstaendige Session an und lieferte damit ein Flag, das "geprueft"
behauptet, obwohl in diesem Anmeldevorgang nichts geprueft wurde — die
Zusicherung hing allein an einer Annahme ueber die MFA-Richtlinie des
Entra-Mandanten, die dieser Code nicht nachpruefen kann.
Ein ADMIN mit aktivierter 2FA laeuft jetzt auch per SSO durch denselben
TOTP-Schritt wie beim Passwort-Login. Ausgesperrt wird dabei niemand:
twoFactorEnabled heisst, dass der zweite Faktor eingerichtet ist. Fuer
KUNDENkonten bleibt der bequeme Weg wie dokumentiert bestehen.
PERFORMANCE — zwei unbegrenzte Abfragen auf dem Admin-Dashboard.
Die Startseite des Admin-Bereichs lud bei jedem Aufruf
1. JEDE Bestellposition, die es je gab, samt Produkt-Join — um daraus
fuenf Zeilen "Top-Produkte" zu rechnen, und
2. JEDE Bestellung, die es je gab — um daraus eine einzige Zahl
("Stammkunden") zu machen. Die Begruendung im Code lautete, Prisma
koenne kein HAVING. Es kann.
Beides erledigt jetzt die Datenbank per groupBy. Aus "waechst mit jedem
Verkauf" wird "eine Zeile je verkauftem Produkt" bzw. "eine Zeile je
Stammkundschaft". Die Kategorie haengt am Produkt und laesst sich nicht
mitgruppieren; sie kommt aus einer kurzen Nachfrage ueber die
Primaerschluessel der tatsaechlich verkauften Produkte.
PERFORMANCE — fehlende Indizes auf order_items.
PostgreSQL legt fuer Fremdschluessel-Spalten keinen Index an (anders als
MySQL/InnoDB). Auf der am schnellsten wachsenden Tabelle des Shops fehlten
dadurch zwei:
- productId: hasCustomerPurchased (lib/reviews.ts) prueft den
"verifizierten Kauf" bei JEDEM Aufruf einer Produktseite durch eine
angemeldete Kundschaft — bisher als vollstaendiger Tabellenscan.
- batchId: das Loeschen einer Charge prueft ueber onDelete: Restrict
gegen dieselbe Tabelle.
Migration 20260919010000_order_item_fk_indexes.
tsc: 0 Fehler. vitest: 328/328 gruen. eslint: 0 Warnungen.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
3e81896194
commit
2bbb38c31a
4 files changed
+124
-36
No files matched your search
@@ -2,7 +2,14 @@ import { randomBytes } from "node:crypto";
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { getBaseUrl } from "@/lib/url";
|
||||
import { createSession, hashPassword, getEntraOAuthCookie, clearEntraOAuthCookie } from "@/lib/auth";
|
||||
import {
|
||||
createSession,
|
||||
hashPassword,
|
||||
getEntraOAuthCookie,
|
||||
clearEntraOAuthCookie,
|
||||
setTwoFactorChallengeCookie,
|
||||
} from "@/lib/auth";
|
||||
import { signTwoFactorChallenge } from "@/lib/session";
|
||||
import {
|
||||
isEntraConfigured,
|
||||
exchangeEntraAuthorizationCode,
|
||||
@@ -135,11 +142,28 @@ export async function GET(request: Request) {
|
||||
});
|
||||
}
|
||||
|
||||
// Anmeldung per SSO wird bewusst als vollwertig authentifiziert behandelt
|
||||
// und ueberspringt die App-eigene 2FA-Abfrage (falls fuer das Konto
|
||||
// aktiviert): Microsoft ist hier die pruefende Authentifizierungsstelle,
|
||||
// deren eigene Absicherung (bis hin zu Microsofts eigener MFA) die Rolle
|
||||
// unseres TOTP-Schritts uebernimmt.
|
||||
// Fuer KUNDENkonten wird die Anmeldung per SSO bewusst als vollwertig
|
||||
// authentifiziert behandelt und ueberspringt die App-eigene 2FA-Abfrage
|
||||
// (falls fuer das Konto aktiviert): Microsoft ist hier die pruefende
|
||||
// Authentifizierungsstelle, deren eigene Absicherung (bis hin zu Microsofts
|
||||
// eigener MFA) die Rolle unseres TOTP-Schritts uebernimmt.
|
||||
//
|
||||
// Fuer ADMINkonten gilt das NICHT. requireAdmin (admin/actions/_shared.ts)
|
||||
// laesst eine Admin-Aktion nur zu, wenn am Konto twoFactorEnabled steht —
|
||||
// dieses Flag soll zusichern, dass hinter jeder Rueckerstattung und jedem
|
||||
// Blick in die Kundendaten tatsaechlich ein zweiter Faktor stand. Ueber
|
||||
// diesen Weg war das nur noch eine Annahme ueber die MFA-Richtlinie des
|
||||
// Entra-Mandanten, die dieser Code nicht nachpruefen kann: ein Flag, das
|
||||
// "geprueft" behauptet, obwohl hier nichts geprueft wurde. Deshalb laeuft
|
||||
// ein Admin denselben TOTP-Schritt wie beim Passwort-Login. Ausgesperrt
|
||||
// werden kann dabei niemand — twoFactorEnabled heisst, dass der zweite
|
||||
// Faktor bereits eingerichtet ist.
|
||||
if (customer.role === "ADMIN" && customer.twoFactorEnabled) {
|
||||
const challengeToken = await signTwoFactorChallenge(customer.id);
|
||||
await setTwoFactorChallengeCookie(challengeToken);
|
||||
return NextResponse.redirect(new URL("/konto/zwei-faktor-code", baseUrl));
|
||||
}
|
||||
|
||||
await createSession(customer.id, customer.role, customer.sessionVersion);
|
||||
return NextResponse.redirect(new URL("/konto", baseUrl));
|
||||
}
|
||||
Reference in new issue
Block a user