Autor
Marc Zollingkoffer
Director Software Engineering
SYZYGY Techsolutions
Lesedauer
3 Minuten
Publiziert
30. März 2022
Authentication und Authorization sind oft wesentliche Aspekte einer Softwarelösung. Wenn wir sicherstellen wollen, dass Auth&Auth wie gewünscht implementiert ist, muss getestet werden. Hierzu sind automatisierte Blackbox-Integrationstests ein probates Mittel. Auth-Context-Fakes können dabei hilfreich sein, sind aber nicht trivial umzusetzen. Besser: Die tatsächliche Einbindung des IAM (Identity and Access Management) Providers für die Tests.
In unserem konkreten Fall authentifizieren sich User verschiedener Websites im Rahmen einer SSO-Lösung über Azure ADB2C.
Anbindung Azure ADB2C mit .Net Core
Diese Websites verwenden wiederum ein API, welches sie im Autorisierungs-Kontext des jeweiligen Users konsumieren. Eine Operation des API ist z.B. die Kundendaten (Account) für einen User abzufragen. Dazu reicht die Website das JWT-Auth-Token des bei ihr angemeldeten Users an das API durch. Das API ist in .Net Core implementiert. Der Account-Endpunkt des API sieht dann wie folgt aus:
Durch @Authorize und @RequiresScope wird sichergestellt, dass der Endpunkt im richtigen Auth&Auth-Context angesprochen wird, es sich also um einen authentifizierten User handelt und die Anfrage im entsprechenden Scope erfolgt. User und Scope werden mit Hilfe der Microsoft.Indentity.Web Bibliothek über das JWT-Token aufgelöst.
Wie können wir nun genau diesen Aspekt testen und überprüfen, dass für den User der richtige Account gefunden wird? Eine Möglichkeit bestünde darin, über Fakes den Auth&Auth-Context zu manipulieren, mit dem Vorteil, dass die Azure ADB2C-Dependency weitgehend ignoriert werden kann und die Tests daher als einfache Unit-Tests umgesetzt werden können.
Der Nachteil, wie bei allen Fakes: Es wird nicht mit und gegen das „richtige“ System getestet. Bei einer so komplexen Sache wie IAM basierte Auth&Auth kein ganz risikoloses und auch nicht unbedingt triviales Unterfangen. Außerdem verliert sich dann der gewünschte Blackbox-Charakter unserer Tests (d.h. außer der API-Spezifikation muss für die Tests kein weiteres Wissen über die Implementierung vorliegen).
Wir haben uns daher dafür entschieden, integrativ mit dem „echten“ IAM zu testen. Hierzu müssen die Tests in die Lage versetzt werden, einzelne User gegen das IAM zu authentifizieren.
Die folgenden Bausteine werden benötigt, um unsere Tests herzustellen:
- Eine App im Azure ADB2C-Tenant, die die entsprechenden Scopes bereitstellt. Die App muss die Authentication von Public Client Flows erlauben.
- Test-User müssen im ADB2C-Tenant angelegt werden
- Einen ROPC-User-Flow (Sign in using resource owner password credentials) im ADB2C damit Logins ohne Benutzerinteraktion möglich sind. Dabei ist zu beachten, dass die benötigten Application Claims (z.B. Email) bereitgestellt werden.
- Eine Test-Basis-Klasse mit Fixture für den API-Aufruf und entsprechenden Auth-Calls zum Azure ADB2C. Die Klasse implementiert ein Fluent-API, um eine gute Lesbarkeit der Tests sicherzustellen.
- Die eigentliche Testimplementierung als Ableitung der Test-Basis-Klasse
Am Ende sieht dann ein Test, der z.B. überprüft, ob ein User tatsächlich nur Zugriff auf seine eigenen Account-Daten hat, wie folgt aus:
Die vorgestellte Methode macht es also möglich, den IAM-Provider vollwertig in Integrationstests einzubinden. Dies ist besonders dann sinnvoll, wenn man Auth&Auth-Aspekte im Blackbox-Verfahren verifizieren möchte.
Dass die uns allen bekannte Testpyramide von 2 Entwicklern zu der gleichen Menge an Unit-, Integration- oder Functional-Tests interpretiert wird ist undenkbar. Das ist nicht schlimm, führt es doch zu guten Diskussionen. Nur in einem sind wir uns einig: Gar kein Test ist falsch!
David BrendelSenior Software Developer – SYZYGY Techsolutions
Head of Technology