3.2.1 Authentifizierung Native Applikation

Um ein Sage ID Access Token für eine Native Applikation wie Mobile oder Desktop Applikation zu erhalten, muss OAuth 2.0 Grant Flow mit Proof Key for Code Exchange (RFC 7636) implementiert werden.

Mit PKCE, eine Applikation erzeugt für jede Anfrage eine kryptographisch zufälligen Key, den code_verifier und transformiert einen Parameter code_challenge, der an Sage ID gesendet wir, um den authorization_code zu erhalten. Wenn eine Applikation den authorization_code erhält, wird dieser code und code_verifier an den Sage ID Token Endpunkt gesendet, um im Austausch die anfragten Token (Access Token) zu erhalten.

 

Dieser OAuth 2.0 Flow hat folgende Schritte:

  1. Ihre Applikation initiiert den Flow und leitet einen Benutzer an Sage ID (/authorize Endpunkt) weiter und sendet code_challenge und code_challenge_method Parameter.

  2. SageID leitet den Benutzer zu Ihrer Applikation weiter mit einem authorization_code Parameter in der URL.

  3. Ihre Applikation sendet authorization_code und code_verifier zusammen mit redirect_uri und client_id an Sage ID zum /oauth/token Endpunkt.

  4. Sage ID validiert diese Parameter und gibt ein Access Token und optional ein Refresh Token zurück an Ihre Applikation.

  5. Ihre Applikation speichert auf sichere Art das Refresh Token unter Verwendung des Betriebssystem z.B. Data Protection (DPAPI) pro Benutzer.

  6. Dann kann Ihre Applikation das Access Token verwenden, um Sage 100 API aufzurufen im Benutzerkontext.

  7. Wenn das Access Token abläuft, kann Ihrer Applikation den Sage ID /oauth/token Endpunkt aufrufen mit refresh_token Grant Typ und dem Refresh Token, um ein neues Access Token zu erhalten.

Wenn ein Benutzer sich abmeldet von Ihrer Applikation, muss das Refresh Token gelöscht werden.

OAuth 2.0 Flow

Folgende Postman Collection enthält OAuth 2.0 Flows für die Native Applikation mit ClientID:

Für die anderen Typen muss ein Sage ID Client beantragt werden.

Sichere Speicherung von Refresh Token in einer Native Applikation

Refresh Tokens müssen auf sichere Art und Weise gespeichert werden, weil den Namen und Passwort eines Benutzers repräsentieren. Mit einem gültigen Refresh Token kann ein Access Token geholt werden. Ein Refresh Token kann z.B. 90 Tage gültig sein. Falls Access Token. Falls ein Refresh Token nicht geschützt wird und ein Angreifer Zugriff erhält, kann im Austausch ein Access Token erzeugt werden und dieser im Benutzerkontext Anfragen stellen.

In Windows ist es eine bewährte Methode DPAPI in user mode zu verwenden und diese zu speichern mit einem zufälligen AES Schlüssel. Dieser Schlüssel kann verwendet werden, um eine Datei zu verschlüsseln, der den Refresh Token enthält. Es ist empfohlen die Datei in einem isolierten Speicher in dem Benutzerprofil zu speichern. NTFS Berechtigungen können gesetzt werden, um diese zusätzlich zu schützen.

Implementierung

In diesem Kapitel werden die Schritte beschrieben, um eine SageID Anmeldung in einer .Net Anwendung umzusetzen. Ein code verifier und eine code challenge wird erzeugt, um nach einem Browser login eines Benutzers ein Access token zu erhalten und eine Anfrage an die Sage 100 API umsetzen zu können. Anschließend wird mit einem Refresh Token ein aktualisiertes Access Token erhalten.

Die Code Snippets sollten in .Net Framework und auch .Net Core funktionieren mit RestSharp Nuget Package. Diese Code Snippets sind einfach gehalten und dienen den Flow zu veranschaulichen. Es kann natürlich auch andere Packages verwendet werden als RestSharp für die Anfragen.

1. Erzeugen eine Code Verifier

Zunächst wird ein code_verifiergespeichert.

var rng = RandomNumberGenerator.Create(); var bytes = new byte[32]; rng.GetBytes(bytes); // Ein URL-safe string sollte verwendet werden als code_verifier (section 4 of RFC 7636) var verifier = Convert.ToBase64String(bytes) .TrimEnd('=') .Replace('+', '-') .Replace('/', '_');

2. Erzeugen einer Code Challenge

code_verifier wird verwendet, um eine code_challenge zu erzeugen, die an den /authorize Endpunkt gesendet wird.

Sie müssen diesen Wert Hashen und dürfen diesen nicht im Klartext senden.

 

var challenge = string.Empty; using (var sha256 = SHA256.Create()) { var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(verifier)); challenge = Convert.ToBase64String(challengeBytes) .TrimEnd('=') .Replace('+', '-') .Replace('/', '_');

3. Erhalten der Benutzer Token

Um den Authorization Code Flow zu starten, muss die Native Applikation den Benutzer zur /authorize Endpunkt weiterleiten inklusive der code_challenge.

Bei der Implementierung sollte nicht ein Prozess zum Starten eines Browsers wie im simplen Beispiel gestartet werden. Es könnte z.B. ein WPF Browser Control verwendet werden für die SageID Anmeldung und auslesen des Authorization Code.

//Beispiel zum Öffnen eines Browser Fensters und erhalten des Codes string url = "https://id.sage.com/authorize?audience=s100de/sage100&scope=openid token access_token offline_access email profile&response_type=code&client_id=<IHRE_CLIENTID>&code_challenge=<IHRE_CODE_CHALLENGE>&code_challenge_method=S256&redirect_uri=https://id.sage.com/mobile"; ProcessStartInfo psi = new ProcessStartInfo { FileName = url, UseShellExecute = true }; Process.Start(psi);

4. Austausch des Authorization Code mit einem Access Token

Jetzt kann der Authorization Code ausgetauscht werden mit einem Access Token, um einen Aufruf der Sage 100 API umsetzen zu können. Der Authorization Code vom vorhergehenden Schritt wird verwendet, der an /oauth/token per POST gesendet werden kann.

The Antwort enthält access_token, refresh_token, id_token, und token_type. Ein Beispiel:

5. Aufruf der Sage 100 API

Mit dem access_token kann die Sage 100 API aufgerufen werden, in dem der Access Token (Bearer) übergeben wird im Authorization Header.

6. Einen neuen Access Token anfragen

Wenn ein refresh_token erhalten wurde, kann der Endpunkt /oauth/token angefragt werden mit dem refresh_token grant_type und dem refresh token, um ein neuen Access Token zu erhalten.

Die Antwort enthält access_token, id_token, scope, expires_in und token_type.