Konzept
Versicherte können sich über das mobile FdV mittels Push-Notifications über Ereignisse in Fachdiensten (z.B. ePA-Aktensystem, E-Rezept-Fachdienst, Dienste der Kassen) informieren lassen. Der Versicherte kann im FdV aus den möglichen Ereignissen (zum Beispiel in Form von Channels) diejenigen auswählen, für die er benachrichtigt werden möchte. Standardmäßig werden keine Push-Notifications gesendet.
Architektur
An der Umsetzung des Notification Managements sind folgende Komponenten und Services beteiligt:
Der Zweck dieses Konzepts besteht darin, eine flexible und sichere Push Infrastruktur bereitzustellen, die es ermöglicht, dass verschiedene Fachdienste Push-Notifications an eine mobile Anwendung senden können. Durch die Implementierung eines zentralen Push Gateways pro Frontend wird eine einheitliche Schnittstelle geschaffen, die als Fassade für die plattformspezifischen APIs von Anbietern wie Google und Apple fungiert. Dies erlaubt es mehreren Backends, gleichzeitig Push-Benachrichtigungen für eine fremde App bereitzustellen, ohne dass jedes Backend individuell mit den plattformspezifischen APIs interagieren muss. Ein wesentlicher Vorteil dieses Ansatzes ist die erhöhte Sicherheit: Die sensiblen Zugangsdaten und Schlüssel, die für die Nutzung der plattformspezifischen Push-APIs erforderlich sind, verbleiben beim Push Gateway und müssen nicht mit den einzelnen Fachdiensten geteilt werden. Dadurch wird das Risiko eines unbefugten Zugriffs auf diese Geheimnisse minimiert und die Integrität der Kommunikation gewährleistet. Als Vorbild dient die Push Implementierung wie sie im Matrix Protokoll beschrieben ist.
Um zusätzliche Sicherheit zu gewährleisten kann eine Push-Nachricht zwischen dem Fachdienst und dem FdV verschlüsselt werden. Weder Push Gateway noch Push Provider besitzen die Information um eine Entschlüsselung vorzunehmen. Die Entscheidung ob eine Push-Nachricht verschlüsselt werden muss oder unverschlüsselt bleiben kann wird durch die Spezifikation des jeweiligen Fachdienstes vorgenommen. Bisher wird davon ausgegangen, dass eine Verschlüsselung für ePA und E-Rezept notwending sein wird, diese jedoch bei TIM optional ist.
Fachdienst
Der anwendungsspezifische Fachdienst verwaltet Geräte die sich bei ihm für den Push-Notification empfang registriert haben. Der Fachdienst erstellt Push-Notifications für vom Nutzer abonnierte Ereignisse und übermittelt diese an das zuständige Push Gateway. Er bietet Schnittstellen für die FdVs der Versicherten zur Registrierung und Konfiguration von Pushern an. Ein Pusher bezieht sich auf eine FdV-Instanz und ist eine Konfiguration im Fachdienst, in der die Informationen zur Adressierung der Push-Notifications hinterlegt werden (u.a. das zu nutzende Push Gateway, Schlüssel zur Verschlüsselung von Nachrichteninhalten). Der Versicherte kann für mehrere Endgeräte Pusher im Fachdienst hinterlegen.
Push Gateway
Das Push Gateway besitzt einen anwendungsübergreifenden Endpunkt, an den Push-Notifications übermittelt werden. Das Push Gateway leitet die Informationen der Push-Notification an den Push Provider weiter. Es wird vom Hersteller des FdV bereitgestellt, und es kann weitere Endpunkte für Kassendienste geben, die ebenfalls über dieses Push Gateway Notifications versenden.
Push Provider
Der Push Provider ist ein Service des Herstellers des mobilen Betriebssystems (z.B. Google, Apple). Der Push Provider sendet Notifications an App-Instanzen auf Endgeräten der Nutzer.
FdV Instanz
Die FdV-Instanz ist ein auf einem mobilen Endgerät installiertes FdV. Push-Notifications werden für eine FdV-Instanz registriert und an diese gesendet. Die FdV-Instanz kann mehrere Anwendungen integrieren (ePA, E-Rezept, TI-Messenger, Kassenanwendungen), für die der Versicherte jeweils Push-Notifications auswählen kann.
Authentisierung
Die Verbindungen zwischen Push Gateway und den Fachdiensten sind beidseitig authentisiert und verschlüsselt. Die anderen sind Fachdienst oder Push-Provider spezifisch.
Verschlüsselung des Benachrichtigungsinhaltes
Push-Gateways können verschlüsselten und unverschlüsselte Push-Nachrichten empfangen und weiterleiten. Die Verschlüsselung des Benachrichtigungsinhaltes ist fachdienstspezifisch und wird durch die Spezifikation des Fachdienstes festgelegt.
Im Fall von Verschlüsselten Push-Nachrichten wird der Benachrichtigungsinhalt einer jeden Benachrichtigung mittels eines Authenticated-Encryption-Verfahrens verschlüsselt (AES/GCM), sodass der Inhalt der Benachrichtigung nicht von Dritten eingesehen oder verändert werden kann.
Wenn sich eine FdV-Instanz beim Fachdienst für Benachrichtigungen registriert, erzeugt die App ein initiales gemeinsames Geheimnis (initial-shared-secret
(ISS
)) und überträgt dieses kryptographisch gesichert an den Fachdienst. Registriert sich das FdV an verschieden Fachdiensten, so wird für jeden Fachdienst ein eigenes ISS
erzeugt.
Dieses gemeinsame Geheimnis ist die Grundlage der kryptographischen Sicherung des Benachrichtigungsinhaltes. Die Benachrichtigung wird vom Fachdienst mit verschlüsseltem Benachrichtigungsinhalt über das Push Gateway und den Push Provider an die FdV-Instanz übermittelt.
Ganz ähnlich wie bei vielen Messaging-Anwendungen werden die verwendeten Schlüssel für die kryptographische Absicherung der Nachrichten regelmäßig gewechselt auf eine Weise, dass eine Wiederherstellbarkeit von alten Schlüsseln kryptographisch ausgeschlossen ist.
Der Fachdienst erhält ein ISS und einen Zeitstempel von dessen Erzeugung von dem FdV bei der Registrierung. Mittels einer "Hashed Message Authentication Code (HMAC)-based key derivation function" (HKDF) [RFC-5869] werden per HKDF(ISS, info="<Jahr>-<Monat>")
zwei Werte abgeleitet:
-
Ein Geheimnis für den Monat und Jahr des Zeitstempels (
shared-secret-Jahr-Monat
) -
ein AES/GCM-Schlüssel für den Monat und Jahr des Zeitstempels (
AES/GCM-Schlüssel-Jahr-Monat
).
Diese beiden Werte werden im Fachdienst sicher gespeichert und das ISS
wird im Fachdienst gelöscht.
Beispiel für einen Austausch im Oktober 2023:
Das ISS sei zufällig erzeugt gleich (hexdump) f2ca1bb6c7e907d06dafe4687e579fce76b37e4e93b7605022da52e6ccc26fd2
. Dann ergibt HKDF(ISS, info="2023-10", L=64) = (hexdump) 185fed66ea5cabbe00147bbd298b5dab0ed41b57ab254d35897b3a4504306e3b3b4adcd58dea98db8e9cb0f5763fcd04fe932d67926cc04b20ba2a2f304ffff9
. Die ersten 32 Byte (256 Bit) sind das shared-secret-2023-10
gleich (hexdump) 185fed66ea5cabbe00147bbd298b5dab0ed41b57ab254d35897b3a4504306e3b
und die letzten 32 Byte sind der AES/GCM-Schlüssel-2023-10
ist gleich (hexdump) 3b4adcd58dea98db8e9cb0f5763fcd04fe932d67926cc04b20ba2a2f304ffff9
.
Soll im Oktober 2023 eine Benachrichtigung kryptographisch gesichert werden, um sie an das E-Rezept-FdV zu versenden, dann wird der Schlüssel AES/GCM-Key-2023-10
dafür verwendet. Soll im November 2023 eine Benachrichtigung gesichert werden, so muss per HKDF(shared-secret-2023-10, info="2023-11")
wieder ein Geheimnis — diesmal für November 2023 — und ein neuer AES/GCM-Schlüssel abgeleitet werden. shared-secret-2023-11 = (hexdump) 0c8662d90b04818afb317406fe7fcfcf8d103cd9bc6ad7847890d28620e85ec3
, AES/GCM-Schlüssel-2023-11 = (hexdump) 39aa5dacd538f53f4b956d84c9b8f2e26933274d160b9fd1a263a27681c6331b
Alle shared-secret-Jahr-Monat
und alle AES/GCM-Schlüssel-Jahr-Monat, die älter sind als zwei Monate werden, sowohl im Notification Service als auch im E-Rezept-FdV gelöscht, jedoch niemals das jüngste noch verfügbare (auch wenn es älter als zwei Monate ist). Der fachliche Hintergrund von "zwei Monaten" ist, dass sichergestellt sein muss, dass falls der E-Rezept-FD die Benachrichtigung Sekunden vor Monatsende erstellt, und diese im E-Rezept-FdV erst nach einigen Sekunden dann im Folgemonat empfangen werden, die Entschlüsselung im E-Rezept-FdV immer noch möglich sein muss.
Sollte erst im Januar 2024 die nächste Benachrichtigung gesendet werden, so muss die Ableitung für 2023-12
erzeugt werden und darauf basierend anschließend die Ableitung für 2024-01
. Anschließend werden die Ableitungs- und Schlüsseldaten für 2023-11
gelöscht. Die Schlüsseldaten für 2024-01
werden für die kryptographische Sicherung verwendet.
Somit erreicht man das Ziel, dass bei Kompromittierung eines AES/GCM-Jahr-Monat-Schlüssels
nur die Benachrichtigungen der letzten zwei Monate entschlüsselt werden können.
Registrierung einer ePA-FdV-Instanz
Damit eine FdV-Instanz Push-Notifications empfangen kann, muss diese zunächst beim Push-Provider sowie in den gewünschten Fachdiensten registriert werden.
-
Die FdV-Instanz registriert sich beim Push Provider und erhält ein pushkey, das die FdV-Instanz eindeutig identifiziert.
-
Die FdV-Instanz erzeugt ein
initial_shared_secret
und speichert den Zeitpunkt (<Jahr>-<Monat>
) zu welchem dieses erzeugt wurde alstime_iss_created
. -
Der Nutzer meldet sich beim Fachdienst (z.B. Aktensystem) an und registriert einen Pusher. Teil der Registrierungsdaten sind:
-
der
pushkey
, -
die
app_id
, -
die Art des
Pushers
(kind
, hier immer"http"
), -
die Adresse des Push Gateways (
data.url
) -
das
initial_shared_secret
-
time_iss_created
Die genauen Felder und Erklärungen dazu sind in der OpenAPI-Spezifikation zu finden. Dieapp_id
und die Adresse des Push Gateways wurden vom Hersteller im FdV hinterlegt.
-
-
Die FdV-Instanz und der Fachdienst erzeugen den ersten Schlüssel aus dem
initial_shared_secret
und demtime_iss_created
. Anschließend löschen sie dasinitial_shared_secret
.
Möchte der Versicherte Push Notifications von mehreren Fachdiensten erhalten, wird durch die FdV-Instanz in jedem dieser Fachdienste ein Pusher registriert.
{ "lang": "en", "kind": "http", "app_display_name": "Mat Rix", "device_display_name": "iPhone 9", "app_id": "com.example.app.ios", "pushkey": "<APNS/GCM TOKEN>", "data": { "url": "https://push-gateway.location.here/_matrix/push/v1/notify" }, "append": false }
Deregistrierung einer FdV-Instanz
Der gleiche Endpunkt wird sowohl zur Deregistrierung als auch zur Registrierung bei einer FdV-Instanz verwendet. Bei der Deregistrierung werden nur das pushkey
, die app_id
und kind
(die Art des Pushers benötigt). Die Art des Pushers muss dann null sein, damit der Fachdienst weiß, dass der Pusher gelöscht werden soll.
Liste aktuelle Pushers enthalten
Die FdV-Instanz kann eine Liste aller registrierten Pusher des Nutzers durch eine GET Operation auf dem bestimmten Endpunkt des Fachdienstes erhalten. Die Details dazu sind in der OpenAPI-Spezifikation beschrieben.
Versenden von Push-Notifications
Die folgende Abbildung veranschaulicht den Ablauf, wenn ein Ereignis in einem Fachdienst eintritt, für welches Push-Benachrichtigungen gesendet werden sollen (z.B. wenn ein Nutzer ein neues Dokument in einem Konto des ePA-Aktensystems einstellt):
-
Der Fachdienst führt folgende Schritte durch
-
Erzeugen des Nachrichteninhalts für dieses spezifische Ereignis. Die Strukturierung ist fachdienstspezifisch.
-
Erzeugen eines neuen gültigen Schlüssels, wenn kein gültiger vorhanden ist.
-
-
Für jeden registrierten Pusher
p
, der für das Ereignis abonniert ist, wird eine Push-BenachrichtigungNotification_p
mit mindestens folgenden Inhalten erzeugt (Die möglichen Felder und deren Beschreibungen sind auf der OpenAPI-Seite zu finden):-
ciphertext
= Nachrichteninhalt aus 1a,Base64(IV || Chiffrat || Authentication Tag)
verschlüsselt mit dem aktuell gültigen Schlüssel. -
time_message_encrypted
= Zeitpunkt der Verschlüsselung des Nachrichteinhaltes. -
devices
= (mindestens: app_id, push_token)
-
-
Für jeden Pusher p wird die Push-Benachrichtigung
Notification_p
an das Push Gateways des Pushersp
übermittelt. -
Das Push Gateway übermittelt die Push-Benachrichtigung
Notification_p
an den Push Provider. -
Der Push-Provider sendet die Notification an die zur
push_token
gehörende FdV-Instanz. -
Die FdV-Instanz entschlüsselt den Nachrichteninhalt mit dem aktuell gültigen Schlüssel (erzeugt ihn, wenn er nicht schon vorhanden ist) und zeigt dem Nutzer den Nachrichteninhalt entsprechend an.
-
Bei Bedarf kann sich der Nutzer in der FdV-Instanz anmelden, um sich beispielsweise ein eingestelltes Dokument anzusehen.
Versenden aus Push Gateway Sicht
Apple
HTTP-Header |
Wert |
Beschreibung |
|
|
|
|
|
|
authorization |
|
Required for token-based authentication |
apns-push-type |
|
|
apns-id |
||
apns-expiration |
||
apns-priority |
|
|
apns-topic |
||
apns-collapse-id |
Themen für produktspezifische Implementierungen
Die folgenden Themen sind in diesem Dokument nicht enthalten, da sie zu stark von der produktspezifischen Implementierung abhängen:
-
Lokalisierung: Die genaue Implementierung der Lokalisierung ist stark abhängig vom Payload und damit vom spezifischen Anwendungsfall.
-
Channels: Die Anforderungen und Implementierung von Channels sind anwendungsspezifisch und können je nach Produkt variieren.
-
Payload: Die genaue Struktur und der Inhalt der Nutzdaten können je nach Anwendungsfall und Produktfunktionalität unterschiedlich sein. Die Struktur wird im Fachkonzept der jeweiligen Anwendung spezifiziert.
-
Implementierung des Push Gateways: Die technische Umsetzung des Push-Mechanismus kann von der gewählten Infrastruktur und den spezifischen Anforderungen des Push Gateways abhängen. Die Technologie entwickelt sich schnell weiter, was auch die Kommunikation zwischen Push Gateway und Push Providers beeinflusst.
-
Berechtigung: Die Berechtigungen für die verschiedenen Endpunkte sind anwendungsfallspezifisch und können je nach Produkt variieren.
Für Hinweise zur Implementierung dieser Themen verweisen wir auf die produktspezifischen Spezifikationen und Implementierungsleitfäden.
Optionale Features können hier gefunden werden.
Beispiele
Device Registrierung
app_id
{
"lang": "en",
"kind": "http",
"app_display_name": "Mat Rix",
"device_display_name": "iPhone 9",
"app_id": "com.example.app.ios",
"pushkey": "<APNS/GCM TOKEN>",
"data": {
"url": "https://push-gateway.location.here/_matrix/push/v1/notify"
},
"append": false
}
data
{
"lang": "en",
"kind": "http",
"app_display_name": "Mat Rix",
"device_display_name": "iPhone 9",
"app_id": "com.example.app",
"pushkey": "<APNS/GCM TOKEN>",
"data": {
"url": "https://push-gateway.location.here/_matrix/push/v1/notify",
"platform": "ios"
},
"append": false
}
url
{
"lang": "en",
"kind": "http",
"app_display_name": "Mat Rix",
"device_display_name": "iPhone 9",
"app_id": "com.example.app",
"pushkey": "<APNS/GCM TOKEN>",
"data": {
"url": "https://push-gateway.location.here/ios/_matrix/push/v1/notify"
},
"append": false
}
Event-Trigger
Beispiel für ein Event-Trigger in ePA:
function trigger001() {
user = getUser()
devices = getDevices(user)
channel = getChannel(trigger001)
for device in devices {
if device.channels[channel].isSubscribed {
notification = createNotification(trigger001, device)
sendNotification(notification, channel)
}
}
}
function createNotification(trigger, device) {
month = date.now().month // "2024-11"
encryptionKey = getEncryptionKey(device, month)
payload = {
event: "trigger001"
}
iv = random(32)
(cipher, authTag) = aesEncrypt(payload)
ciphertext = Base64(iv + cipher + authTag)
return {
month: month,
ciphertext: ciphertext,
devices: [
app_id: device.app_id,
pushkey: device.pushkey,
pushkey_ts: device.pushkey_ts,
data: device.data,
tweaks: {}
]
}
}
Push Gateway
Endpoint: http://localhost:8080/push/v1/notify
IN
{
"month": "2024-11",
"ciphertext": "asdfdfjksfjklsdljkdsf==",
"prio": "high",
"counts": {},
"devices": [
{
"app_id": "de.gematikkk.app.ios",
"pushkey": "abcd-efghi-jklm-nopq",
"pushkey_ts": 0,
"data": {
"format": "string"
},
"tweaks": {
}
}
]
}
OUT
APNS (Apple Push Notification Service)
HTTP-Header |
Wert |
Beschreibung |
|
|
|
|
|
|
authorization |
|
Required for token-based authentication |
apns-push-type |
|
|
apns-priority |
|
Payload:
{
"aps": {
"mutable-content": true
}
"ciphertext": notification.ciphertext,
"month": notification.month
}
if notification.counts.badge then
payload.aps.badge = notification.counts.badge
end if
FCM (Firebase Cloud Messaging)
HTTP-Header |
Wert |
Beschreibung |
|
|
|
|
|
Defines the format of the request |
|
|
Confirms token-based authentication (optional, specific to certain systems) |
authorization |
|
Required for token-based authentication. |
Payload:
{
"message":{
"token":"PUSH_KEY",
"android": {
"priority": "HIGH",
}
"data":{
"ciphertext": "ENCRYPTED_DATA_HERE",
"month": notification.month
}
}
}
Mobile App
iOS-Extension:
func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
// Retrieve the push notification payload
let payload = request.content.userInfo
// Decrypt the ciphertext
let ciphertext = payload["ciphertext"]
let plaintext = decrypt(ciphertext)
// Update the notification content
let content = request.content.mutableCopy() as! UNMutableNotificationContent
let title = LocalizedString("notification_title_\(event_id)")
let body = LocalizedString("notification_body_\(event_id)")
content.title = title
content.body = body
// Call the completion handler with the updated notification content
contentHandler(content)
}
Android:
fun onMessageReceived(
request: RemoteMessage
) {
// Retrieve the push notification payload
val payload = request.data
// Decrypt the ciphertext
val ciphertext = payload["ciphertext"]
val plaintext = decrypt(ciphertext)
// Update the notification content
val eventId = payload["event_id"]
val title = resources.getString(resources.getIdentifier("notification_title_$eventId", "string", packageName))
val body = resources.getString(resources.getIdentifier("notification_body_$eventId", "string", packageName))
// Display the notification using the processed title and body
showNotification(title, body)
}
fun showNotification(title: String?, body: String?) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationId = 1
// Create a notification channel for Android O (API 26) and above
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"default_channel",
"Default Channel",
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(channel)
}
// Build the notification using NotificationCompat for backward compatibility
val notification = NotificationCompat.Builder(this, "default_channel")
.setContentTitle(title)
.setContentText(body)
.build()
// Display the notification with a unique notification ID
notificationManager.notify(notificationId, notification)
}
Sync: 22.11.2024 14:56