| 
 
 | 
| 
 | 
 OAuth / OpenID Connect als Zentraler Anmeldedienst HIT/ZID
 Kurz und bündigBevor eine OAuth-Anfrage durchgeführt werden kann, müssen die Clients bei der Zentralen Datenbank registriert worden sein. Jeder Client (nicht der Benutzer!) wird durch seine Kennung, seine Antwort-URIs und ein Passwort authentifiziert. Dann kann damit nach dem OpenID Connect-Verfahren (kurz OIDC) zunächst eine Nutzerautorisierung und schließlich ein Access Token angefordert werden: 
 Neben diesen kann über OIDC Discovery in Erfahrung gebracht werden, welche URIs und Parameter die OIDC-Schnittstelle versteht: z.B. für Test-System. Es ist neben OIDC Core lediglich OIDC Session Management implemeniert. Keine der beiden Channel Logout-Mechanismen sind vorhanden. Registrierung ClientWichtiger Hinweis: Nur registrierte Clients können sich mit OAuth verbinden. Für eine Registrierung ist vorab eine Genehmigung durch den Vertreter des Landes in der BLAG/DZ erforderlich! Da wir (derzeit) eine Client-Registrierung weder per Webseite, noch per HIT-Protokoll, noch per OpenID Connect Dynamic Registration unterstützen, bitte formlos eine Email an technik@hi-tier.de mit folgenden Angaben senden (einfach Tabelle ausfüllen, dann den "Email-Text erzeugen"-Knopf klicken und das erzeugte in die Email einfügen): 
 Wir tragen die per Email zugesandten Angaben manuell bei uns ein und Sie erhalten dann von 
		uns einen zufällig generierten String, der als  Neu ab Februar 2022: die Schnittstelle wurde um eine Anmelde-Nutzergruppe, 
		eine Daten/Rechte-Freigabe und Angaben von Verantwortlichen erweitert 
		(siehe die letzten vier Felder im Formular oben). Diejenigen, die vor 
		Februar 2022 einen Client registriert haben (egal ob für Test, 
		Prodution oder Wartung), melden bitte die Angaben aus den vier 
		genannten Feldern formlos per Email unter der Angabe des Systems und der
		   Details zur ImplementierungAblaufDie OAuth-Autorisierung nach OIDC läuft in zwei Stufen ab (Schema "Authorization Code Flow"): 
 Dadurch, dass der Authorization Code eingetauscht wird, ist sichergestellt, dass mögliche PIN-Angaben im Browser (in Schritt 2) dort verbleiben und der Client in Schritt 3 (und folgenden) keine Angaben zur Nutzer-PIN kennt. Es wird ein klassisches Session-Cookie mitgeführt, um mehrfache Authentifizierungen innerhalb kurzer Zeit zu ermöglichen, ohne sich jedesmal erneut anmelden zu müssen. Erkennt der ZAD ein erhaltenes Session-Cookie, wird sofort ein neuer Authorization Code an den Client zurückgesendet, ohne die Anmeldemaske des ZAD anzuzeigen. Ein explizites Abmelden des Anwenders ist daher auch implementiert, Details dazu siehe unten. Domains für OIDC-AnfragenDie Webserver von HIT sind unter der zentralen Domain  Damit der Client sicher nur mit einer IP-Adresse arbeitet, muss dieser mit einer der folgenden Domainnamen arbeiten: 
 Es ist dringend anzuraten, im Client, der OIDC handhabt, alle genannten Domainnamen zu hinterlegen und bei jedem Authorization Request zufällig eine Domain auszuwählen und in sämtlichen URLs dieser Session zu verwenden. Der Tokentausch (Authorization Code zum Access Token) 
		muss mit der gleichen ausgewählten Domain wie beim Authorization Request 
		vorgenommen werden. In den 
		Beispielaufrufen der einzelnen Stufen unten ist somit der Platzhalter  SystemeIn den folgenden beschriebenen Stufen wird die URI für unser Testsystem angegeben. Für die anderen Systeme lautet die Pfadangabe in der URI wie folgt: 
 (zum Platzhalter  Eine Eintragung Ihres Clients in eines der Systeme setzt voraus, dass ein Vertreter des Landes in der Bund.-Länder-Arbeitsgruppe Direktzahlungen (BLAG/DZ) die Nutzung von OIDC genehmigt. Stufe 1: Authorization Code [AUC]Client-Anfrage an den HIT/ZID-Anmeldedienst mit HTTP GETDie URI für die Client-Anfrage (Schritt 1) ist  Der  Die Angaben für  Die  Der  Optional:  Technisch gesehen wird z.B. aus einer Webanwendung heraus ein Redirect an unseren Autorisierungsendpunkt (Schritt 1) abgesetzt: HTTP/1.1 302 Found Location: /HitTest3/zad_oauth/auth_req? scope=openid &response_type=code &client_id=45678R &redirect_uri=https%3A%2F%2Fwww.ihr-client.de%2Froute%2Fendpunkt &nonce=client.session.id &state=xsrf.blocker Host: www.hi-tier.de ( Überprüfung der QueryString-ParameterUnser Endpunkt überprüft auf Vorhandensein der übergebenen Parameter. Wenn nicht ausreichend, dann wird eine entsprechende JSON-Fehlerantwort gesendet. OIDC erlaubt weitere Angaben im Authentication Request, von 
		denen manche (z.B.  Zuerst wird die Client-Angabe  Wenn Client gültig, dann wird  Wenn Client und Redirect-URI gültig, dann wird zusammen mit einem internen Token zur Anmeldemaske des Zentralen Anmeldedienstes weitergeleitet, auf der sich der Nutzer des Clients als HIT/ZID-Anwender authentifizieren muss (Schritt 2). Schlägt die Anmeldung fehl, kann der Anwender die Anmeldung wie bei der klassischen HIT-Webanwendung wiederholen, bis er angemeldet ist (weiterhin Schritt 2). Kann er sich aufgrund einer falschen PIN nicht anmelden oder ist er gesperrt, muss er über den Knopf "Abbrechen" zu OAuth zurückkehren. In dem Fall wird eine entsprechende JSON-Fehlerantwort gesendet (Schritt 3). Ist das Passwort eines Nutzers abgelaufen oder muss dieses wegen Neuzuteilung sofort geändert werden, dann wird der Nutzer auf eine Passwort-Änderungsseite weitergeleitet, auf dieser er sich unter Angabe seines bisherigen Passwortes ein neues Passwort vergeben kann. Ist dieser Vorgang erfolgreich, dann ist der Nutzer authorisiert und wird zu OAuth zurückgeleitet. 
 Beispiel Fehlerantwort, wenn Client nicht autorisiert (Schritt 3): HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Cache-Control: private
Pragma: no-cache
{
   "error": "invalid_request",
   "error_description": "OAuth-Anmeldung fehlgeschlagen - CLIENT_ID nicht gefunden",
   "nonce": "client.session.id",
   "state": "xsrf.blocker"
}Erfolgreiche Anmeldung am HIT/ZID-AnmeldedienstNach erfolgreicher Anmeldung erzeugt der HitServer auf der selben Datenbankverbindung den Authorization Code für diesen Client und dessen Nutzer. Die Antwort-URI wird anhand  Beispiel Fehlerantwort, wenn Client autorisiert, aber Nutzeranmeldung abgebrochen (Schritt 3): es wird ein Redirect an den von Ihnen registrierten Endpunkt veranlasst: https://www.ihr-client.de/route/endpunkt? error=unauthorized_client &error_description=Anmeldung+fehlgeschlagen:+Falsche+oder+fehlende+PIN &error_hit=224 &nonce=client.session.id &state=xsrf.blocker Im Schlüssel  Beispiel Antwort nach erfolgreicher Anmeldung des Nutzers (Schritt 3): es wird ein Redirect an den von Ihnen registrierten Endpunkt veranlasst: HTTP/1.1 302 Found Location: https://www.ihr-client.de/route/endpunkt?code=ich.bin.der.lange.kurzlebige.auth.code&nonce=client.session.id&state=xsrf.blocker An keiner Stelle wird die PIN des Nutzers aus der Anmeldemaske des Zentralen Anmeldedienstes an den Client übermittelt. Da aber der Authorization Code und die PIN über HTTP-Client oder Webbrowser tranferiert wurden, muss dieser im nächsten Schritt ohne diese Clients durch einen Access Token ersetzt werden. 
 Stufe 2: Access Token [ACT]Client-Anfrage an den HIT/ZID-Anmeldedienst mit HTTP  | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|  | entweder einen HTTP-Header Authorizationmit dem 
			SchemaBasicund Base64-encodetem
			client_id:client_secretmitsenden | 
|  | oder client_idundclient_secretals 
			Teil desquerystringmitliefern | 
Letzteres ist laut OAuth zulässig, wenn die Verbindung mit TLS verschlüsselt ist, was sie bei HIT/ZID grundsätzlich ist.
Eine POST-Anfrage mit Authorization-Header (Schritt 4) sähe so aus:
POST /HitTest3/zad_oauth/token HTTP 1.1 Host: www.hi-tier.de Content-Type: application/x-www-form-urlencoded Authorization: Basic base64base64base64base64base64 grant_type=authorization_code &code=ich.bin.der.lange.kurzlebige.auth.code &redirect_uri=https%3A%2F%2Fwww.ihr-client.de%2Froute%2Fendpunkt
Die Angaben der Autorisierung werden geprüft. Im Fehlerfall wird eine entsprechende JSON-Fehlerantwort gesendet (Schritt 5).
Der Parameter grant_type muss authorization_code 
		lauten. Falls nicht, wird eine entsprechende JSON-Fehlerantwort 
		gesendet (Schritt 5).
Wenn soweit korrekt, werden sämtliche Angaben gegen den HitServer geprüft. Bei fehlerhaften Angaben erhält man eine entsprechende JSON-Fehlerantwort (Schritt 5).
Eine Fehlerantwort bei falscher Client-ID (Schritt 5) sähe z.B. so aus:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Cache-Control: private
Pragma: no-cache
{
   "error": "invalid_client",
   "error_description": "Falsche Client-Credentials"
}
		Wenn erfolgreich, liefert der HitServer das Access Token ACT, optional das Refresh Token (RET), und für den Payload in Form eines ID-Token die Betriebsnummer und ggf. weitere Angaben je nach Daten-/Rechtefreigabe.
Aus diesen Angaben wird eine Datenstruktur (=Payload) für ein 
		ID-Token befüllt und als
		JWT (=JSON Web Token) codiert,
		dieses als 
		id_token zusammen mit dem access_token, ggf. dem 
		refresh_token und weiteren 
		Angaben 
		als JSON-Antwort an den Client zurückgesendet (Schritt 5).
Der Client erhält im ID-Token zusätzlich zu den vorgegebenen 
		Schlüsseln lediglich bnr und mbn, da aus 
		Sicherheitsgründen gegenüber dem HitServer mit einer sehr beschränkten 
		Kompetenz auf der HIT-Datenbank gearbeitet wird. Möchte man mehr Daten 
		zum Betrieb erhalten, dann kann dies unter Zuhilfenahme des Access 
		Token z.B. über unsere REST-Schnittstelle abgefragt werden.
Eine erfolgreiche Antwort auf die Anforderung eines Access Tokens sieht so aus:
HTTP/1.1 200 OK
Cache-Control: private
Pragma: no-cache
Content-Type: application/json; charset=utf-8
{
   "token_type": "Bearer",
   "access_token": "mit.mir.kann.man.sich.bei.HIT.autorisieren",
   "expires_in": 1200,
   "expires_at": 1576760000,
   "refresh_token": "wenn.ACT.abgelaufen.nimm.mich",
   "id_token": "eyJhbGciOiJub25lIn0=.codiertesJWT."
}
		Die Angabe expires_at (=Anzahl Sekunden seit Unix Epoch 
		am 01.01.1970 0 Uhr UTC) ist die einzige ausserhalb der 
		OIDC-Spezifikation, korreliert aber direkt mit expires_in: 
		es ist der Zeitpunkt, an dem das ACT abgelaufen sein wird.
Das gelieferte ID-Token (der Payload) enthält in jedem Fall 
		die Standard-OIDC-Claims "iss" (Issuer), "sub" 
		(Subject), "aud" (Audience), "iat" 
		(Issued at), "exp" (Expires at) und wenn 
		vorhanden auch "nonce".
HIT/ZID-spezifisch werden immer "bnr" und "mbn" 
		geliefert und je nach Daten-/Rechte-Freigabe zusätzlich: "typ_betr" 
		(als Array), "name_betr", "adresse_betr". 
		Siehe Formular oben zu den Details.
Der Inhalt von Feld access_token kann nun für die Dauer 
		von expires_in Sekunden als Identifikation, als PIN-Ersatz oder als Session-Key verwendet werden.
Als Identifikation genügt der bloße "Besitz" dieses Tokens - damit lässt sich ein Benutzer eindeutig identifizieren.
Darüber hinaus kann das Token -derzeit nur im Test!- in 
		Kombination mit Betriebsnummer und Mitbenutzerkennung zur Anmeldung 
		verwendet werden.
		Beispiel: Login mit Access Token statt PIN
*1:XS:LOGON/BNR15;MELD_WG;TIMEOUT;OI_C_ID;OI_TOKEN:09 000 000 0001;3;1200;45678R;mit.mir.kann.man.sich.bei.HIT.autorisieren
Die Angabe des Clients OI_C_ID ist hierbei zusätzlich 
		erforderlich, um alle von diesem Client zur Betriebsnummer vergebenen
		Access Token zu löschen, falls jemand mehrmals durch 
		Ausprobieren dieses Token "erraten" möchte. Damit wird verhindert, dass 
		der Betrieb für die PIN-Anmeldung gesperrt wird.
Im REST-Interface von HIT3 gibt des optional die Parameter cid 
		(für die Client ID) und act (für das Access Token), die 
		statt der Angabe einer Nutzer-PIN verwendet werden können. Auf die 
		Angabe des act kann verzichtet werden, wenn das Token als 
		HTTP-Header Authorization und dem Schema Bearer 
		(und nicht als klassisches Basic-Schema) mitgesendet wird.
Die Clients, die bei der Registrierung (siehe oben) angegeben 
haben, dass sie ein refresh_token nutzen wollen, erhalten dieses 
auch in Stufe 2 zusammen mit dem Access Token geliefert.
Das Refresh Token dient dazu, ein abgelaufenes oder auch noch gültiges Access Token zu erneuern.
POSTDie URI für die Client-Anfrage (Schritt 4) ist https://DOMAIN/HitTest3/zad_oauth/token
Da eine HTTP POST-Anfrage zwingend ist, enthält der 
		HTTP-Content (nicht die URI) dieser Anfrage einen 
		querystring, 
		der aus  grant_type=refresh_token&refresh_token=XXX&scope=openid 
		besteht.
Der Content-Type dafür ist application/x-www-form-urlencoded.
Der HTTP POST-Request muss autorisiert sein, d.h.
|  | entweder einen HTTP-Header Authorizationmit dem 
			SchemaBasicund Base64-encodetem
			client_id:client_secretmitsenden | 
|  | oder client_idundclient_secretals 
			Teil desquerystringmitliefern | 
Letzteres ist laut OAuth zulässig, wenn die Verbindung mit TLS verschlüsselt ist, was sie bei HIT/ZID grundsätzlich ist.
Eine POST-Anfrage mit Authorization-Header (Schritt 4) sähe so aus:
POST /HitTest3/zad_oauth/token HTTP 1.1 Host: www.hi-tier.de Content-Type: application/x-www-form-urlencoded Authorization: Basic base64base64base64base64base64 grant_type=refresh_token &scope=openid &refresh_token=wenn.ACT.abgelaufen.nimm.mich
Die Angaben der Autorisierung werden geprüft. Im Fehlerfall wird eine entsprechende JSON-Fehlerantwort gesendet (Schritt 5).
Der Parameter grant_type muss refresh_token 
		lauten, auch scope ist vorgegeben. Falls nicht, wird eine 
entsprechende JSON-Fehlerantwort gesendet (Schritt 5).
Wenn soweit korrekt, werden sämtliche Angaben gegen den HitServer geprüft. Bei fehlerhaften Angaben erhält man eine entsprechende JSON-Fehlerantwort (Schritt 5). Auch, wenn das Refesh Token selbst bereits abgelaufen ist.
Wenn erfolgreich, wird mit dem neuen Access Token (das bisherige wird gelöscht, wenn noch gültig) 
eine Antwort gebildet.
		Weitere Angaben für z.B. ein neues ID-Token werden nicht 
		ermittelt (also kein "frisches" Payload).
Eine Fehlerantwort bei falscher Client-ID (Schritt 5) sähe so aus:
HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Cache-Control: private
Pragma: no-cache
{
   "error": "invalid_client",
   "error_description": "Falsche Client-Credentials"
}
		Eine einfache JSON-Antwort mit dem neuen Access Token, dem bekannten Refresh Token und dessen Gültigkeitsdauer wird erzeugt und geliefert (Schritt 5).
Beispiel:
HTTP/1.1 200 OK
Cache-Control: private
Pragma: no-cache
Content-Type: application/json; charset=utf-8
{
   "token_type": "Bearer",
   "access_token": "ich.bin.ab.jetzt.zustaendig.fuer.HIT",
   "expires_in": 1200,
   "expires_at": 1576777777,
   "refresh_token": "wenn.ACT.abgelaufen.nimm.mich"
}
		Nach erfolgreicher Anmeldung in der Anmeldemaske des Zentralen Anmeldedienstes wird ein klassisches Session-Cookie gesetzt, das einen Nutzer für die nächsten 20 Minuten authentifiziert. Nach einem erfolgreichen Austausch des Authorization Code in ein Access Token ändert sich diese Laufzeit auf die bei der Registrierung des Clients gewünschte Laufzeit des Access Tokens.
Wird in der Zeit, in der die Session besteht, ein neuer Authorization Request 
versendet, erhält man einen neuen Authorization Code, ohne sich neu anmelden zu müssen.
Damit diese Session vorzeitig beendet werden kann, z.B. wenn die Sitzung nicht 
mehr benötigt wird oder ein anderer Nutzer sich anmelden möchte, gibt es den 
end_session_endpoint mit der URI: https://DOMAIN/HitTest3/zad_oauth/let_me_go
Die URI besitzt drei Parameter, keiner davon ist zwingend:
|  | id_token_hint: das erhaltende ID-Token kann als 
	Hinweisgeber für eine Sitzung mitgesendet werden, um inbesondere nach Ablauf 
	der Session dennoch geordnet per Redirect zurückkehren zu können | 
|  | post_logout_redirect_uri: dies ist das gewünschte Ziel zum 
	Rückkehren per Redirect. Dieses muss angegeben werden, wenn bei der 
	Registrierung mehr als nur ein Rückkehrziel angegeben wurde! | 
|  | state: ein für den Client zum Schutz vor XSRF interessanter 
	Status, der durchgeschleift wird. Solltestatenicht zum Client 
	gehören, weil ein Dritter den Logout durchführt, findet der Logout dennoch 
	statt. | 
Weder das OpenID Connect Front-Channel Logout noch das OpenID Connect Back-Channel Logout sind hier implementiert!
Stimmen Parameter nicht oder passt das ID-Token nicht zur Session oder kann die Weiterleitungs-URI nicht eindeutig bestimmt werden, erhält man eine JSON-Antwort als Fehlermeldung.
Derzeit nicht in Produktion verfügbar! (noch in Testung - also nur im Test, Wartung oder Clone verfügbar)
Es gibt Anwendungen, die arbeiten außerhalb eines in sich geschlossenen Anwendungskontext (z.B. Smartphone-App leitet weiter an Smartphone-Browser) und benötigen daher eine Prüfmöglichkeit, ob ein Access Token oder ein Refresh Token noch gültig ist.
Der Endpunkt ist: https://DOMAIN/HitTest3/zad_oauth/intrspct 
, der nur als HTTPS-POST-Anfrage durchgeführt werden darf.
Derzeit wird nur das zu prüfende Token mit dem Parameter token 
angegeben. Der Parameter token_type_hint ist nicht implementiert.
Zusätzlich sind aus Sicherheitsgründen die Parameter client_id und
client_secret mitzuliefern, um ein "Ausprobieren" von Tokens 
einzudämmen.
Als Antwort erhält man immer ein JSON-Objekt, das die Felder 
		active und die client_id enthält (letztere weil sie 
		beim Request mitgegeben werden).
		Stimmem beide client-Parameter nicht, erhält das Objekt 
		Fehlerangaben. Nur wenn active gleich true 
		ist, ist zum Zeitpunkt der Abfrage das Token noch gültig.
Da zur Prüfung das Confirm-Kommando des HitServers verwendet wird, welches auch für den Tokentausch bzw. die Tokenerneuerung zuständig ist, kann kein expliziter Tokentyp überprüft werden. Die Angabe des Token prüft somit immer auf noch gültige Access Token und Refresh Token.
..
|   |