Skip to content

C# und Microsoft Entra ID: Rollenbasierte APIs absichern

Praxis-Tutorial: ASP.NET Core, Microsoft Entra ID, JWT, App-Rollen und Berechtigungsprüfung. Eine API ist nicht schon deshalb geschützt, weil ein Benutzer sich anmelden konnte. Authentifizierung stellt fest, wer den Aufruf durchführt; Autorisierung entscheidet, welche Aktion dieser Aufrufer ausführen darf. In diesem Tutorial richten wir eine .NET-Web-API so ein, dass Lese- und Schreibzugriffe getrennt gesteuert werden.

1. Zielbild: Welche Komponenten sind beteiligt?

Wir verwenden zwei Rollen: Api.Reader zum Lesen und Api.Editor zum Schreiben. Eine App-Registrierung beschreibt die geschützte API samt Rollen. Über die zugehörige Unternehmensanwendung werden Benutzer, Gruppen oder Client-Anwendungen zugewiesen. Ein Client fordert ein Access Token für diese API an; die API validiert das Token und prüft vor jedem geschützten Endpunkt die Rolle.

Benutzer oder Dienst → Microsoft Entra ID → Access Token
                                          ↓
                                   ASP.NET Core API
                                   1. JWT validieren
                                   2. Rollen auswerten
                                   3. Ressource freigeben

Wichtig: Ein Token für Microsoft Graph oder eine andere API darf nicht einfach für den eigenen Dienst akzeptiert werden. Die konfigurierte Audience muss zu deiner API passen. Ein ID Token für die Anmeldung ist außerdem kein Ersatz für ein API-Access-Token.

2. Voraussetzungen

  • Ein Microsoft-Entra-Mandant mit Berechtigung, App-Registrierungen und App-Rollen anzulegen.
  • Eine aktuelle, unterstützte .NET-Version und das ASP.NET-Core-Web-API-SDK.
  • Ein Testbenutzer und, für den Dienst-zu-Dienst-Test, optional eine zweite Client-App-Registrierung.
  • Kenntnis über die Mandanten-ID (TenantId) und die Anwendungs-ID (ClientId) der API.

3. API in Microsoft Entra ID registrieren

  1. Öffne Microsoft Entra Admin Center → Entra ID → App-Registrierungen → Neue Registrierung.
  2. Vergib beispielsweise den Namen Demo Orders API und wähle bewusst die unterstützten Kontotypen. Für eine interne Unternehmens-API ist ein einzelner Mandant häufig die einfachste Wahl.
  3. Speichere Verzeichnis-ID (Mandant) und Anwendungs-ID (Client). Beide IDs sind keine Kennwörter.
  4. Unter Eine API verfügbar machen richtest du bei Bedarf eine Application-ID-URI ein. Sie identifiziert die Ressource, die der Client aufruft.

Lege jetzt unter App-Rollen zwei Rollen an. Gib als Value exakt Api.Reader und Api.Editor an. Der Value ist später der Wert des roles-Claims und muss genau mit der Zeichenfolge im C#-Code übereinstimmen. Wähle unter „Zulässige Mitgliedertypen“ passend Benutzer/Gruppen und/oder Anwendungen aus: Eine Benutzerrolle und eine Anwendungsberechtigung sind unterschiedliche Zuweisungen.

4. Rollen zuweisen: Unternehmensanwendung statt nur Registrierung

Öffne Entra ID → Unternehmensanwendungen → Demo Orders API → Benutzer und Gruppen. Weise dem Testbenutzer die Rolle Api.Reader zu. Für Schreibrechte erhält ein zweiter Testbenutzer oder ein geeigneter berechtigter Benutzer Api.Editor. Beachte, dass die Zuweisung von Gruppen abhängig von der Lizenzierung eingeschränkt sein kann und verschachtelte Gruppen nicht automatisch übernommen werden. Nach Änderungen benötigst du ein neu ausgestelltes Token; bereits ausgegebene Tokens ändern sich nicht rückwirkend.

Für Client Credentials (Dienst zu Dienst) erhält dagegen die aufrufende Anwendung unter API-Berechtigungen die Anwendungsberechtigung deiner API. Nach der erforderlichen Administratorzustimmung erscheint die erlaubte App-Rolle im Access Token für die API. Verwechsle diesen Ablauf nicht mit delegierten Scopes, die eine Anwendung im Namen eines angemeldeten Benutzers nutzt.

5. ASP.NET-Core-API erstellen

Ein schlankes Beispiel auf Basis von Minimal APIs:

dotnet new webapi -n EntraRolesApi
cd EntraRolesApi
dotnet add package Microsoft.Identity.Web

Trage in appsettings.json die tatsächlichen IDs deiner API ein. Diese Datei enthält hier keine Secrets:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "YOUR-TENANT-ID",
    "ClientId": "YOUR-API-CLIENT-ID"
  }
}

Für APIs, die mit einem bestimmten Mandanten arbeiten, setzt das Microsoft-Identity-Web-Paket die JWT-Bearer-Authentifizierung auf Basis dieser Einstellungen auf. Passe die Konfiguration bei mehreren Mandanten, abweichenden Audiences oder komplexeren Clienttypen gezielt an, statt die Validierung abzuschalten.

6. Rollenprüfung tatsächlich im Code erzwingen

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

builder.Services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("OrdersRead",
        policy => policy.RequireAuthenticatedUser()
                        .RequireRole("Api.Reader", "Api.Editor"));
    options.AddPolicy("OrdersWrite",
        policy => policy.RequireAuthenticatedUser()
                        .RequireRole("Api.Editor"));
});

var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/api/orders", () =>
    Results.Ok(new[] { new { Id = "10042", Status = "Open" } }))
   .RequireAuthorization("OrdersRead");

app.MapPost("/api/orders", () =>
    Results.Accepted("/api/orders/10043"))
   .RequireAuthorization("OrdersWrite");

app.Run();

Der POST-Handler ist absichtlich ein Autorisierungsbeispiel: Er speichert keinen Auftrag und implementiert keine Fachlogik. Die Policy OrdersRead erlaubt hier beide Rollen, während OrdersWrite ausschließlich Api.Editor akzeptiert. Rollenwerte müssen mit den tatsächlich ausgegebenen Claims übereinstimmen. Prüfe im jeweiligen Setup außerdem den konfigurierten Role-Claim-Typ, falls die Middleware Claims anders abbildet.

7. 401 und 403 unterscheiden

401 Unauthorized heißt in diesem Zusammenhang, dass der Aufruf nicht korrekt authentifiziert wurde – beispielsweise weil das Token fehlt, abgelaufen ist oder für eine andere Audience ausgestellt wurde. 403 Forbidden heißt, dass die Identität bekannt ist, aber die nötige Berechtigung für den Endpunkt fehlt. Eine Rolle nur im Frontend zu verstecken reicht nicht: Benutzer können HTTP-Endpunkte direkt aufrufen.

8. Was beim Token-Test zu prüfen ist

  1. Ein Aufruf ohne Bearer-Token muss einen geschützten Endpunkt abweisen.
  2. Ein Token für eine andere Ressource muss ebenfalls abgewiesen werden.
  3. Ein gültiges Token ohne die benötigte App-Rolle darf den geschützten Schreibendpunkt nicht erreichen.
  4. Api.Reader darf lesen, aber nicht schreiben.
  5. Api.Editor darf entsprechend der definierten Policy lesen und schreiben.
  6. Nach einer Rollenänderung muss mit einem neu ausgestellten Access Token getestet werden.

Für Diagnosezwecke darfst du Claims in einer lokalen Testumgebung kontrollieren; speichere rohe produktive Tokens nicht im Anwendungslog und gib sie niemals in Support-Tickets weiter.

9. Typische Fehler und ihre Ursachen

  • Token gültig, dennoch 403: Die App-Rolle wurde nicht zugewiesen, das Token ist veraltet oder der Rollenwert stimmt nicht exakt.
  • Unerwartetes 401: Falsche Audience, falscher Tenant, falscher Token-Typ oder fehlender Bearer-Header.
  • Keine App-Rolle bei Client Credentials: Prüfe API-Berechtigungen, den Mitgliedertyp „Anwendungen“ und die Administratorzustimmung.
  • Zu breite Berechtigungen: Trenne Leserechte von Schreibrechten und definiere für administrative Aktionen eine weitere eigenständige Policy.
  • Rollenprüfung nur im UI: Implementiere die Kontrolle zusätzlich serverseitig an jedem sensiblen Endpunkt.

10. Produktionscheckliste

Setze HTTPS voraus, verwende kurze und angemessene Token-Laufzeiten, validiere Issuer und Audience, erzwinge Rollen beziehungsweise Scopes am Endpunkt und dokumentiere die Rollenvergabe. Für Anwendungen sind Zertifikate oder verwaltete Identitäten in der Regel besser als langlebige Client-Secrets. Vermeide übermäßige Berechtigungen und lege ein Verfahren für das Entfernen von Zugriffsrechten fest. Für feinere Mandanten- oder Datensatzberechtigungen genügen globale App-Rollen allein oft nicht; prüfe zusätzlich die fachliche Berechtigung auf die konkret angeforderte Ressource.

Weiterführende Microsoft-Dokumentation

Kommentare (0)

Noch keine Kommentare. Schreibe den ersten Beitrag zur Diskussion.

Kommentar schreiben