Wie score Schulen voneinander trennt, Personen anmeldet und Noten schützt.
Mandanten
Eine Einrichtung – meist eine Schule – ist ein Mandant. Darüber liegen Verwaltungsebenen wie
Träger oder Land. Jede Fachtabelle trägt die Einrichtung, zu der eine Zeile gehört.
Eine Mitgliedschaft verbindet Person, Einrichtung, Rolle und Zeitraum. Eine Lehrkraft an zwei
Schulen hat zwei Mitgliedschaften und sieht beide Schulen, aber jede nur in ihrer Rolle.
Row-Level Security
Die Trennung liegt in PostgreSQL, nicht nur in der Anwendung:
score-api setzt zu Beginn jeder Transaktion Person und erlaubte Einrichtungen. Der Kontext
gilt nur für diese Transaktion und kommt aus den heute gültigen Mitgliedschaften, nie aus der
Anfrage.
Die Anwendung arbeitet unter einer eigenen Datenbankrolle ohne BYPASSRLS und ohne
Eigentümerrechte. Migrationen laufen getrennt davon.
Policies sind mit FORCE ROW LEVEL SECURITY aktiv. Ohne Kontext liefert keine Fachtabelle
eine Zeile.
Schreibrechte prüft ebenfalls die Datenbank: Noten schreibt nur, wer den Kurs unterrichtet;
Entsperren darf nur die Schulleitung. Verstöße werden zu HTTP 403.
Tests legen je Fall eine eigene Datenbank an und prüfen als Anwendungsrolle unter anderem: keine
Sonderrechte, ohne Kontext keine Zeilen, Lehrkraft an zwei Schulen, Schreiben in eine fremde
Einrichtung scheitert, eine Schülerin sieht nur ihre eigenen Daten.
Anmeldung
Fokus
Anmeldung: OIDC in score-api, Sitzung als Cookie
Quelle: score, api/internal/auth
Diagrammdaten anzeigen
Daten zu Anmeldung: OIDC in score-api, Sitzung als Cookie
Nr.
Von
An
Nachricht
Art
Abschnitt
1
Browser
score-web
GET /auth/login
Aufruf
2
score-web
score-api
durchgereicht
Aufruf
3
score-api
Browser
Weiterleitung, PKCE, Nonce
Antwort
4
Browser
Keycloak
Anmeldung beim IdP
Aufruf
5
Keycloak
Browser
Code
Antwort
6
Browser
score-api
/auth/callback über score-web
Aufruf
7
score-api
Keycloak
Code tauschen
Aufruf
8
Keycloak
score-api
ID-Token
Antwort
9
score-api
PostgreSQL
Konto, Person, Sitzung (Hash)
Aufruf
10
score-api
Browser
Cookie score_session
Antwort
11
Browser
score-web
GET /kurse
Aufruf
12
score-web
score-api
GET /v1/kurse mit Cookie
Aufruf
13
score-api
PostgreSQL
Kontext setzen, SELECT
Aufruf
14
PostgreSQL
score-api
nur eigene Einrichtungen
Antwort
15
Keycloak
score-api
Back-Channel-Logout
asynchron
opt [zentrale Abmeldung]
OpenID Connect mit Authorization Code, PKCE und Nonce, ausgeführt in score-api. Der Browser
erhält nur ein httpOnly-Cookie; in der Datenbank steht lediglich dessen SHA-256.
Keycloak brokert die Identitätsanbieter. Das Konto hängt am Subject des ursprünglichen
Anbieters, weil sich die Keycloak-eigene Kennung bei einem Neuaufbau ändern kann.
Sitzungen enden nach Inaktivität (Standard 8 Stunden) und nach einer Höchstdauer (Standard
12 Stunden).
Back-Channel-Logout: Meldet Keycloak eine zentrale Abmeldung, beendet score alle Sitzungen
dieser Anmeldung. Das Logout-Token wird auf Signatur, Zielgruppe, Ereignis und Alter geprüft.
Rücksprungziele nach der Anmeldung sind nur relative Pfade.
Browser-Schutz
Content-Security-Policy als HTTP-Header: Skripte und Styles nur mit Hashes, die beim Rendern
jeder Seite entstehen, keine Ressourcen anderer Herkunft, kein Einbetten in fremde Seiten,
Formulare nur an score selbst und an den Identitätsanbieter. Für die Notenvorschau ist
WebAssembly erlaubt.
Dazu HSTS, X-Content-Type-Options, Referrer-Policy, Permissions-Policy und die
Cross-Origin-Header. Seiten mit Noten dürfen nicht gecacht werden (Cache-Control: no-store).
Formulare prüfen die Herkunft der Anfrage; das Sitzungs-Cookie ist SameSite=Lax.
score-api liefert nur JSON, PDFs und Weiterleitungen und verbietet Browsern, davon etwas
auszuführen oder einzubetten.
Schutzbedarf
Noten, Zeugnisse, Förderdaten und Identitäten haben den Schutzbedarf „hoch“. Daraus folgen der
Betrieb nur in Deutschland, Schlüssel beim Kunden (im Landesprofil KMS oder HSM), die Trennung
von fachlicher Administration und technischem Betrieb und ein Notfallzugang nur im
Vier-Augen-Prinzip mit vollständigem Protokoll.