Did you know that you can navigate the posts by swiping left and right?

Basic Auth mit ASP.NET Core MVC

28 Dec 2016 . category: C# . Kommentare
#ASP.NET #Basic Authentication #.NET CORE #REST #Attribute #C# #Azure #MVC

Basic Authentication ist eine der einfachsten und gängigsten Authentifizierungsmehtoden im Internet. Die Art und Weise wie diese Authentifizierung funktioniert ist in der RFC 2617, HTTP Authentication: Basic and Digest Access Authentication spezifiziert. Die aktuelle Version von ASP.NET Core MVC kommt von Hause aus ohne Basic Authenication, da dies inperformant (Bei jedem HTTP-Request muss die Authentifizierung durchlaufen werden) ist und hohe sicherheitsrisiken mit sich bringt (Benutzername und Passwort werden im Klartext versendet). Aufgrund der Sicherheitsrisiken ist es nicht nur dringend empfohlen, sondern unvermeidlich eine verschlüsselte Verbinung via HTTPS zum Server aufzubauen.Wenn wir unsere REST-Api auf Microsoft Azrue als App Service hosten, bekommen wir direkt ein gültiges HTTPS-Zertifikat für unsere Anwendung “Out of the Box”. Für Lösungen die woanders gehostet werden, bietet Let’s Encrypt eine kostenlose Alternative um an gültige Zertifikate für HTTPS zu kommen. Es gibt also keine Ausreden mehr ;)!
Wie dem auch sei, die bessere alternative für eine sichere und performatere Lösung sind JSON Web Token (JWT), die in der RFC 7519 spezifiziert sind und das Authentifizierungsschema Bearer verwenden.

Trotzdem aller Nachteile der Basic Authentication gegenüber neuerer Technologien gibt es heute noch viele gute Gründe, Basic Authentication zu verwenden:

  • Einfache Authentifizierung für prototypische Implementierungen
  • Von vielen Webbrowsern unterstützt (Eingabedialog für Benutzername und Kennwort)
  • Auf HTTP-Protokoll-Ebene leicht zu implementieren/ debuggen
  • Unterstützung von bestehenden, auf Basic Authentifizierung basierenden, (Legacy-)Anwendungen

Aus diesen Gründen möchte ich zeigen, wie einfach man ein eigenes C#-Attribute implementieren kann, dass ähnlich wie das AuthorizeAttribute von ASP.NET MVC funktioniert.

Aufbau eines HTTP Requests

Um die Basis dafür zu schaffen, schauen wir uns zuerst den Aufbau eines beliebigen HTTP-Requests mit Basic Authentifizierung an:

In diesem HTTP-Request finden wir den Authorization HTTP Header. Der Wert des Authorization-Schlüssels lautet “Basic dXNlcm5hbWU6cGFzc3dvcmQ=”. Das Wort “Basic” vermittelt den Server, dass ein Client versucht sich mit der Basic-Authentifizierung am Server zu authenthifizieren. Getrennt von dem Schlüsselwort “Basic” und einem Leerzeichen folgt ein Token, indem Benutzername und Kennwort zu finden sind. Wer an dieser Stelle glaubt, dass es sich hierbei um eine verschlüsselte oder gehashte Zeichenkettte habdelt, die nicht ohne weiteres in Klartext umgewandelt werden kann, liegt an dieser Stelle falsch. Genau gesagt handelt es sich hier bei um eine Base64 kodierte Zeichenkette, die Problemlos wieder in einen Klartext umgewandelt werden kann.

Wie zu erkennen ist, sind Benutzername und Kennwortt getrennt durch einen Doppelpukt aneinander gereiht und in ergeben als Base64 kodierte Zeichenkette den Basic Token für die Authentifizierung.

Statische Authentifizierung

Die Authentifizierung mit statischen Zugangsdaten funktioniert ganz einfach, allerdings bietet sie nicht viel Spielraum, denn die Zugangsdaten sind hart in den Quellcode integriert.

Um wie im oberen Beispiel zu erreichen, den Get()-Methode des _AuthController_s mit der Basic Authentifizierung auszustatten, muss man lediglich das BasicAuthenticationAttribute verwenden und als Parameter die Zugangsdaten übergeben. Als Ergebnis wird die Methode unserer REST API nun geschützt. Testen können wir das, indem wir einen HTTP Request absenden. Ich verwende dazu häufig Tools wie Fiddler oder Postman, die es ermöglichen auf HTTP-Protokollebene Anfragen auszuführen und die Antworten anzuzeigen. Mein Test sieht wie folgt aus:

Dabei erhalte ich folgende Antwort vom Server:

Wie man sieht, war ich authorisiert meine Anfrage an die REST API durchzuführen. Der erkannte Benutzername lautet someone@example.com.

UserManager Authentifizierung

Da die statische Authentifizierung oft nicht flexibel genug ist, sondern wir häufig den Anwendungsfall haben, dass wir unserer Benutzer mit dem IdentityFramework verwalten, habe ich das Programm dahingehend erweitert. Im folgenden Beispiel sieht man nun, wie die Get()-Methode mit dem UserManagerBasicAuthenticationAttribute bestückt ist. Als Parameter bekommt dieses Attribut noch den Typen unseres IdentityUsers übergeben. Dieser Typ besagt, mit welcher konkreten Model-Klasse wir mit dem IdentityFramework arbeiten möchten. Sofern man das generierte Projekt-Template vom Visual Studio verwendet und nichts anpasst, wird standardmäßig die Klasse ApplicationUser für diesen Zweck generiert. Die Besonderheit dieser Klasse besteht darin, dass sie von IdentityUser erbt.

Bei einem erneuten Test sieht der HTTP Request dann wie folgt aus:

Der Server antwortet wie erwartet, die Authentifizierung gegen das IdentityFramework hat erfolgreich funktioniert.

Was passiert unter der Haube?

Sowohl das BasicAuthenticationAttribute als auch das UserManagerBasicAuthenticationAttribute erben beide von der Basisklasse BasicAuthenticationBaseAttribute. Diese Klasse wiederum erbt von ActionFilterAttribute was dafür sorgt, dass jede für Action die auf einem Contorller ausgeführt wird, zuvor die Methode OnActionExecuting() aufgerufen wird. In dieser Methode führen wir für jeden HTTP Request eine Basic Authentifizierung durch und prüfen, ob die im HTTP Header bereitgstellten Zugangsdaten valide sind. Für den Fall das sie nicht valide sind, wird ein entsprechender HTTP Response generiert. Für die Fall, dass es sich um valide Zugangsdaten handelt, wird der aktuelle Benutzerkontext gesetz und vorerst kein HTTP Repsonse generiert, da anschließend vom MVC Framework die Methode des entsprechenden Controllers aufgerufen wird.

Fazit

Wie bereits erwähnt, ist es in dem meisten Fällen nicht empfehlenswert Basic Authentication zu verwenden. Wenn man jedoch aus einem der besagten Gründe daruf angewiesen ist, ist es trotzdem möglich ASP.NET Core MVC WebApi zusammen mit Basic Authentication zu verwenden.

Der gesamte Quellcode dieses Blogeintrags inklusive steht auf Github bereit: https://github.com/rherlt/Blog-NetCoreBasicAuth


Me

Als Software-Consultant und -Entwickler begleitet Rico täglich Unternehmen auf dem Weg ins mobile Zeitalter. Dabei beschäftigt er sich seit fünf Jahren täglich intensiv mit der Cross-Plattform-Entwicklung unter Xamarin und Anbindung vom Apps an Web Services. Er veranstaltet leidenschaftlich gerne Programmierwettbewerbe für Studenten und organisiert in Berlin Cloud Meetups. Rico ist Microsoft Student Partner (StudentPartners.de), CEO von 2cld, Consultant, Software Architect, Xamarin und .NET Entwickler. In der Freizeit reist er gerne, am liebsten mit seinem Motorrad.