API braucht Benutzerberechtigungen? Delegierten Scope exponieren

Veröffentlicht am:

APIs sollten Access Tokens nicht nur akzeptieren, weil das Token technisch gueltig ist.

Sie sollten auch pruefen, was der angemeldete Benutzer tun darf.

Fuer benutzerbasierten API-Zugriff ist das Microsoft-Entra-Muster:

Einen delegierten Scope exponieren.

Dieses Muster wird verwendet, wenn:

  • ein Benutzer vorhanden ist
  • eine App eine API im Namen dieses Benutzers aufruft
  • die API Benutzerberechtigungen pruefen muss
  • die Authentifizierung ueber Microsoft Entra ID erfolgt
  • die Autorisierung auf dem scp Claim im Access Token basiert

In diesem Beispiel:

  • CloudTrips API ist die geschuetzte Resource
  • CloudTrips Client ist eine benutzerorientierte Client-App
  • Employee ist der angemeldete Benutzer

Der Client kann eine Web-App, SPA, CLI, mobile App oder Desktop-App sein.

Der wichtige Teil ist immer gleich:

Client fordert Scope an -> Entra stellt Access Token aus -> API validiert aud und scp

Delegierter Scope vs App Role

Ein delegierter Scope beschreibt, was eine Client-App im Namen eines angemeldeten Benutzers tun darf.

In Tokens erscheinen delegierte Berechtigungen in:

scp

Beispiel:

{
  "scp": "Trips.Read"
}

Eine App Role beschreibt rollenbasierte Autorisierung fuer eine Anwendung, einen Benutzer oder eine Gruppe.

In Tokens erscheinen App Roles in:

roles

Verwende delegierte Scopes, wenn die API-Entscheidung von der Berechtigung abhaengt, die der Client fuer den Benutzer angefordert hat.

Verwende App Roles, wenn die App-Entscheidung von der Rolle abhaengt, die dem Benutzer oder der Gruppe zugewiesen ist.

Dasselbe User Token kann beide Claims enthalten:

{
  "scp": "Trips.Read",
  "roles": ["Trip.Approver"]
}

Dann beantworten die Claims unterschiedliche Fragen:

scp

Frage:

Darf dieser Client diese API-Operation fuer den angemeldeten Benutzer aufrufen?

Beispiel:

Read Endpoint erlauben, wenn scp Trips.Read enthaelt.

roles

Frage:

Welche Rolle hat dieser Benutzer oder diese Gruppe in der App?

Beispiel:

Approval-Funktionen anzeigen, wenn roles Trip.Approver enthaelt.

Fuer APIs ist ein haeufiges Muster:

aud pruefen -> Token ist fuer diese API
scp pruefen -> Client hat delegierte Berechtigung
roles pruefen -> Benutzer hat erforderliche Business-Rolle, wenn der Endpoint sie braucht

Dieser Trip konzentriert sich vor allem auf delegierte Scopes und den scp Claim.

CloudTrips API App erstellen

Erstelle zuerst die Resource-Anwendung.

Gehe zu:

Entra ID > App registrations > New registration

Erstelle eine Anwendung:

Name: CloudTrips-API
Supported account types: Single tenant

Diese App Registration repraesentiert die API, die Access Tokens empfaengt und validiert.

Microsoft Entra App-Registrierung mit CloudTrips API als Anwendungsname

Application ID URI setzen

Oeffne in CloudTrips-API:

Expose an API

Setze die Application ID URI:

api://<cloudtrips-api-application-id>

Dieser Wert wird zur API Audience.

Das Access Token sollte diesen Wert spaeter im aud Claim enthalten.

CloudTrips API Expose an API Seite mit konfigurierter Application ID URI

Delegierten Scope hinzufuegen

Waehle in CloudTrips-API:

Add a scope

Erstelle einen delegierten Scope:

Scope name: Trips.Read
Who can consent: Admins and users
Admin consent display name: Read CloudTrips trips
Admin consent description: Allows the app to read CloudTrips trips for the signed-in user.
User consent display name: Read your CloudTrips trips
User consent description: Allows the app to read your CloudTrips trips.
State: Enabled

Damit definierst du eine Benutzerberechtigung, die Client-Apps anfordern koennen.

Add a scope Formular mit Trips.Read und Consent-Anzeigewerten

Nach dem Speichern erscheint der Scope unter:

Scopes defined by this API

Der vollstaendige Berechtigungswert ist:

api://<cloudtrips-api-application-id>/Trips.Read

CloudTrips API Expose an API Seite mit aufgelistetem Trips.Read Scope

Client App erstellen

Erstelle jetzt eine Client-App, die den Scope anfordern wird.

Gehe zu:

Entra ID > App registrations > New registration

Erstelle eine Anwendung:

Name: CloudTrips-Client
Supported account types: Single tenant

Die genaue Plattform haengt vom App-Typ ab.

In diesem Trip soll der Client nur zeigen, dass eine benutzerorientierte App den delegierten Scope anfordern kann.

Microsoft Entra App-Registrierung mit CloudTrips Client als Anwendungsname

API-Berechtigung hinzufuegen

Oeffne in CloudTrips-Client:

API permissions > Add a permission

Waehle:

My APIs > CloudTrips-API > Delegated permissions > Trips.Read

Damit darf die Client-App Trips.Read im Namen des angemeldeten Benutzers anfordern.

CloudTrips Client API permissions Seite mit ausgewaehlter delegierter Berechtigung Trips.Read

Wenn dein Tenant Administratorfreigabe verlangt, klicke:

Grant admin consent

Nach dem Consent sollte der Berechtigungsstatus zeigen, dass Consent fuer den Tenant erteilt wurde.

CloudTrips Client API permissions Seite mit erteiltem Admin Consent fuer Trips.Read

Access Token anfordern

Der Client fordert ein Access Token mit dem vollstaendigen Scope-Wert an:

api://<cloudtrips-api-application-id>/Trips.Read

Der genaue OAuth Flow haengt vom Client-Typ ab:

Client-Typ Typischer Flow
Serverseitige Web-App Authorization Code Flow
SPA Authorization Code Flow mit PKCE
CLI oder Device Device Code Flow
Mobile oder Desktop-App Authorization Code Flow mit PKCE

Der wichtige Request-Wert ist der Scope:

scope=openid profile api://<cloudtrips-api-application-id>/Trips.Read

Access Token pruefen

Decodiere das Access Token.

Fuer delegierten API-Zugriff pruefst du diese Claims:

Claim Bedeutung
aud API, die das Token akzeptieren soll
scp Delegierte Berechtigungen, die dem Client erteilt wurden
sub Stabiler Benutzerbezeichner fuer diese App
tid Tenant ID
iss Token Issuer

Der wichtige Nachweis in diesem Trip ist:

{
  "aud": "api://<cloudtrips-api-application-id>",
  "scp": "Trips.Read"
}

Token in der API validieren

Die API sollte mehr pruefen als nur die Token-Signatur.

Validiere mindestens:

  • Signatur
  • Issuer
  • Audience
  • Ablaufzeit
  • erforderlichen delegierten Scope

Beispiel-Logik:

const audiences = Array.isArray(claims.aud) ? claims.aud : [claims.aud];

if (!audiences.includes('api://<cloudtrips-api-application-id>')) {
  throw new Error('Invalid audience');
}

const scopes = String(claims.scp ?? '').split(' ');

if (!scopes.includes('Trips.Read')) {
  throw new Error('Missing required scope');
}

Wenn das Token gueltig ist und scp=Trips.Read enthaelt, gibt die API die geschuetzten Daten zurueck.

Scopes und Rollen in User Tokens vergleichen

Scopes und Rollen werden oft verwechselt, weil beide in User Access Tokens vorkommen koennen.

Sie sind nicht dasselbe.

scp kommt aus delegierten API-Berechtigungen.

Der Claim sagt, welche Berechtigung die Client-App fuer diesen API-Aufruf erhalten hat.

roles kommt aus App-Role-Zuweisungen.

Der Claim sagt, welche Rolle der angemeldete Benutzer oder seine Gruppe in der Anwendung hat.

Verwende scp fuer API-Berechtigungsgrenzen:

Darf dieser Client GET /trips fuer diesen Benutzer aufrufen?
Erforderlicher Claim: scp enthaelt Trips.Read

Verwende roles fuer App- oder Business-Autorisierung:

Darf dieser Benutzer eine Reise genehmigen?
Erforderlicher Claim: roles enthaelt Trip.Approver

Fuer eine einfache Read API kann scp=Trips.Read ausreichen.

Fuer einen sensiblen Workflow pruefst du beide:

scp enthaelt Trips.Write
roles enthaelt Trip.Manager

Die API sollte trotzdem Tokens ablehnen, die zwar gueltige JWTs sind, aber nicht fuer diese API gueltig sind.

Lehne den Request ab, wenn:

  • aud fuer eine andere API ist
  • scp nicht Trips.Read enthaelt
  • das Token abgelaufen ist
  • das Token aus dem falschen Tenant stammt
  • die Token-Signatur nicht verifiziert werden kann

Beispiele:

403 Invalid audience
403 Missing required scope: Trips.Read
401 Access token is expired

Enterprise-Hinweis

Delegierte Scopes sind Teil des API-Vertrags.

Benenne sie sorgfaeltig.

Gute Scope-Namen beschreiben die API-Berechtigung:

Trips.Read
Trips.Write
Trips.Approve

Vermeide breite Scopes, wenn eine engere Berechtigung moeglich ist.

Fuer Produktion solltest du dokumentieren:

  • welche Clients welchen Scope anfordern duerfen
  • ob User Consent erlaubt ist
  • wann Admin Consent erforderlich ist
  • welche API-Endpunkte welche Scopes verlangen
  • wie fehlende Scopes geloggt und untersucht werden

So wird Autorisierung leichter auditierbar und sicherer zu aendern.