feat: Anmeldung mit Pflicht-2FA, Rollen und Audit-Log
Auth.js mit Zugangsdaten-Provider: E-Mail, Passwort und TOTP-Code werden in einem Formular abgefragt. Ein zweistufiger Ablauf muesste zwischen den Schritten einen Zwischenzustand halten - genau das ist die uebliche Schwachstelle, und am Handy ist ein Formular ohnehin schneller. Anmeldung: - Sperre wird VOR dem Passwortvergleich geprueft, damit ein gesperrter Zugang nicht einmal Argon2-Rechenzeit kostet. - Bei unbekannter Adresse wird gegen einen Dummy-Hash gerechnet und die Antwort auf eine Mindestdauer gestreckt. Sonst verraet die Antwortzeit, welche Adressen existieren. - Wiederherstellungscodes werden nach Gebrauch entfernt. - Veraltete Argon2-Parameter werden beim erfolgreichen Login nachgezogen. Rate-Limiting in der Datenbank statt Redis - ein Server, wenige Benutzer, kein Grund fuer eine weitere Komponente. Gezaehlt wird nach E-Mail und nach Anschluss, damit weder viele Anschluesse noch viele Adressen helfen. Zugriffsschutz (sitzung.ts): - Die Sitzung allein entscheidet nichts. Bei jedem Aufruf wird der Benutzer frisch geladen und die Sitzungsgeneration verglichen - so lassen sich alle Anmeldungen auf einen Schlag beenden. - erfordereZugang() prueft immer gegen die betreuteId, nie nur im UI. - Erneute Bestaetigung vor sensiblen Aktionen ueber ein signiertes, kurzlebiges Cookie statt ueber Serverzustand. Audit-Log: aenderungErmitteln() protokolliert nur die tatsaechlich geaenderten Felder; Passwoerter und TOTP-Geheimnisse werden ersetzt, nie gespeichert. Ein Fehler im Protokoll bricht die Fachaktion nicht ab - ausser die Aktion laeuft in einer Transaktion, dann faellt beides. CSP mit Nonce pro Anfrage in der Middleware: keine Fremdquellen, kein CDN, keine Fonts von aussen. Fachseiten werden nicht zwischengespeichert. Etappe: 1 Phase: Fundament
This commit is contained in:
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
import type { Rolle } from '@prisma/client'
|
||||
import type { DefaultSession } from 'next-auth'
|
||||
|
||||
/**
|
||||
* Erweiterung der Auth.js-Typen um die Felder, die diese Anwendung in der
|
||||
* Sitzung mitfuehrt. Ohne diese Deklaration waeren session.user.rolle und
|
||||
* Verwandte in TypeScript unbekannt.
|
||||
*/
|
||||
|
||||
declare module 'next-auth' {
|
||||
interface User {
|
||||
rolle: Rolle
|
||||
sitzungsGeneration: number
|
||||
zweiterFaktorAktiv: boolean
|
||||
}
|
||||
|
||||
interface Session {
|
||||
user: {
|
||||
id: string
|
||||
rolle: Rolle
|
||||
sitzungsGeneration: number
|
||||
zweiterFaktorAktiv: boolean
|
||||
/** Unix-Sekunden der letzten vollstaendigen Anmeldung. */
|
||||
angemeldetSeit: number
|
||||
} & DefaultSession['user']
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'next-auth/jwt' {
|
||||
interface JWT {
|
||||
rolle?: Rolle
|
||||
sitzungsGeneration?: number
|
||||
zweiterFaktorAktiv?: boolean
|
||||
angemeldetSeit?: number
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
Reference in New Issue
Block a user