Seiteninhalt:
Der TI-Flow-Fachdienst ist ein Dienst im Internet. Jeder Zugriff auf den Resource Server läuft über einen ZETA Guard, der aus zwei Komponenten besteht:
Für Entwickler sind zwei Protokollphasen klar zu unterscheiden:
POST /token)POST /token)Bevor ein Client Tokens anfragen kann, muss er einmalig pro ZETA Guard-Instanz registriert werden. Die Registrierung liefert eine client_id.
POST /register
Content-Type: application/json
{
"client_name": "MeinPVS",
"grant_types": ["urn:ietf:params:oauth:grant-type:token-exchange"],
"token_endpoint_auth_method": "private_key_jwt",
"jwks": { ... } // Client Instance Public Key
}
Die client_id wird anschließend in allen client_assertion-JWTs als iss und sub verwendet.
Wird für neue Sessions verwendet, wenn noch kein gültiges Refresh Token vorliegt. Typisch für stationäre Clients (PVS, Krankenhaussystem) mit SM(C)-B.
Ablauf:
GET /nonceattestation_challenge = SHA-256( SHA-256(Client_Instance_Public_Key_JWK) ‖ nonce )
attestation_challenge, signiert mit dem TPM Attestation Keysubject_token – ein JWT, das vom Konnektor mit der SM(C)-B signiert wird und die professionOID der Institution enthältclient_assertion – ein JWT, signiert mit dem Client Instance Key, das die TPM-Attestierung enthältToken Request:
POST /token
Content-Type: application/x-www-form-urlencoded
DPoP: <dpop-proof-jwt>
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange
&subject_token=<smcb-signed-jwt>
&subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Ajwt
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=<client-assertion-jwt>
&scope=tif-rx-task-prescribe%20tif-diga-task-prescribe
client_assertion-JWT Payload (Pfad A – mit TPM-Attestierung):
{
"iss": "<client_id>",
"sub": "<client_id>",
"aud": "<token_endpoint_url>",
"exp": 1234567890,
"jti": "<unique-id>",
"urn:gematik:params:oauth:client-attestation:tpm2": {
"attestation_data": "<Base64(client_statement)>",
"client_statement_format": "client-statement"
}
}
Sobald ein Refresh Token vorhanden ist, kann damit ohne erneute SM(C)-B-Interaktion ein neues AT geholt werden. Das RT ist 12 Stunden gültig – innerhalb dieses Zeitraums ist keine Neuattestation nötig.
POST /token
Content-Type: application/x-www-form-urlencoded
DPoP: <dpop-proof-jwt>
grant_type=refresh_token
&refresh_token=<refresh-token>
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=<client-assertion-jwt-ohne-attestierung>
&scope=tif-rx-task-prescribe%20tif-diga-task-prescribe
Hinweis: Der
scope-Parameter im Refresh-Request darf nur Scopes enthalten, die bereits im ursprünglichen AT enthalten waren.
Die Policy Engine prüft bei jedem /token-Request vier Bedingungen – alle müssen erfüllt sein:
| Prüfung | Quelle | Bedingung |
|---|---|---|
| Berufsgruppe / Institution | professionOID aus dem subject_token |
Muss in den erlaubten roles des angefragten Scopes stehen |
| Client-Zulassung | product_id + product_version aus dem ZETA-Client |
Muss in der gematik-Zulassungsliste registriert sein |
| Scopes | scope-Parameter im Request |
Alle angefragten Scopes müssen für die professionOID erlaubt sein |
| Audience | resource-Parameter (oder aus Scope abgeleitet) |
Muss zu einem erlaubten Resource Server des Scopes passen |
Schlägt eine Prüfung fehl, liefert der PDP einen Fehler mit konkretem Grund (z.B. "User profession is not allowed", "One or more requested scopes are not allowed").
Ein PVS oder Krankenhaussystem sollte in Pfad A immer alle Scopes anfragen, die es für seinen Betrieb benötigt – in einem einzigen Token Request.
Begründung:
Typische Scope-Kombination für eine Arztpraxis (PVS):
scope=tif-rx-task-prescribe tif-diga-task-prescribe
Typische Scope-Kombination für eine Apotheke:
scope=tif-rx-task-dispense tif-rx-communication tif-rx-chargeitem-provide tif-rx-subscription
Typische Scope-Kombination für eine FdV (Versicherter):
scope=tif-rx-task-manage tif-rx-communication tif-rx-chargeitem-manage tif-rx-consent-manage tif-rx-eu-access-manage tif-rx-audit tif-rx-notification tif-diga-task-manage tif-diga-communication tif-diga-audit
| Token | TTL |
|---|---|
| Access Token (AT) | 300 Sekunden (5 Minuten) |
| Refresh Token (RT) | 43.200 Sekunden (12 Stunden) |
Der PEP ist ein HTTP-Proxy, der vor dem TI-Flow-Fachdienst Resource Server sitzt. Jeder API-Call muss ein gültiges AT tragen.
Request-Format:
GET /rx/Task
Authorization: DPoP <access-token>
DPoP: <dpop-proof-jwt>
Der PEP prüft bei jedem Request folgende Bedingungen (gemäß §A_25668 gemSpec_ZETA):
exp-Claim des AT muss in der Zukunft liegenaud-Claim im AT muss zur URL des aufgerufenen Resource Backends passenscope-Claim im AT muss die angefragte HTTP-Methode + Pfad-Kombination abdeckencnf-Claim im AT passen (Proof of Possession)Alle fünf Prüfungen müssen bestanden werden. Schlägt eine fehl, wird der Request mit 401 Unauthorized abgewiesen.
Fehlt im AT ein benötigter Scope oder passt die Audience nicht zur aufgerufenen URL, signalisiert der PEP einen Step-up (§A_28525):
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="insufficient_scope",
scope="tif-rx-task-prescribe",
resource="<resource-url>"
Der Client muss daraufhin beim PDP ein neues AT mit dem fehlenden Scope anfragen. Falls der Scope noch nie im bisherigen AT enthalten war, ist Pfad A (neue Session mit Attestierung) erforderlich.
| Akteur | OID-Referenz | OID | Erlaubte Scopes |
|---|---|---|---|
| Betriebsstätte Arzt | oid_praxis_arzt |
1.2.276.0.76.4.50 |
|
| Zahnarztpraxis | oid_zahnarztpraxis |
1.2.276.0.76.4.51 |
|
| Betriebsstätte Psychotherapeut | oid_praxis_psychotherapeut |
1.2.276.0.76.4.52 |
|
| Krankenhaus | oid_krankenhaus |
1.2.276.0.76.4.53 |
|
| Institution Vorsorge / Reha | oid_institution-vorsorge-reha |
1.2.276.0.76.4.257 |
|
| Öffentliche Apotheke | oid_oeffentliche_apotheke |
1.2.276.0.76.4.54 |
|
| Krankenhausapotheke | oid_krankenhausapotheke |
1.2.276.0.76.4.55 |
|
| Kostenträger | oid_kostentraeger |
1.2.276.0.76.4.59 |
|
| Versicherter (FdV) | oid_versicherter |
1.2.276.0.76.4.49 |
|
| NCPeH-Fachdienst | oid_ncpeh |
1.2.276.0.76.4.292 |
|
| Betriebsstätte gematik | oid_bs_gematik |
1.2.276.0.76.4.58 |
|
policies:
# ── Arzneimittel ─────────────────────────────────────────────────────────────
"tif-rx-task-prescribe":
description: "E-Rezept verordnen"
roles:
- { oid: "1.2.276.0.76.4.50", description: "oid_praxis_arzt" }
- { oid: "1.2.276.0.76.4.51", description: "oid_zahnarztpraxis" }
- { oid: "1.2.276.0.76.4.52", description: "oid_praxis_psychotherapeut" }
- { oid: "1.2.276.0.76.4.53", description: "oid_krankenhaus" }
- { oid: "1.2.276.0.76.4.56", description: "oid_institution-vorsorge-reha" }
rules:
- { method: POST, path: "rx/Task/$create" }
- { method: POST, path: "rx/Task/{id}/$activate" }
- { method: POST, path: "rx/Task/{id}/$abort" }
"tif-rx-task-dispense":
description: "E-Rezept einlösen"
roles:
- { oid: "1.2.276.0.76.4.54", description: "oid_oeffentliche_apotheke" }
- { oid: "1.2.276.0.76.4.55", description: "oid_krankenhausapotheke" }
rules:
- { method: POST, path: "rx/Task/$accept" }
- { method: POST, path: "rx/Task/{id}/$reject" }
- { method: POST, path: "rx/Task/{id}/$close" }
- { method: POST, path: "rx/Task/{id}/$dispense" }
- { method: POST, path: "rx/Task/{id}/$abort" }
- { method: GET, path: "rx/Task/" }
- { method: GET, path: "rx/Task/{id}" }
"tif-rx-task-manage":
description: "E-Rezepte verwalten"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "rx/Task/" }
- { method: GET, path: "rx/Task/{id}" }
- { method: POST, path: "rx/Task/{id}/$abort" }
- { method: PATCH, path: "rx/Task/{id}" }
- { method: GET, path: "rx/medicationdispense/" }
- { method: GET, path: "rx/medicationdispense/{id}" }
"tif-rx-task-ePeDA":
description: "E-Rezepte in EU einlösen"
roles:
- { oid: "1.2.276.0.76.4.292", description: "oid_ncpeh" }
rules:
- { method: POST, path: "rx/$get-eu-prescriptions" }
- { method: POST, path: "rx/Task/{id}/$eu-close" }
"tif-rx-communication":
description: "Nachrichten zu E-Rezepten zwischen Versichertem und Apotheke"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
- { oid: "1.2.276.0.76.4.54", description: "oid_oeffentliche_apotheke" }
- { oid: "1.2.276.0.76.4.55", description: "oid_krankenhausapotheke" }
rules:
- { method: POST, path: "/rx/Communication" }
- { method: GET, path: "/rx/Communication" }
- { method: GET, path: "/rx/Communication/{id}" }
- { method: DELETE, path: "/rx/Communication/{id}" }
"tif-rx-chargeitem-manage":
description: "Abrechnungsinformationen verwalten"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "rx/ChargeItem/" }
- { method: GET, path: "rx/ChargeItem/{id}" }
- { method: PATCH, path: "rx/ChargeItem/{id}" }
- { method: DELETE, path: "rx/ChargeItem/{id}" }
"tif-rx-chargeitem-provide":
description: "Abrechnungsinformationen bereitstellen"
roles:
- { oid: "1.2.276.0.76.4.54", description: "oid_oeffentliche_apotheke" }
- { oid: "1.2.276.0.76.4.55", description: "oid_krankenhausapotheke" }
rules:
- { method: GET, path: "rx/ChargeItem/{id}" }
- { method: POST, path: "rx/ChargeItem" }
- { method: PUT, path: "rx/ChargeItem/{id}" }
"tif-rx-consent-manage":
description: "Einwilligung verwalten"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "rx/Consent/" }
- { method: POST, path: "rx/Consent/" }
- { method: DELETE, path: "rx/Consent/" }
"tif-rx-eu-access-manage":
description: "EU-Berechtigung verwalten"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "rx/$read-eu-access-permission" }
- { method: POST, path: "rx/$grant-eu-access-permission" }
- { method: DELETE, path: "rx/$revoke-eu-access-permission" }
"tif-rx-audit":
description: "Zugriffsprotokoll abrufen"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "rx/AuditEvent" }
- { method: GET, path: "rx/AuditEvent/{id}" }
"tif-rx-notification":
description: "App Notification verwalten"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "rx/pushers" }
- { method: POST, path: "rx/pushers/set" }
- { method: GET, path: "rx/channels" }
- { method: POST, path: "rx/channels/{pushkey}" }
"tif-rx-subscription":
description: "Benachrichtigungen registrieren"
roles:
- { oid: "1.2.276.0.76.4.54", description: "oid_oeffentliche_apotheke" }
- { oid: "1.2.276.0.76.4.55", description: "oid_krankenhausapotheke" }
rules:
- { method: POST, path: "rx/Subscription" }
"tif-rx-task-probe":
description: "Probing E-Rezept"
roles:
- { oid: "1.2.276.0.76.4.58", description: "oid_bs_gematik" }
rules:
- { method: POST, path: "rx/Task/$create" }
# ── DiGA Verordnung ────────────────────────────────────────────────────────
"tif-diga-task-prescribe":
description: "DiGA Verordnung verordnen"
roles:
- { oid: "1.2.276.0.76.4.50", description: "oid_praxis_arzt" }
- { oid: "1.2.276.0.76.4.51", description: "oid_zahnarztpraxis" }
- { oid: "1.2.276.0.76.4.52", description: "oid_praxis_psychotherapeut" }
- { oid: "1.2.276.0.76.4.53", description: "oid_krankenhaus" }
- { oid: "1.2.276.0.76.4.56", description: "oid_institution-vorsorge-reha" }
rules:
- { method: POST, path: "diga/Task/$create" }
- { method: POST, path: "diga/Task/{id}/$activate" }
- { method: POST, path: "diga/Task/{id}/$abort" }
"tif-diga-task-dispense":
description: "DiGA Verordnung einlösen"
roles:
- { oid: "1.2.276.0.76.4.59", description: "oid_kostentraeger" }
rules:
- { method: POST, path: "diga/Task/$accept" }
- { method: POST, path: "diga/Task/{id}/$reject" }
- { method: POST, path: "diga/Task/{id}/$close" }
- { method: GET, path: "diga/Task/{id}" }
"tif-diga-task-manage":
description: "DiGA Verordnungen verwalten"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "diga/Task/" }
- { method: GET, path: "diga/Task/{id}" }
- { method: POST, path: "diga/Task/{id}/$abort" }
- { method: GET, path: "diga/medicationdispense/" }
- { method: GET, path: "diga/medicationdispense/{id}" }
"tif-diga-communication":
description: "Nachrichten zu DiGA-Verordnungen zwischen Versichertem und Kostenträger"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
- { oid: "1.2.276.0.76.4.59", description: "oid_kostentraeger" }
rules:
- { method: POST, path: "/diga/Communication" }
- { method: GET, path: "/diga/Communication" }
- { method: GET, path: "/diga/Communication/{id}" }
- { method: DELETE, path: "/diga/Communication/{id}" }
"tif-diga-audit":
description: "Zugriffsprotokoll abrufen"
roles:
- { oid: "1.2.276.0.76.4.49", description: "oid_versicherter" }
rules:
- { method: GET, path: "diga/AuditEvent" }
- { method: GET, path: "diga/AuditEvent/{id}" }
"tif-diga-subscription":
description: "Benachrichtigungen registrieren"
roles:
- { oid: "1.2.276.0.76.4.59", description: "oid_kostentraeger" }
rules:
- { method: POST, path: "diga/Subscription" }
"tif-diga-task-probe":
description: "Probing DiGA"
roles:
- { oid: "1.2.276.0.76.4.58", description: "oid_bs_gematik" }
rules:
- { method: POST, path: "diga/Task/$create" }
{
"access_token_ttl": 300,
"refresh_token_ttl": 43200,
"allowed_scopes": [
"tif-rx-task-prescribe",
"tif-rx-task-dispense",
"tif-rx-task-manage",
"tif-rx-task-ePeDA",
"tif-rx-communication",
"tif-rx-chargeitem-manage",
"tif-rx-chargeitem-provide",
"tif-rx-consent-manage",
"tif-rx-eu-access-manage",
"tif-rx-audit",
"tif-rx-notification",
"tif-rx-subscription",
"tif-rx-task-probe",
"tif-diga-task-prescribe",
"tif-diga-task-dispense",
"tif-diga-task-manage",
"tif-diga-communication",
"tif-diga-audit",
"tif-diga-subscription",
"tif-diga-task-probe"
]
}