From 89a267c54398f527a599a3a2134922849912e9d4 Mon Sep 17 00:00:00 2001
From: Marco Holz <marco.holz@fitko.de>
Date: Wed, 1 Dec 2021 14:50:37 +0000
Subject: [PATCH] Use hex instead of base64 encoding for
 `callback-authentication` header

---
 docs/details/callbacks.mdx                    | 31 ++++++++++++-------
 .../getting-started/receiving/destination.mdx |  2 +-
 docs/getting-started/receiving/query.mdx      |  6 +++-
 .../details/callbacks.mdx                     | 31 ++++++++++++-------
 .../getting-started/receiving/destination.mdx |  2 +-
 .../getting-started/receiving/query.mdx       |  6 +++-
 6 files changed, 50 insertions(+), 28 deletions(-)

diff --git a/docs/details/callbacks.mdx b/docs/details/callbacks.mdx
index 57f0eacd0..ca4fcbbb2 100644
--- a/docs/details/callbacks.mdx
+++ b/docs/details/callbacks.mdx
@@ -15,17 +15,23 @@ Im Folgenden verwenden wir die Begriffe *Callback* und *Webhook* synonym.
 
 ## Callback-URL
 API-Clients stellen zum Empfang von Callbacks einen HTTP-Endpunkt bereit, an den der Zustelldienst einen HTTP-POST-Request übermitteln kann.
-API-Clients müssen auf eingehende Callbacks mit einer HTTP-Response mit Status Code `200 OK` antworten.
-Die URL dieses HTTP-Endpunkts bezeichnen wir als Callback-URL (`callbackUrl`).
+Die URL dieses Callback-Endpunkts bezeichnen wir als Callback-URL (`callbackUrl`).
 Sie wird von dem an FIT-Connect angebundenen System festgelegt.
 
+Der Callback-Endpunkt muss von außen über das Internet erreichbar sein, damit der Zustelldienst Callbacks an diesen Endpunkt senden kann.
+Der Callback-Endpunkt MUSS zwingend über TLS (HTTPS) abgesichert sein und DARF NICHT ohne Verschlüsselung via HTTP erreichbar sein.
+Der Zustelldienst wird Callbacks nur über eine via HTTPS verschlüsselte Verbindung auslösen.
+
+API-Clients müssen auf eingehende Callbacks mit einer HTTP-Response mit einem Status Code `2xx Success` antworten (z.B. `200 OK` oder `202 Accepted`).
+
 Eine solche Callback-URL kann z.B. wie folgt aussehen:
 ```
 https://fachverfahren.beispielstadt.example.org/callbacks/fit-connect
 ```
 
-Die Callback-URL **DARF NUR** über HTTPS erreichbar sein.
-Der Zustelldienst wird Callbacks nur über eine via HTTPS verschlüsselte Verbindung auslösen.
+:::caution Warnung
+Da der Callback-Endpunkt öffentlich über das Internet erreichbar ist, **MÜSSEN** angebundene Systeme prüfen, ob eingehende Callbacks von einem vertrauenswürdigen Zustelldienst stammen. Zu diesem Zweck **MÜSSEN** die im Abschnitt [Prüfung von Callbacks](#callback-validation) beschriebenen Prüfungen durchgeführt werden.
+:::
 
 ## Konfiguration von Callbacks
 Eine Konfiguration von Callbacks ist [über das Self-Service-Portal](../getting-started/receiving/destination.mdx) und über die API-Endpunkte <ApiLink to="/v1/destinations/{destinationId}" withMethod="put" /> bzw. <ApiLink to="/destinations/{destinationId}" withMethod="patch" /> möglich.
@@ -80,8 +86,9 @@ TODO: Codebeispiel ergänzen
   </TabItem>
 </Tabs>
 
-## Prüfung von Callbacks
-API-Clients, die Callbacks empfangen, **MÜSSEN** zwingend sicherstellen, dass ausgelöste Callbacks von einem vertrauenswürdigen Zustelldienst stammen.
+## Prüfung von Callbacks {#callback-validation}
+Da der Callback-Endpunkt öffentlich über das Internet erreichbar ist, **MÜSSEN** angebundene Systeme prüfen, ob eingehende Callbacks von einem vertrauenswürdigen Zustelldienst stammen.
+
 Hierzu enthalten Callbacks einen Message Authentication Code (HMAC) gemäß [RFC 2104](https://datatracker.ietf.org/doc/html/rfc2104) auf Basis des angegebenen *Callback-Secrets*.
 Ein HMAC kann als „symmetrische Signatur“ verstanden werden und ermöglicht die Prüfung der Herkunft und Integrität eines eingehenden Callbacks.
 
@@ -93,16 +100,16 @@ Bei der Prüfung der Echtheit des ausgelösten Callbacks **MÜSSEN** API-Clients
 Das folgende Beispiel zeigt die Verwendung der HTTP-Header `callback-authentication` und `callback-timestamp`:
 ```http
 POST /callbacks/fit-connect
-callback-authentication: f4eig0ht6hdlsfz6DVqGjXi1j3RAombIQ7vjG1M2TFZx1fGurzg1nOEh00lPfLEulhio1RyTOav1e1aMi69SRg==
+callback-authentication: 798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df
 callback-timestamp: 1672527599
 
 {"type":"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions","submissionIds":["f39ab143-d91a-474a-b69f-b00f1a1873c2"]}
 ```
 
-Der HMAC wird gebildet aus dem im HTTP-Header `callback-timestamp` übertragenen Zeitstempel und dem im HTTP-Body übertragenen Payload, getrennt durch das Zeichen `.` (Punkt), jeweils UTF-8-kodiert.
+Der HMAC wird gebildet aus dem im HTTP-Header `callback-timestamp` übertragenen Zeitstempel und dem im HTTP-Body übertragenen Payload, getrennt durch das Zeichen `.` (Punkt), jeweils UTF-8-kodiert. Der HMAC wird hexadezimal kodiert übertragen.
 Als Hash-Algorithmus wird SHA-512 verwendet.
 ```
-callback-authentication = BASE64(HMAC(key={callback-secret}, message={timestamp}.{http-body}))
+callback-authentication = HEX(HMAC(key={callback-secret}, message={timestamp}.{http-body}))
 ```
 
 Um den HMAC zu verifizieren, bildet der API-Client mithilfe des *Callback Secret* den HMAC nach und vergleicht diesen mit dem im HTTP-Header `callback-authentication` übertragenen HMAC.
@@ -136,12 +143,12 @@ else:
 payload = str(request['headers']['callback-timestamp']) + '.' + request['body']
 
 expected_hmac = hmac.digest(CALLBACK_SECRET.encode("utf-8"), payload.encode("utf-8"), digest=sha512)
-expected_hmac_base64 = base64.b64encode(expected_hmac).decode()
+expected_hmac_hex = binascii.hexlify(expected_hmac).decode('utf-8')
 
-print('hmac', expected_hmac_base64)
+print('hmac', expected_hmac_hex)
 
 # 3. Berechneten HMAC mit HMAC aus HTTP-Header vergleichen
-if not hmac.compare_digest(request['headers']['callback-authentication'], expected_hmac_base64):
+if not hmac.compare_digest(request['headers']['callback-authentication'], expected_hmac_hex):
     print('Error: invalid hmac')
     sys.exit(2)
 else:
diff --git a/docs/getting-started/receiving/destination.mdx b/docs/getting-started/receiving/destination.mdx
index 9e47d566e..8902ae3b8 100644
--- a/docs/getting-started/receiving/destination.mdx
+++ b/docs/getting-started/receiving/destination.mdx
@@ -34,7 +34,7 @@ Ein Zustellpunkt benötigt zur Erstellung eine Vielzahl von Angaben, die sich im
 
 In diesem Bereich vergeben Sie einen Namen, unter dem der Zustellpunkt im Self-Service-Portal angezeigt wird.
 
-Sie können Ihr empfangendes System per Callback (Webhook) über neue Einreichungen informieren lassen.
+Sie können Ihr empfangendes System per Callback (Webhook) [über neue Einreichungen informieren lassen](./query.mdx).
 Die Nutzung eines Callbacks ist grundsätzlich optional, wird jedoch empfohlen.
 Tragen Sie dafür die Adresse des Callbacks und ein Geheimis zur Absicherung ein.
 Die Nutzung eines Callbacks ohne ein Geheimnis ist nicht möglich.
diff --git a/docs/getting-started/receiving/query.mdx b/docs/getting-started/receiving/query.mdx
index 92dc23637..1186920d4 100644
--- a/docs/getting-started/receiving/query.mdx
+++ b/docs/getting-started/receiving/query.mdx
@@ -17,12 +17,16 @@ Callbacks zur Benachrichtigung über neue Einreichungen haben das folgende Forma
 
 ```http
 POST /callbacks/fit-connect
-callback-authentication: f4eig0ht6hdlsfz6DVqGjXi1j3RAombIQ7vjG1M2TFZx1fGurzg1nOEh00lPfLEulhio1RyTOav1e1aMi69SRg==
+callback-authentication: 7f87a283486dea1765b1fcfa0d5a868d78b58f7440a266c843bbe31b53364c5671d5f1aeaf38359ce121d3494f7cb12e9618a8d51c9339abf57b568c8baf5246
 callback-timestamp: 1672527599
 
 {"type":"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions","submissionIds":["f39ab143-d91a-474a-b69f-b00f1a1873c2"]}
 ```
 
+:::caution Warnung!
+Da der Callback-Endpunkt des empfangenden Systems öffentlich über das Internet erreichbar ist, **MÜSSEN** angebundene Systeme prüfen, ob eingehende Callbacks von einem vertrauenswürdigen Zustelldienst stammen. Zu diesem Zweck **MÜSSEN** die im Artikel [Prüfen von Callbacks](../../details/callbacks.mdx#callback-validation) beschriebenen Prüfungen durchgeführt werden.
+:::
+
 Wenn das empfangende System über den Eingang neuer Einreichungen benachrichtigt wurde, dann kann es diese wie im Artikel [Einreichung herunterladen](./download-submission.mdx) beschrieben herunterladen.
 
 ## Polling
diff --git a/versioned_docs/version-FIT-Connect_v1/details/callbacks.mdx b/versioned_docs/version-FIT-Connect_v1/details/callbacks.mdx
index 57f0eacd0..ca4fcbbb2 100644
--- a/versioned_docs/version-FIT-Connect_v1/details/callbacks.mdx
+++ b/versioned_docs/version-FIT-Connect_v1/details/callbacks.mdx
@@ -15,17 +15,23 @@ Im Folgenden verwenden wir die Begriffe *Callback* und *Webhook* synonym.
 
 ## Callback-URL
 API-Clients stellen zum Empfang von Callbacks einen HTTP-Endpunkt bereit, an den der Zustelldienst einen HTTP-POST-Request übermitteln kann.
-API-Clients müssen auf eingehende Callbacks mit einer HTTP-Response mit Status Code `200 OK` antworten.
-Die URL dieses HTTP-Endpunkts bezeichnen wir als Callback-URL (`callbackUrl`).
+Die URL dieses Callback-Endpunkts bezeichnen wir als Callback-URL (`callbackUrl`).
 Sie wird von dem an FIT-Connect angebundenen System festgelegt.
 
+Der Callback-Endpunkt muss von außen über das Internet erreichbar sein, damit der Zustelldienst Callbacks an diesen Endpunkt senden kann.
+Der Callback-Endpunkt MUSS zwingend über TLS (HTTPS) abgesichert sein und DARF NICHT ohne Verschlüsselung via HTTP erreichbar sein.
+Der Zustelldienst wird Callbacks nur über eine via HTTPS verschlüsselte Verbindung auslösen.
+
+API-Clients müssen auf eingehende Callbacks mit einer HTTP-Response mit einem Status Code `2xx Success` antworten (z.B. `200 OK` oder `202 Accepted`).
+
 Eine solche Callback-URL kann z.B. wie folgt aussehen:
 ```
 https://fachverfahren.beispielstadt.example.org/callbacks/fit-connect
 ```
 
-Die Callback-URL **DARF NUR** über HTTPS erreichbar sein.
-Der Zustelldienst wird Callbacks nur über eine via HTTPS verschlüsselte Verbindung auslösen.
+:::caution Warnung
+Da der Callback-Endpunkt öffentlich über das Internet erreichbar ist, **MÜSSEN** angebundene Systeme prüfen, ob eingehende Callbacks von einem vertrauenswürdigen Zustelldienst stammen. Zu diesem Zweck **MÜSSEN** die im Abschnitt [Prüfung von Callbacks](#callback-validation) beschriebenen Prüfungen durchgeführt werden.
+:::
 
 ## Konfiguration von Callbacks
 Eine Konfiguration von Callbacks ist [über das Self-Service-Portal](../getting-started/receiving/destination.mdx) und über die API-Endpunkte <ApiLink to="/v1/destinations/{destinationId}" withMethod="put" /> bzw. <ApiLink to="/destinations/{destinationId}" withMethod="patch" /> möglich.
@@ -80,8 +86,9 @@ TODO: Codebeispiel ergänzen
   </TabItem>
 </Tabs>
 
-## Prüfung von Callbacks
-API-Clients, die Callbacks empfangen, **MÜSSEN** zwingend sicherstellen, dass ausgelöste Callbacks von einem vertrauenswürdigen Zustelldienst stammen.
+## Prüfung von Callbacks {#callback-validation}
+Da der Callback-Endpunkt öffentlich über das Internet erreichbar ist, **MÜSSEN** angebundene Systeme prüfen, ob eingehende Callbacks von einem vertrauenswürdigen Zustelldienst stammen.
+
 Hierzu enthalten Callbacks einen Message Authentication Code (HMAC) gemäß [RFC 2104](https://datatracker.ietf.org/doc/html/rfc2104) auf Basis des angegebenen *Callback-Secrets*.
 Ein HMAC kann als „symmetrische Signatur“ verstanden werden und ermöglicht die Prüfung der Herkunft und Integrität eines eingehenden Callbacks.
 
@@ -93,16 +100,16 @@ Bei der Prüfung der Echtheit des ausgelösten Callbacks **MÜSSEN** API-Clients
 Das folgende Beispiel zeigt die Verwendung der HTTP-Header `callback-authentication` und `callback-timestamp`:
 ```http
 POST /callbacks/fit-connect
-callback-authentication: f4eig0ht6hdlsfz6DVqGjXi1j3RAombIQ7vjG1M2TFZx1fGurzg1nOEh00lPfLEulhio1RyTOav1e1aMi69SRg==
+callback-authentication: 798cd0edb70c08e5b32aa8a18cbbc8ff6b3078c51af6d011ff4e32e470c746234fc4314821fe5185264b029e962bd37de33f3b9fc5f1a93c40ce6672845e90df
 callback-timestamp: 1672527599
 
 {"type":"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions","submissionIds":["f39ab143-d91a-474a-b69f-b00f1a1873c2"]}
 ```
 
-Der HMAC wird gebildet aus dem im HTTP-Header `callback-timestamp` übertragenen Zeitstempel und dem im HTTP-Body übertragenen Payload, getrennt durch das Zeichen `.` (Punkt), jeweils UTF-8-kodiert.
+Der HMAC wird gebildet aus dem im HTTP-Header `callback-timestamp` übertragenen Zeitstempel und dem im HTTP-Body übertragenen Payload, getrennt durch das Zeichen `.` (Punkt), jeweils UTF-8-kodiert. Der HMAC wird hexadezimal kodiert übertragen.
 Als Hash-Algorithmus wird SHA-512 verwendet.
 ```
-callback-authentication = BASE64(HMAC(key={callback-secret}, message={timestamp}.{http-body}))
+callback-authentication = HEX(HMAC(key={callback-secret}, message={timestamp}.{http-body}))
 ```
 
 Um den HMAC zu verifizieren, bildet der API-Client mithilfe des *Callback Secret* den HMAC nach und vergleicht diesen mit dem im HTTP-Header `callback-authentication` übertragenen HMAC.
@@ -136,12 +143,12 @@ else:
 payload = str(request['headers']['callback-timestamp']) + '.' + request['body']
 
 expected_hmac = hmac.digest(CALLBACK_SECRET.encode("utf-8"), payload.encode("utf-8"), digest=sha512)
-expected_hmac_base64 = base64.b64encode(expected_hmac).decode()
+expected_hmac_hex = binascii.hexlify(expected_hmac).decode('utf-8')
 
-print('hmac', expected_hmac_base64)
+print('hmac', expected_hmac_hex)
 
 # 3. Berechneten HMAC mit HMAC aus HTTP-Header vergleichen
-if not hmac.compare_digest(request['headers']['callback-authentication'], expected_hmac_base64):
+if not hmac.compare_digest(request['headers']['callback-authentication'], expected_hmac_hex):
     print('Error: invalid hmac')
     sys.exit(2)
 else:
diff --git a/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/destination.mdx b/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/destination.mdx
index 9e47d566e..8902ae3b8 100644
--- a/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/destination.mdx
+++ b/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/destination.mdx
@@ -34,7 +34,7 @@ Ein Zustellpunkt benötigt zur Erstellung eine Vielzahl von Angaben, die sich im
 
 In diesem Bereich vergeben Sie einen Namen, unter dem der Zustellpunkt im Self-Service-Portal angezeigt wird.
 
-Sie können Ihr empfangendes System per Callback (Webhook) über neue Einreichungen informieren lassen.
+Sie können Ihr empfangendes System per Callback (Webhook) [über neue Einreichungen informieren lassen](./query.mdx).
 Die Nutzung eines Callbacks ist grundsätzlich optional, wird jedoch empfohlen.
 Tragen Sie dafür die Adresse des Callbacks und ein Geheimis zur Absicherung ein.
 Die Nutzung eines Callbacks ohne ein Geheimnis ist nicht möglich.
diff --git a/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/query.mdx b/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/query.mdx
index 92dc23637..1186920d4 100644
--- a/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/query.mdx
+++ b/versioned_docs/version-FIT-Connect_v1/getting-started/receiving/query.mdx
@@ -17,12 +17,16 @@ Callbacks zur Benachrichtigung über neue Einreichungen haben das folgende Forma
 
 ```http
 POST /callbacks/fit-connect
-callback-authentication: f4eig0ht6hdlsfz6DVqGjXi1j3RAombIQ7vjG1M2TFZx1fGurzg1nOEh00lPfLEulhio1RyTOav1e1aMi69SRg==
+callback-authentication: 7f87a283486dea1765b1fcfa0d5a868d78b58f7440a266c843bbe31b53364c5671d5f1aeaf38359ce121d3494f7cb12e9618a8d51c9339abf57b568c8baf5246
 callback-timestamp: 1672527599
 
 {"type":"https://schema.fitko.de/fit-connect/submission-api/callbacks/new-submissions","submissionIds":["f39ab143-d91a-474a-b69f-b00f1a1873c2"]}
 ```
 
+:::caution Warnung!
+Da der Callback-Endpunkt des empfangenden Systems öffentlich über das Internet erreichbar ist, **MÜSSEN** angebundene Systeme prüfen, ob eingehende Callbacks von einem vertrauenswürdigen Zustelldienst stammen. Zu diesem Zweck **MÜSSEN** die im Artikel [Prüfen von Callbacks](../../details/callbacks.mdx#callback-validation) beschriebenen Prüfungen durchgeführt werden.
+:::
+
 Wenn das empfangende System über den Eingang neuer Einreichungen benachrichtigt wurde, dann kann es diese wie im Artikel [Einreichung herunterladen](./download-submission.mdx) beschrieben herunterladen.
 
 ## Polling
-- 
GitLab