Diese Seite beschreibt die Genfer Umsetzung des OIDC-Auto-Provisionings. Das
allgemeine Framework ist unter
OIDC Auto-Provisionierung (Single-Sign-On)
dokumentiert. Umgesetzt in backend/logic/GeOidcUserProvisioner.php.
Der Identity-Provider GINA authentifiziert die Genfer Benutzer. GINA liefert BISO jedoch nur die Liste der Applikationsrollen (keine feingranularen Rechte) – und diese nicht in den Front-Channel-Claims, sondern über einen userinfo-Endpoint. BISO holt die Rollen dort ab und bildet sie auf vollständig konfigurierte BISO-Benutzer ab.
Aus dem Login/userinfo stammen:
sub → login.benutzername (z.B. PIERRER; aus dem Front-Channel-Claim gelesen)firstName, lastName, email → verknüpfte Person (aus der userinfo-Antwort,
daher sauber UTF-8-kodiert)roles → z.B. DIP.BISO.ADMINISTRATEUR-APPLICATIONDie Rollen werden als voller String (inkl. Präfix DIP.BISO.) gemappt; die Config-Werte
tragen entsprechend den vollen Rollennamen. Die generische Rolle DIP.BISO.UTILISATEUR
wird ignoriert (führt allein zu keinem Zugriff).
Beispiel einer userinfo-Antwort:
{
"sub": "BRESSONJ",
"firstName": "Julien",
"lastName": "Bresson",
"email": "julien.bresson@etat.ge.ch",
"roles": [
"DIP.BISO.ADMINISTRATEUR-APPLICATION",
"DIP.BISO.GESTIONNAIRE-SECRETAIRE",
"DIP.BISO.UTILISATEUR"
]
}
Die französischen Formularlabels der BISO-Benutzermaske entsprechen folgenden Benutzer-Feldern (in Genf wird Regionalstelle als Prestation beschriftet):
| Formularlabel (FR) | Benutzer-Feld |
|---|---|
| Personne | person_id (verknüpfte Person: Name/Vorname/E-Mail) |
| Prestation | institution_id (eine Institution) |
| Groupe comptes rendus | protokoll_gruppe_id (eine Gruppe) |
| Groupe Propriétaire | owner_group_id (eine Gruppe) |
| Autorisation du groupe = Écrire | owner_group_initial_mode = 6 (Schreiben) |
| Autorisation d'accès par d'autres = Lire | world_initial_mode = 4 (Lesen) |
| Langue = Français | sprache_id = Französisch |
| Conseiller/ère | ist_berater |
| Secrétariat | sekretariat |
| Chef d'atelier | workshopleiter |
| Planificateur d'atelier | workshopplaner |
| Modifier des modules et des prestations | produkte |
| Modifier des personnes et des institutions | stammdaten |
| Montrer Meta-Infos | show_meta_infos |
| Créer des utilisateurs | darf_benutzer_anlegen |
Gemeinsam für alle Profile: Sprache = Französisch, owner_group_initial_mode = 6
(Schreiben), world_initial_mode = 4 (Lesen), verknüpfte Person. Die Person wird
zudem je Seat als aktiver Mitarbeiter der Prestation/Institution erfasst
(find-or-create, deaktivierte werden reaktiviert) — das Personen-Feld im
Benutzer-Formular zeigt nur Mitarbeiter der Institution an.
| Profil (Applikationsrolle) | Benutzer/Seats | Gruppen | Rollen/Rechte | Prestation / Groupe comptes rendus / Groupe Propriétaire |
|---|---|---|---|---|
ADMINISTRATEUR-APPLICATION |
1 | alle Gruppen | alle Rollen-Flags; alle Rechte ausser darf_benutzer_anlegen |
OSP |
GESTIONNAIRE-SECRETAIRE |
1 | OSP + die 8 Service-Gruppen | Conseiller, Secrétariat, Chef d'atelier, Planificateur; Rechte produkte/stammdaten/show_meta_infos | OSP |
GESTIONNAIRE-CONSEILLER |
ein Benutzer pro Service | OSP + Service-Gruppe | Conseiller, Chef d'atelier, Planificateur (kein Secrétariat); Rechte produkte/stammdaten/show_meta_infos | der jeweilige Service |
Kombination: Die Profile wirken additiv — ein OSP-Seat plus je ein Conseiller-Seat
pro Service. ADMINISTRATEUR-APPLICATION und GESTIONNAIRE-SECRETAIRE teilen sich den
OSP-Seat (beide zeigen auf die OSP-Institution; das Admin-Profil ist das Superset und
gewinnt dort).
Ein GESTIONNAIRE-CONSEILLER mit mehreren PRESTATION-*-Rollen erhält je Service
einen eigenen Benutzer (Seat) auf demselben Login. Beim Login zeigt BISO dann das
bestehende Mehrfach-Benutzer-Auswahlfenster, in dem der Benutzer den gewünschten Service
wählt (unterschieden über die Institution/Prestation). Siehe
Seat-Konzept.
Bei jedem Login (wenn oidc.sync_existing = true):
syncBenutzer / applySeat).Person werden aktualisiert
(die bereits verknüpfte Person wird wiederverwendet, kein Duplikat).aktiv=false); er gewährt keinen Zugriff mehr, seine Daten bleiben aber erhalten.UTILISATEUR) →
alle Seats werden deaktiviert und der Login wird abgelehnt; es bleibt kein
aktiver Benutzer mehr, nur der Login-Datensatz.mod_auth_openidc muss den Handshake durchführen und das Access-Token an PHP
weiterreichen (damit OIDC_access_token für den userinfo-Aufruf verfügbar ist):
OIDCPassClaimsAs both
OIDCPassAccessToken On
Vorlage: docker/dev/apache-000-oidc.conf.
config.php – BasisConfig::set('oidc.auto_provision', true); // aktiviert das Provisioning (remote_user_auth nicht nötig)
Config::set('oidc.sync_existing', true);
Config::set('oidc.userinfo_endpoint', 'https://ssorec.geneveid.ch/ginasso/oauth2/userinfo');
Config::set('oidc.roles_claim', 'roles');
config.php – Gruppen-/Institutions-Mapping (nach ID)Rollen werden nach ID auf BISO-Gruppen und -Institutionen abgebildet. Die IDs stammen aus der GE-Produktions-Datenbank. Jeder Service und OSP müssen dort sowohl als Gruppe als auch als Institution existieren.
Die dafür benötigten IDs liefern die folgenden beiden Abfragen. Die Spalte
anzahl_benutzer zeigt, wie viele Benutzer den Eintrag nutzen — so lassen sich die aktiv
genutzten Einträge erkennen. Beide Abfragen liegen auch als ausführbare Scripte unter
sql/ bereit.
Gruppen (für osp_gruppe_id und die gruppe_id je Service):
SELECT g.id, g.name, count(bg.benutzer_id) AS anzahl_benutzer
FROM gruppe g
LEFT JOIN benutzer_gruppe bg ON bg.gruppe_id = g.id
GROUP BY g.id, g.name
ORDER BY g.name;
Institutionen / Prestations (für osp_institution_id und die institution_id je
Service; der Filter ist_bsb grenzt auf die OSP-Prestations ein — ohne ihn erscheinen
auch alle Schulen):
SELECT i.id, i.name, i.aktiv,
count(b.id) FILTER (WHERE b.deleted IS NULL AND b.aktiv) AS anzahl_benutzer
FROM v_institution i
LEFT JOIN benutzer b ON b.institution_id = i.id
WHERE i.ist_bsb
GROUP BY i.id, i.name, i.aktiv
ORDER BY i.name;
Config::set('oidc.ge.osp_gruppe_id', 0); // OSP: Gruppe
Config::set('oidc.ge.osp_institution_id', 0); // OSP: Institution (Prestation)
Config::set('oidc.ge.services', [
// '<volle ROLLE, GROSSBUCHSTABEN>' => ['gruppe_id' => <int>, 'institution_id' => <int>],
'DIP.BISO.PRESTATION-CYCLE-D-ORIENTATION' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-ACCESSII' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-PREQUALIFIANT' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-CFP-COMMERCE' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-ECG' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-COLLEGE' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.ENSEIGNEMENT-SPECIALISE' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-ETUDIANTS' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-TOUT-PUBLIC' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-VIAMIA' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-CHAMP-DOLLON' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-FEMME-ET-EMPLOI' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-TREMPLIN-JEUNES' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-EVASCOL' => ['gruppe_id' => 0, 'institution_id' => 0],
'DIP.BISO.PRESTATION-PRO-APPRENTIS' => ['gruppe_id' => 0, 'institution_id' => 0],
]);
// Die 8 Service-Rollen, in deren Gruppen das SECRETAIRE-Profil Mitglied ist:
Config::set('oidc.ge.secretaire_service_roles', [
'DIP.BISO.PRESTATION-ETUDIANTS', 'DIP.BISO.PRESTATION-TOUT-PUBLIC', 'DIP.BISO.PRESTATION-VIAMIA',
'DIP.BISO.PRESTATION-CHAMP-DOLLON', 'DIP.BISO.PRESTATION-FEMME-ET-EMPLOI',
'DIP.BISO.PRESTATION-TREMPLIN-JEUNES', 'DIP.BISO.PRESTATION-EVASCOL', 'DIP.BISO.PRESTATION-PRO-APPRENTIS',
]);
Eigener oidc-Log-Kanal wie im allgemeinen Framework beschrieben, siehe
OIDC Auto-Provisionierung – Logging.
Benutzer können vorab aus der GINA-Rollenliste angelegt werden, ohne dass sich jede Person zuerst einmal anmelden muss:
php backend/tools/ge_oidc_user_import.php <datei.xlsx> # Probelauf (Default)
php backend/tools/ge_oidc_user_import.php <datei.xlsx> --do-it # schreibt
Loginname: Standardmässig wird die Spalte Identifiant zu login.benutzername, per
--login-column=<Überschrift> umstellbar. Entscheidend ist, dass die Spalte denselben Wert
trägt, den GINA als sub liefert — und das ist der Identifiant (BRESSONJ), nicht die
E-Mail-Adresse. Trifft die Spalte den sub nicht, wird der importierte Benutzer beim
ersten SSO-Login nicht erkannt und ein zweites Konto entsteht. Zur Kontrolle meldet der
Probelauf für die gewählte und die alternative Spalte, wie viele Werte bereits als
Login existieren; die Spalte mit der Überschneidung ist die richtige.
Gross-/Kleinschreibung: Der Login-Pfad normalisiert nirgends — extractUsername()
trimmt nur, findLogin() vergleicht exakt, und der Unique-Index auf login.benutzername
ist case-sensitiv. Der Loginname muss den sub des IdP daher zeichengenau treffen. Das
Script warnt deshalb unter Angabe der Zeile, wenn ein Wert sich von einem bestehenden Login
nur in der Schreibweise unterscheidet — das ergäbe ein Zweitkonto. Korrigiert wird nichts
automatisch: die Schreibweise gehört in die Quelldatei.
Das Script bildet die Rollen nicht selbst ab: es baut aus jeder Zeile die Claims, die
GINA liefern würde, und übergibt sie dem bestehenden GeOidcUserProvisioner. Seats,
Gruppen, Flags, verknüpfte Person und Mitarbeiter entstehen dadurch identisch zum
SSO-Login. Der userinfo-Aufruf wird für den Lauf abgeschaltet (die Rollen kommen aus der
Datei), oidc.sync_existing wird erzwungen.
Erwartetes Dateiformat (Sheet Collaborateurs-GINA-BISO): eine Bandzeile mit den Zellen
GINA und – weiter rechts – BISO, darunter eine Kopfzeile mit Identifiant, Nom,
Prénom, Adresse email. Jede Spalte zwischen GINA und BISO ist eine Rolle und muss
einer Profilrolle oder einem Schlüssel aus oidc.ge.services entsprechen. Markierung ist
x. Die optionale Spalte Nb de sous-profils attendus dans BISO wird gegen die berechnete
Seat-Anzahl geprüft.
Vor dem ersten Schreibzugriff prüft das Script die ganze Datei und bricht bei Problemen ab,
ohne etwas zu schreiben: unbekannte Rollenspalte (mit Korrekturvorschlag), doppelter
Identifiant, fehlende Identität, Zeile ohne Profilrolle. Ein Service aus der Config ohne
Spalte in der Datei ergibt nur eine Warnung.
Pro Person meldet der Lauf die erkannten Profil- und Servicerollen, die daraus berechneten
Prestationen (ID und Name) sowie ob ein OSP-Seat entsteht. Ein OSP-Seat kommt nur aus
ADMINISTRATEUR-APPLICATION oder GESTIONNAIRE-SECRETAIRE; GESTIONNAIRE-CONSEILLER
vergibt die OSP-Gruppe, aber keine OSP-Prestation.
Weil der Import dasselbe Ergebnis liefern muss wie ein echter GINA-Login, warnt das Script
zusätzlich, wenn eine Zeile ADMINISTRATEUR-APPLICATION trägt, aber nicht alle
Service-Spalten markiert sind. GINA vergibt einem Administrator alle Service-Rollen;
steht zusätzlich GESTIONNAIRE-CONSEILLER in derselben Zeile, entsteht daraus beim ersten
SSO-Login pro Service ein Berater-Konto. Die Warnung nennt beide Zahlen.
Im Probelauf läuft alles in einer Transaktion, die am Schluss zurückgerollt wird. Mit
--do-it wird pro Person committet — ein Fehler bei einer Person lässt die bereits
verarbeiteten bestehen. Ein zweiter Lauf legt nichts neu an, sondern synchronisiert nur.
Benutzer, die nicht in der Liste stehen, werden nicht angefasst.
Voraussetzung ist eine vollständige Konfiguration: oidc.ge.services muss alle Services
enthalten, und Gruppen und Institutionen müssen existieren (siehe sql/).
Profil-Rollen: ADMINISTRATEUR-APPLICATION, GESTIONNAIRE-SECRETAIRE,
GESTIONNAIRE-CONSEILLER (jeweils mit Präfix DIP.BISO.).
Service-Rollen (PRESTATION-*): PRESTATION-CYCLE-D-ORIENTATION,
PRESTATION-ACCESSII, PRESTATION-PREQUALIFIANT, PRESTATION-CFP-COMMERCE,
PRESTATION-ECG, PRESTATION-COLLEGE, ENSEIGNEMENT-SPECIALISE,
PRESTATION-ETUDIANTS, PRESTATION-TOUT-PUBLIC, PRESTATION-VIAMIA,
PRESTATION-CHAMP-DOLLON, PRESTATION-FEMME-ET-EMPLOI, PRESTATION-TREMPLIN-JEUNES,
PRESTATION-EVASCOL, PRESTATION-PRO-APPRENTIS.
oidc.debug_claims = true setzen: die normalisierten Claims und die rohen
OIDC_*-Server-Variablen werden in den oidc-Kanal geloggt (nur Dev/Test;
Token-Werte werden dabei maskiert).biso-oidc.log prüfen: Provisioning-Start, geholte Rollen, erstellte/aktualisierte
Seats, Deaktivierungen, Fehler.oidc.ge.services-Mapping nicht hinterlegt –
ohne erkannte Rolle werden alle Seats deaktiviert und der Zugriff verweigert.