[Epic] Destination Verwaltung per API ermöglichen
Warum?
Bisher erfolgt die manuelle Eingabe sämtlicher Daten in das Self-Service-Portal. Dies bedeutet einen erheblichen Zeitaufwand, insbesondere für Großunternehmen wie ADKB und Ok.Komm, wenn beispielsweise 2.000 Zustellpunkte erstellt werden müssen. Diese Dienstleister besitzen in der Regel in ihren eigenen Managementsystemen alle Informationen zu den Systemen, Leistungen und Zuständigkeiten, die für die Anlage und Verwaltung von Destinationen benötigen.
Die Submission API von FIT-Connect ist bereits darauf ausgelegt, die Anlage und Verwaltung von Destinationen über Schnittstellenaufrufe zu realisieren. Bisher scheiterte eine sinnvolle Nutzung durch Drittsysteme primär daran, dass eine initiale Erstellung von Destinations per API nicht möglich war, da in der jetzigen Architektur und im API Design keine Zuordnung von Destinations an den User möglich war. Grund hierfür ist die Tatsache, dass der Zustelldienst das über den API Call keine Zuordnung zum User möglich ist und der Zustelldienst auch keine Besitzinformationen speichert, sondern nur das SSP. Daher kann aktuell nur das SSP Destinations per API erstellen, aber keine Drittsysteme.
Ferne gibt es auch einen Freitextnamen für Destinations für eine bessere interne Verwaltung von Destinations durch verantwortliche Behörde, der aber nicht per API bearbeitbar ist, sondern nur über das SSP bearbeitbar ist und dort auch nur gespeichert wird.
Ziel: Die Architektur und API sollen so modifiziert werden, dass eine vollständige Erstellung und Verwaltung von Destinations per API auch von Drittsystemen möglich ist.
Verbundene Themen außerhalb des Epics:
- Durch eine Anpassung des JWTs soll es auch möglich sein, mit mehr als 30 Destination Scopes zu arbeiten. Wir aber in #1230 (closed) umgesetzt.
- Langfristig soll auch die Erstellung von API-Clients sowie der Scope von Clients für bestimmte Destinations für Drittsysteme möglich sein und soll durch die Architektur möglich sein, aber ist nicht Teil des Umfangs dieses Epics.
Relevante Links und Bemerkungen
- Dieses Epic wurde bereits versucht im Kontext der Self-Service-API umzusetzen, bei denen des SSP eine eigene API anbietet, die Anfragen zum Zustelldienst vermittelt. Siehe: https://git.fitko.de/fit-connect/planning/-/issues/?sort=created_date&state=opened&label_name%5B%5D=Epic%3A%3ASelf-Service-API&first_page_size=20
- Interne Evaluierungen und Einschätzungen haben ergeben, dass der dortige Ansatz Probleme verursachen könnte und viele Implikationen für zukünftige Weiterentwicklung von FIT-Connect haben (z.B. Performance, Entwicklungsgeschwindigkeit, Erfüllung von fachlichen Anforderungen wie mehrere Destinations) haben könnte.
Angedachte Architektur
Draw.io Datei:Architecture-Changes.drawio
Aufbau eines Access Tokens für die Endpunkte
Feld | Inhalt | Erläuterung |
---|---|---|
sub (Subject) |
User ID | ID des Users, für den der Client agiert. Eindeutiger / langzeitstabiler Identifikator des User aus dem User Backend (Keycloak). Nutzer ist in diesem Fall der Betreiber des API-Clients (Onlinedienst/Fachverfahren). Alternativ kann hier auch eine Gruppen-ID stehen, wir direkt Gruppen als Konzept in Keycloak umsetzen. |
aud (Audience) |
URL der Submission API | Die URL der API des Zustelldienstes, für den der Token ausgestellt wurde, gemäß RFC 7519, Abschnitt 4.1.3. Anm. Wojtek: #1278 (comment 107705) |
scope |
Scopes für die Verwaltung von Destinations | Eine Liste der Zustellberechtigungs-Scopes, separiert mit Leerzeichen gemäß RFC 6749, Abschnitt 3.3. Finale Scopes noch zu klären. |
iss (Issuer) |
URL des Autorisierungsservers | URL des Autorisierungsservers der das Access Token ausgestellt hat. |
exp |
Unix Timestamp | Ablaufzeitpunkt des Access Tokens (DARF max. 2 Stunden gültig sein; vgl. BSI APP.3.1) |
iat |
Unix Timestamp | Ausstellungszeitpunkt des Access Tokens. |
jti (JWT ID) |
ID des Tokens | Eindeutige ID des ausgestellten Tokens. |
client_id |
Client ID | Client ID des Clients, für den der Access Token ausgestellt wird. |
Ablauf Anlage neuer Clients
Folgender Ablauf erzeugt eines User gebundene Autorisierung. Diese wird nicht über einen Authorization Code Grant erzeugt (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-08#name-authorization-code-grant), sondern per API des Connect2ID, um die Komplexität zu reduzieren. Das entspricht grundsätzlich dem Refresh Token Grant (siehe Ablauf unten).
sequenceDiagram
User->>IDP (Keycloak): Login to SSP
IDP (Keycloak)->>SSP: Forward User
SSP->>IDP (Keycloak): GET User Data and Client-ID for User-ID
IDP (Keycloak)->>SSP: Return User Data and Client-ID requested User-ID
SSP->>ZSD: GET Destination Data
ZSD->>ZSD: Look up Destination for User-ID in Token Sub Claim
ZSD->>SSP: Return Destination Data
SSP->>OAuth(Connect2ID): GET Client Data für Clients-IDs
OAuth(Connect2ID)->>SSP: Return Client Data
SSP->>User: Show User Interface Options and Data
User->>SSP: Create new Client for Destination-ID with Create Scope
SSP->>OAuth(Connect2ID): POST Create Client with Create Scope für User-ID
OAuth(Connect2ID)->>OAuth(Connect2ID): Generate Client ID, Client Secret, Refresh Token and store Client Data in Database
OAuth(Connect2ID)->>SSP: Return Client Data of new Client
SSP->>User: Show Information of the new Client
User->>User: Export Client-ID, Secret und Refresh Token
Ablauf: Destination mittels Submission API anlegen
Dieser Ablauf entspricht dem Refresh Token Grant: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-08#name-refresh-token-grant
Refresh Token erlauben es, weitere Access Tokens ohne erneute Autorisierungsflows abzurufen. Weitere Infos zur Refresh Tokens: https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
Um die Sicherheit zu erhöhen, werden folgende Maßnahmen getroffen:
- Refresh Tokens sind immer an den Client gebunden. Client muss sich ggü. dem OAuth Server mit seinem Secret authentifizieren.
- Um Sicherheitsprobleme beim Verlust von Refresh Tokens UND Client Secret zu reduzieren, wird eine Refresh Token Rotation angewendet, um den Verlust von Refresh Tokens zu identifizieren. Siehe https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-08#section-4.3.1
- Ggf. könnte man überlegen, dem Refresh Token ein Expiration Data geben (bspw. 30 Tage), damit ein regelmäßiger Abruf von Tokens erzwungen wird.
sequenceDiagram
API-Client->>OAuth(Connect2ID): GET Access Token with Client-ID, Secret and Refresh Token
OAuth(Connect2ID)->>OAuth(Connect2ID): Access Token, Invalidate Refresh Token und Generate new Refresh Token
OAuth(Connect2ID)->>API-Client: Return Access Token and Refresh Token
API-Client->>ZSP(Submission-API): POST Create Destination
ZSP(Submission-API)->>ZSP(Submission-API): Generate new Destination ID in the Database
ZSP(Submission-API)->>ZSP(Submission-API): Store Destination Data for Destination ID in the Database
ZSP(Submission-API)->>ZSP(Submission-API): Store User ID from Access Token for Destination ID in the Database
ZSP(Submission-API)->>API-Client: Return Response 201 "Created"
Offene Fragen
Gruppen IDs
Anmerkung: Epic baut auf den Architekturänderungen auf, die durch das Keycloak Epic (#1192 (closed)) umgesetzt werden.
- Offener Punkt: Im Keycloak Epic wird geprüft, ob wir direkt Gruppen bzw. Gruppen-IDs einführen. In diesem Fall würden Destinations und Clients grundsätzlich einer Gruppen-ID statt einer User-ID zugeordnet werden. Wenn noch keine Gruppen-IDs vorhanden sind, müssen später User-IDs auf Gruppen-IDs migriert werden.
Auswahl und Dokumentation des OAuth Flow
- User basierte Autorisierung entspricht dem Authorization Code Flow. Hier holt sich der Client zu Laufzeit eine Autorisierung durch den Nutzer. Müsste daher durch die Client Entwickler implementiert werden. Hier stellen sich auch noch viele Fragen an die Ausgestaltung.
- Refresh Token Flow wäre der inhaltlich passendste Flow, aber ist durch die OpenAPI nicht abgedeckt und müsste durch RapiDoc durch Extensions/Sonderlösungen in der Spec abgebildet werden (geht laut Doku). Zudem müssten Client Entwickler die Nutzung eines Refresh Token implementieren.
- Laut OAuth Spec ginge eventuell auch eine Autorisierung im aktuell genutzten Client Credentials Flow, sodass ohne Refresh Token im Access Token im Sub Claim der User steht: "The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to the protected resources under its control, or those of another resource owner that have been previously arranged with the authorization server (the method of which is beyond the scope of this specification)." --> Es ist aber unklar, ob es sich über den Connect2ID abbilden lässt und ob es Unklarheiten / Probleme in der Implementierung sorgt, da man sich abseits des definierten Standards bewegt.
Aktuell gehen die Architekturbeschreibungen vom Refresh Token Flow aus.
Akzeptanzkriterien
-
Externe API-Clients sollten alle Operationen der Submission-API nutzen können, die das SSP für die Destination Verwaltung nutzt. In diesem Sinn ist die "SSP ist eine Referenzimplementierung der API Nutzung für die Destinationverwaltung". -
Bei Destinationerstellung ist immer sichergestellt, dass diese Destination einem User zugeordnet wurde. -
Es liegt ein Konzept vor, die notwendigen Datenbankmigrationen vom SSP zum Zustelldienst im Kontext des Releases zuverlässig durchzuführen und den Betrieb nicht übermäßig zu unterbrechen. -
Major oder Breaking Changes an der Submission-API sollen vermieden werden. Bestehende Client Implementierungen müssen weiterhin funktionieren. -
Ein passender Flow und Scopes wurden definiert. Nutzung des Flow und der Scopes wurde ausreichend dokumentiert, sodass externe Entwickler die OAuth Umsetzung verstehen. (Siehe offene Frage zu Flows) -
Änderungen an Endpunkten wurden in der Spec und Docusaurus Doku dokumentiert. -
Es wurde geprüft, ob Endpunkte zum Verwalten von Destinations (in der aktuellen Submission API 1.2. im Bereich "Internal") in eine separate Spec (Teamvorschlag: "Destination API" bzw. "Destination Management API") verlagert werden. Bei positiven Ergebnis wurde eine separate Spec erstellt und in der Submission API die betroffenen Endpunkte als deprecated gekennzeichnet. Fachlicher Hintergrund: Entwickler von Clients, die Submissions versenden bzw. empfangen, entwickeln nicht unbedingt Clients zum Verwalten von Destination bzw. entwickeln für beide Anwendungsfälle ein einheitliche Software. Daher würden separate API Specs eine präzisiere und unabhängige Versionierung ermöglichen, da "Breaking" Änderungen an Endpunkten für der Verwaltung von Destinations nicht unbedingt relevant für den Versand bzw. Empfang Submission bezogene Endpunkte sind. Zusätzlich würde eine neue Spec mehr Freiheitsgrade in der Gestaltung ermöglich, da es ein neuer Contract wäre. -
Issue https://git.fitko.de/fit-connect/planning/-/issues/478 wurde mitbedacht
Durchführungsplan (vom Entwickler bei der Storyplanung auszufüllen)
- [Hier Plan einfügen]