Mit einer Web App kann ein externes System über die Web-Service-API Zugriff auf bestimmte Spaces anfordern. Der Benutzer kann anderen Systemen auf automatisierte Weise Zugriff gewähren. Der OAuth-2.0-Ablauf beschreibt dieses Konzept im Detail.
Im Allgemeinen lässt die OAuth-Spezifikation etwas Spielraum für Anpassungen an diesen konkreten Anwendungsfall.
Die Integration folgt grundsätzlich der OAuth-Spezifikation. Am Ablauf sind die folgenden Akteure beteiligt:
Benutzer: Der Benutzer kann der Web App Zugriff auf einen Space gewähren. Der Benutzer ist üblicherweise der Händler, der Ihrer App Zugriff gewährt.
Client: Der Client ruft die Web-Service-API auf, um auf die Daten innerhalb des Space zuzugreifen. Das ist Ihre App. Ihre App kann auch auf einem Webserver laufen.
Server: Wir verwenden in dieser Dokumentation den Begriff server für unser System. Wie im Client-Server-Muster stellt unser System den Server dar.
Um diese Dokumentation einfach zu halten, verwenden wir die Terminologie der OAuth-Spezifikation wieder.
Die obige Abbildung zeigt die folgenden Schritte:
Der Benutzer fordert die Installation der Web App an.
Die Web App (Client) gibt die Autorisierungs-URL zurück, über die der Benutzer der Web App Zugriff gewährt.
Die Autorisierungs-URL erfordert, dass eine redirect_uri vorhanden ist.
Wenn der Benutzer die Autorisierungs-URL aufruft, fordert der Server den Benutzer seinerseits auf,
die angeforderte Berechtigung für den Space zu bestätigen. Als Ergebnis gibt der Server die
redirect_uri an den Browser zurück.
Der Browser ruft die redirect_uri auf, die auf eine von der Web App
kontrollierte URL verweist. Die redirect_uri enthält einen code-Parameter, mit dem
die Web App die Installation der App anfordern kann.
Die folgenden Abschnitte behandeln die obigen Schritte im Detail.
In einem ersten Schritt müssen Sie eine Web App einrichten und die client_id sowie das client_secret abrufen.
Es gibt zwei Möglichkeiten, wie der Benutzer die Installation starten kann. In beiden Fällen muss die Web App den
Benutzer an die authorization URL weiterleiten. Siehe Um Berechtigung bitten, wie das gemacht wird.
Option 1: Der Benutzer löst die Installation innerhalb unserer Anwendung aus. In diesem Fall leiten wir
den Benutzer an die Installation Redirect URL weiter, wie sie in der Web-App-Konfiguration definiert ist. In diesem Fall ruft der Benutzer
die Installation Redirect URL als GET-HTTP-Anfrage auf. Wir stellen sicher, dass die
Anfrage die folgenden Parameter enthält:
space_id: Die App wird in den Space installiert, der durch die Space-ID aufgelöst wird.
action: Die Aktion ist auf install gesetzt. Die Aktion ermöglicht es zu verstehen, welche Operation ausgeführt werden soll.
timestamp: Der Zeitstempel in Sekunden seit 1970. Dies ermöglicht die Prüfung auf Replay-Angriffe. Es wird empfohlen, Anfragen abzulehnen, die älter als einige Stunden sind.
hmac: Ein HMAC wird auf Basis der Anfrageparameter space_id, action und timestamp berechnet. Dies ermöglicht die
Überprüfung, ob eine Anfrage wirklich von uns stammt. Siehe HMAC-Berechnung.
Option 2: Der Benutzer löst die Installation innerhalb der Web App aus. In diesem Fall muss die Web App nach der Space-ID fragen oder einen anderen Ansatz verwenden, um sie zu ermitteln.
Um den Benutzer um die Berechtigung zu bitten, muss der Benutzer weitergeleitet werden an: https://checkout.postfinance.ch/oauth/authorize
Die Anfrage muss die folgenden Anfrageparameter enthalten:
space_id: Die App wird in den Space installiert, der durch die Space-ID aufgelöst wird.
redirect_uri: Die URI, an die der Benutzer zurückgeleitet wird, nachdem er den Zugriff autorisiert hat. Die
Web-App-Konfiguration muss diese URL als redirection endpoint enthalten, andernfalls wird sie abgelehnt.
scope: Der Scope-Parameter enthält eine durch Leerzeichen getrennte Liste von angeforderten Berechtigungs-IDs. Die Berechtigungsliste enthält die vollständige Liste aller Berechtigungen, die angefordert werden können.
state: Ein zufällig generierter Wert, der von Ihrer App (Client) bereitgestellt wird und für jede
Autorisierungsanfrage eindeutig ist. Wenn der Benutzer zur redirect_uri zurückkehrt, fügen wir diesen Wert erneut hinzu. Es ist wichtig, dass
Sie diesen Wert überprüfen, da die Sicherheit kompromittiert werden kann. Wir empfehlen, dass Sie sicherstellen, dass der State nicht für
Replay-Angriffe verwendet werden kann (z. B. einen Zeitstempel einfügen und Anfragen ablehnen, die zu alt sind).
client_id: Die Client-ID, die Ihre App identifiziert. Die client ID kann in der Web-App-Konfiguration abgerufen werden.
Wenn Sie im Parameter scope Berechtigungen anfordern, die bestimmte Funktionen erfordern, die für den Space nicht verfügbar sind,
versuchen wir entweder, diese Funktionen zu aktivieren, oder geben bei der Installationsbestätigung eine reduzierte Menge an Berechtigungen zurück.
Wir entfernen also die Berechtigungen, die wir nicht gewähren können.
Beispielanfrage:
https://checkout.postfinance.ch/oauth/v2/authorize?space_id=15023&client_id=14141&redirect_uri=https%3A%2F%2Fexample.com%2Fconfirm%2Finstall&state=1609445756&scope=1432736711150%201432736711152
|
Note
|
Falls Sie die Berechtigungen der Web App zu einem späteren Zeitpunkt ändern möchten, können Sie dieselben Schritte ausführen, als würden Sie die
App von Grund auf installieren. Sie können den Benutzer mit dem angepassten scope-Parameter an die https://checkout.postfinance.ch/oauth/v2/authorize weiterleiten. Alle folgenden Schritte bleiben gleich.
|
Wenn der Benutzer zur redirect_uri zurückkehrt, muss die Web App die Installation bestätigen und das
access_token gemäss der OAuth-Spezifikation abrufen.
Zusammen mit der redirect_uri werden die folgenden Parameter gesendet:
state: Der State-Parameter enthält den Wert, wie er an die Autorisierungs-URL übergeben wurde. Überprüfen Sie, dass dieser Wert mit dem von Ihnen übergebenen Wert identisch ist.
space_id: Die ID des Space, auf den der Benutzer Zugriff gewährt hat.
timestamp: Der Zeitpunkt, zu dem der Benutzer Zugriff gewährt hat. Die Zeit ist in Sekunden seit 1970 (Unix-Zeitstempel). Prüfen Sie, dass die Gewährung nicht zu alt ist. Ein sinnvoller Wert liegt hier bei etwa 10 Minuten. Dies verhindert Replay-Angriffe.
code: Der Code identifiziert die im vorherigen Schritt erstellte Gewährung. Sie benötigen diesen Code zur Bestätigung der Installation. Siehe unten, wie das gemacht wird.
return_url: Die URL, an die der Benutzer nach Abschluss der Installation zurückgeleitet werden kann. Der optionale Parameter message kann an
die URL angehängt werden, um eine benutzerdefinierte Nachricht anzuzeigen. Der URL-Parameter type definiert, ob eine success-Nachricht oder eine failure-Nachricht angezeigt wird.
hmac: Der HMAC ermöglicht die Überprüfung, dass die Anfrage nicht manipuliert wurde. Siehe HMAC-Berechnung, wie Sie das tun können.
Beispielanfrage:
https://example.com/confirm/install?state=1609445756&space_id=14141×tamp=1609449756&code=AdF7812311414312312387483&hmac=8jAYtV4R7FFTjl3UqWpkmBy78PVQdDygJ1NbM7v_-1AcAMWMhv45PPJA-nYkNT4gCNZ2XECYF3-N5W29ZXGJ6Q
Um die Installation zu bestätigen, müssen Sie einen API-Aufruf senden. Sie müssen eine POST-Nachricht an die
URL https://checkout.postfinance.ch/api/v2.0/web-apps/confirm/{code} senden. Siehe auch die Web-Service-Dokumentation.
Da dies ein regulärer Web-Service-Endpunkt ist, müssen Sie die Authentifizierungs-Zugangsdaten im Header der HTTP-Anfrage bereitstellen.
Verwenden Sie hierfür die client_id als Benutzer-ID und für das client_secret das Secret.
Die Antwort sieht ähnlich wie das folgende Beispiel aus:
{
"access_token": "dummy-value",
"scope": "1432736711150 1432736711152",
"space": 14141,
"state": "1609445756",
"token_type": "web-service-hmac",
}
In diesem Schritt sollten Sie prüfen, ob die zurückgegebene scope-Liste dem entspricht, was Sie angefordert haben, und ob die zurückgegebene Menge
Ihre Anforderungen erfüllt. Wie zuvor angegeben, können nicht in allen Situationen alle angeforderten Berechtigungen gewährt werden.
Der nächste Schritt behandelt, wie die Web-Service-API tatsächlich aufgerufen wird.
Sobald die App erfolgreich im Space installiert wurde, können die client_id und das client_secret verwendet werden, um für den betreffenden Space auf die Web-Service-API
zuzugreifen. Bei der Web-Service-API müssen Sie die client_id als Benutzer-ID und das client_secret als Secret verwenden.
Der Aufruf der API erfolgt genauso, als würden Sie einen Anwendungsbenutzer erstellen und dessen Zugangsdaten verwenden, um die API aufzurufen.
Die Konfigurations-Redirect-URL ermöglicht es, eine Seite zu definieren, auf der die Web App vom Benutzer konfiguriert werden kann. Das bedeutet, dass der Web-App-Eintrag
eine Schaltfläche Configure enthält, die den Benutzer an die in der Web-App-Konfiguration definierte URL weiterleitet.
Die Weiterleitungs-URL enthält die folgenden Parameter:
space_id: Die Space-ID identifiziert den Space, für den die Konfiguration angepasst werden soll.
timestamp: Der Zeitstempel in Sekunden seit 1970. Dies ermöglicht die Prüfung auf Replay-Angriffe. Es wird empfohlen, Anfragen abzulehnen, die älter als einige Stunden sind.
action: Die Aktion ist auf configure gesetzt. Die Aktion ermöglicht es Ihnen, die vom Benutzer ausgelöste Aktion zu verstehen.
return_url: Die URL, an die der Benutzer nach Abschluss der Konfiguration zurückgeleitet werden kann. Der optionale Parameter message kann an die URL angehängt werden. Diese Nachricht wird dem Benutzer angezeigt. Der Parameter type definiert, ob eine success-Nachricht oder eine failure-Nachricht angezeigt wird.
hmac: Ein HMAC wird auf Basis der Anfrageparameter space_id, action, return_url und timestamp berechnet. Dies ermöglicht die
Überprüfung, ob eine Anfrage wirklich von uns stammt. Siehe HMAC-Berechnung.
|
Note
|
Sie sollten immer den hmac prüfen, um zu verhindern, dass ein Angreifer die Konfiguration einer App ändern kann. Der hmac garantiert,
dass der Benutzer berechtigt ist, die Konfigurationsoperation durchzuführen.
|
Um Ihre Web App mit dem Installationsstatus in den verschiedenen Spaces synchron zu halten, empfehlen wir, eine Benachrichtigungs-URL einzurichten. Jede Änderung an der Installation der Web App innerhalb eines Space wird über diese URL gemeldet.
Wir senden eine HTTP-POST-Nachricht mit dem folgenden Body:
{
"space_id": 15023,
"client_id": "14141",
}
Ob die App installiert oder deinstalliert wurde, ist nicht Teil der Nachricht. Verwenden Sie die Web-Service-API, um herauszufinden, was der Auslöser dafür war, dass wir diese Nachricht gesendet haben.
Das obige Verhalten ist beabsichtigt. Es löst die folgenden Probleme:
Es kann vorkommen, dass eine Benachrichtigung mit Verzögerung gesendet wird, weil wir Schwierigkeiten hatten, Ihr System zu erreichen. In diesem Fall lesen Sie den Installationsstatus dennoch aus einer einzigen Quelle, die den korrekten Status enthält.
Es bestehen keine Sicherheitsrisiken, da keine kritischen Informationen in der HTTP-Anfrage enthalten sind. Die Nachricht ist nur ein Auslöser dafür, dass Sie die korrekten Informationen über die Web-Service-API abrufen.
In manchen Fällen können die Web App und unser System aufgrund vorübergehender Ausfälle nicht mehr synchron sein. Mit dem obigen Ansatz können Sie sich entscheiden, den aktuellen Installationsstatus zu jedem beliebigen Zeitpunkt abzurufen.
|
Note
|
Beachten Sie, dass ein Ausfall Ihres Systems uns daran hindern kann, Benachrichtigungen an Ihr System zu senden. In diesem Fall senden wir eine E-Mail, sofern dies in Ihrer Web-App-Konfiguration angegeben ist. |
Um zu überprüfen, dass die Anfragen von unserem System stammen, hängen wir einen HMAC mit SHA-512 an. Er garantiert,
dass die Parameter während der Übertragung nicht verändert werden. Dies ist ähnlich wie ein normaler Hash, jedoch auf sichere Weise.
Die meisten Programmiersprachen bieten eine Implementierung für die HMAC-Berechnung.
Grundsätzlich müssen wir zuerst eine Zeichenkette konstruieren und sie später mit dem client_secret absichern. Dazu
nehmen wir alle Parameter, ordnen sie alphabetisch und verketten sie mit einem | (Pipe).
Siehe das folgende PHP-Beispiel mit den Parametern: space_id, timestamp, client_id und scope
<?php
$client_secret = "OWOMg2gnaSx1nukAM6SN2vxedfY1yLPONvcTKbhDv7I=";
$requestParameters = array();
$requestParameters['client_id'] = "14141";
$requestParameters['state'] = "87ggfr456zghjui876tgvbji";
$requestParameters['space_id'] = 15023;
$requestParameters['scope'] = "1432736711150 1432736711152";
// We sort the array elements by the element's key
ksort($requestParameters);
$parametersToSecure = array();
foreach ($requestParameters as $key => $value) {
$parametersToSecure[] = $key . "=" . $value;
}
$toSecure = implode('|', $parametersToSecure);
$decodedSecret = base64_decode($client_secret);
$hmacValue = base64_encode(hash_hmac("sha512", $toSecure, $decodedSecret, true));
// Replacing "+" with "-" and "/" with "_"
$cleanedMac = $url = strtr($hmacValue, '+/', '-_');
// Remove padding
$cleanedMac = rtrim($cleanedMac, '=');
echo $cleanedMac;
Anmerkungen:
Wir URL-codieren die Parameter nicht, wenn wir den HMAC berechnen. Wenn Ihre Infrastruktur (z. B. Server) den URL-Parameter nicht automatisch decodiert, müssen Sie dies möglicherweise vor der Berechnung des HMAC tun.
Das auf der Web-App-Konfigurationsseite bereitgestellte client_secret ist als Base64-Zeichenkette codiert. Wir müssen es zuerst in ein Binärformat umwandeln.
Die abzusichernden Parameter hängen vom Anwendungsfall ab. Wir verwenden den HMAC in mehreren Situationen, passen Sie die Parameter daher entsprechend an. Wir schliessen nur die Parameter ein, die ausdrücklich aufgeführt sind. Wir schliessen niemals alle Parameter ein. Wenn die Anfrage also weitere Parameter enthält, ignorieren Sie diese.
Der in der Anfrage enthaltene HMAC ist immer Base64-codiert. Wenn Sie den berechneten HMAC mit dem übergebenen HMAC vergleichen, vergleichen Sie sie bitte im Binärformat oder stellen Sie sicher, dass Sie zuvor die verschiedenen Base64-Formate vereinheitlichen. Aufgrund der Tatsache, dass wir den HMAC als URL-Parameter übergeben, müssen wir eine URL-sichere Implementierung ohne Padding verwenden. Siehe RFC 4648
Die Parameterwerte stammen möglicherweise aus einem JSON-Objekt. In diesem Fall müssen die Werte vor dem Verketten in Zeichenketten umgewandelt werden.
Gleitkommazahlen werden mit einem Punkt und mit der gleichen Anzahl von Nachkommastellen wie im JSON dargestellt, und auch optionale Nullen am Ende werden angehängt. Booleans müssen als true oder false dargestellt werden.
In manchen Fällen werden Ihre App-Endpunkte durch eine HTTP-Anfrage aufgerufen, die über unsere Server an Ihre Server gesendet wird. Die Anfrage erfolgt also ohne den Benutzer (Browser). Dieser Abschnitt behandelt wichtige Informationen zu diesen Aufrufen.
In manchen Fällen müssen wir Sie über bestimmte Aktivitäten informieren, die Ihre App ausführen muss. In diesen Fällen verwenden wir Remote-Aufrufe. Diese Aufrufe senden an eine von Ihnen definierte URL eine HTTP-Anfrage mit einigen Daten. Die Daten, die wir senden, hängen vom konkreten Anwendungsfall ab. Wir behandeln hier nur die Dinge, die auf alle Arten von Aufrufen zutreffen.
Verwenden Sie daher die entsprechenden Dokumentationen für die konkreten Anwendungsfälle, um zu verstehen, was der tatsächliche Anfrage-Body enthalten wird.
Jede Anfrage enthält einen Header x-mac-value. Dieser Header enthält einen HMAC, mit dem Sie überprüfen können, dass die Anfrage wirklich von unseren
Systemen stammt. Ausserdem enthält die Anfrage auch den Header x-timestamp, der den Zeitpunkt angibt, zu dem die Anfrage erstellt wurde. Der Zeitstempel enthält die Zeit in Sekunden seit dem ersten Januar
1970. Es handelt sich also um einen Unix-Zeitstempel.
Um den HMAC zu überprüfen, müssen Sie den Wert von x-timestamp mit einer Pipe (|) und dem Anfrage-Body verketten. Die resultierende Zeichenkette müssen Sie an den HMAC mit dem SHA-512-Algorithmus übergeben.
Als Secret können Sie das für die App generierte Secret verwenden. Also dasselbe Secret, das Sie auch zum Aufrufen unserer Web-Service-API verwenden.
Siehe unten auch ein Beispiel in PHP:
<?php
$client_secret = "OWOMg2gnaSx1nukAM6SN2vxedfY1yLPONvcTKbhDv7I=";
$hmac = $_SERVER['HTTP_X_MAC_VALUE']; // PHP requires to transform the header name.
$timestamp = $_SERVER['HTTP_X_TIMESTAMP']; // PHP requires to transform the header name.
$body = file_get_contents('php://input'); // That might be different depending on how you run PHP
$toSecure = $timestamp . '|' . $body;
$decodedSecret = base64_decode($client_secret);
$calculatedHmac = base64_encode(hash_hmac("sha512", $toSecure, $decodedSecret, true));
if (strtolower($calculatedHmac) !== strtolower($hmac)) {
die('The calculated HMAC does not match with the supplied one.');
}
$allowedOffset = 15 * 60; // 15 minutes
if ($timestamp < time() - $allowedOffset) {
die('The request has expired. This seems like a reply attack.');
}
Falls Ihr Server offline ist, wiederholen wir die Anfragen mehrmals. Wir betrachten die Anfrage als erfolgreich zugestellt, wenn wir eine HTTP-Antwort mit einem HTTP-Statuscode 2XX erhalten. Jede andere Antwort wird als fehlgeschlagen betrachtet. Dazu gehören auch Weiterleitungen über den HTTP-Statuscode 302 oder 301.
Auch wenn der Server nicht erreichbar ist, wiederholen wir den Aufruf. Es gibt zudem einen Timeout von 30 Sekunden. Ihr Server muss innerhalb von 30 Sekunden antworten, andernfalls wiederholen wir
den Aufruf. Wenn wir den Aufruf wiederholen, fügen wir aktualisierte Header (x-mac-value und x-timestamp) hinzu, und möglicherweise enthält auch der Body aktualisierte Daten.
Es liegt an Ihnen, wie Sie mehrere Aufrufe handhaben. Je nach Anwendungsfall gibt es verschiedene Alternativen. Bitte prüfen Sie die entsprechende Dokumentation, um zu sehen, welche Möglichkeiten Sie haben, die mehrfache Ausführung der entsprechenden Operation zu verhindern.