Pexon Consulting | 11 Min. Lesezeit | 10.06.2026
TL;DR
Agent Permissions Entra ID ist die Architektur-Entscheidung, die 2026 zwischen „Production-tauglich“ und „Audit-Albtraum“ entscheidet: Statt mit einem Service-Account-Token gegen alle Backend-Systeme zu sprechen, läuft der Agent mit der Identity des aufrufenden Users über OAuth On-Behalf-Of-Flow. Pexon Consulting baut diese Architektur als Standard-Komponente in jedem produktiven Multi-Backend-Agent-Setup — mit Entra ID, Keycloak oder einem anderen IdP, sauberem Audit-Trail und feingranularer Permissions-Durchsetzung. Claude Managed Agents ergänzt diesen Identity-Layer auf Anwendungsebene mit einem eigenen Permission Policies für Enterprise-Agents-Modell aus always_allow und always_ask.
Warum Service-Accounts in Production nicht reichen
Wir sehen das aktuell wöchentlich: Ein Team hat den ersten Agent gebaut, der mit dem CRM und ERP spricht. Der Agent hat einen Service-Account-Token, mit dem er gegen die Backend-APIs spricht. Funktioniert für den PoC. Drei Monate später kommt der Datenschutz-Audit und stellt fest: Im CRM-Audit-Log steht bei jedem Tool-Call der User „Agent-Service“ — niemand weiß, welcher echte Mitarbeiter die Anfrage gestellt hat.
Das ist nicht akademisch. DSGVO verlangt nachweisbar, wer wann welche personenbezogenen Daten verarbeitet hat. BaFin- und KRITIS-Vorgaben verlangen User-bezogene Audit-Trails. Selbst ohne regulatorischen Druck gibt es klare operative Probleme: Wenn ein Agent versehentlich falsche Daten ändert, kannst du nicht nachvollziehen, in welchem User-Kontext das passiert ist. Bei einem Pilotkunden hatten wir genau diesen Fall — ein Agent hat einen Kundenstamm-Eintrag falsch aktualisiert, im Audit-Log stand nur „Agent-Service“, die Recherche dauerte zwei Tage.
Die saubere Antwort heißt OAuth On-Behalf-Of-Flow: Der User authentifiziert sich beim Agent, der Agent tauscht den User-Token gegen einen Token für das Backend, der Backend sieht den echten User in seinen Logs. Identity wandert durch die Kette mit.
Wie der OBO-Flow konkret aussieht
Architektur in fünf Schritten.
Schritt 1: User-Login. User loggt sich in der Chatbot-App ein, typisch über OIDC-Flow gegen Entra ID. Bekommt ein ID-Token plus Access-Token für die Chatbot-App (Audience: api://chatbot-app).
Schritt 2: User schickt Anfrage an Chatbot. Mit dem Access-Token im Authorization-Header. Die Chatbot-App validiert das Token gegen das JWKS-Endpoint des IdP.
Schritt 3: Agent will gegen das CRM-Backend sprechen. Statt einen eigenen Service-Token zu verwenden, ruft der Agent das Entra-Token-Endpoint mit dem User-Token und der Grant-Type on_behalf_of auf. Bekommt einen neuen Token mit Audience api://crm-api plus User-Identity-Claims.
Schritt 4: Agent ruft das CRM mit dem neuen Token. Das CRM validiert das Token, sieht den User in den Claims, prüft User-spezifische Permissions, gibt die Antwort zurück.
Schritt 5: Audit-Trail überall korrekt. Chatbot-App-Log zeigt User. CRM-Log zeigt User. Bei einem Vorfall ist nachvollziehbar, in welchem User-Kontext was passiert ist.
import msal
import httpx
confidential_client = msal.ConfidentialClientApplication(
client_id="CHATBOT_APP_ID",
client_credential="CHATBOT_APP_SECRET",
authority=f"https://login.microsoftonline.com/{TENANT_ID}",
)
def call_crm_obo(user_token: str, crm_endpoint: str, payload: dict) -> dict:
"""Ruft das CRM On-Behalf-Of des Users."""
obo_response = confidential_client.acquire_token_on_behalf_of(
user_assertion=user_token,
scopes=["api://crm-api/.default"],
)
if "access_token" not in obo_response:
raise Exception(f"OBO-Flow fehlgeschlagen: {obo_response.get('error')}")
crm_token = obo_response["access_token"]
response = httpx.post(
crm_endpoint,
headers={"Authorization": f"Bearer {crm_token}"},
json=payload,
)
return response.json()
App Roles und Delegated Permissions
In Entra ID gibt es zwei Permissions-Konzepte für dieses Setup.
Delegated Permissions sind User-getragene Berechtigungen. Der User loggt sich ein, gibt der Chatbot-App das Recht, in seinem Namen das CRM zu lesen. Bei jedem Tool-Call wird die Permission im Token mitgeschickt — scp: "Customer.Read Order.Read". Das CRM-Backend prüft die Permissions im Token und entscheidet, was der Agent für diesen User tun darf.
App Roles sind tieftragene Rollen, die in Entra ID definiert sind. Beispiel: „CustomerSupportAgent“ mit den Rollen Customer.Read und Order.Read. User werden den Rollen zugeordnet (per Group-Membership oder direkt). Im Token landen die Rollen als roles: ["CustomerSupportAgent"]. Das Backend prüft Rollen statt einzelne Scopes.
Pexon-Default: Delegated Permissions für die Tool-Use-Berechtigungen (was darf der Agent für den User tun), App Roles für die Funktions-Berechtigung (welche Tools darf der Agent dem User überhaupt anbieten). Damit ist klar getrennt: User-Berechtigung am Backend vs Feature-Verfügbarkeit am Frontend.
Pattern in einer MCP-Server-Architektur
Für MCP-Server bauen wir das so:
from fastmcp import FastMCP, Context
from fastmcp.auth import BearerTokenAuth
from fastmcp.exceptions import ToolError
import msal
auth = BearerTokenAuth(
jwks_url=f"https://login.microsoftonline.com/{TENANT_ID}/discovery/v2.0/keys",
issuer=f"https://login.microsoftonline.com/{TENANT_ID}/v2.0",
audience="api://mcp-customer-server",
)
mcp = FastMCP("customer-server", auth=auth)
obo_client = msal.ConfidentialClientApplication(...)
@mcp.tool
def get_customer_details(customer_id: str, ctx: Context) -> dict:
"""Holt Kundendetails On-Behalf-Of des aufrufenden Users."""
user_token = ctx.auth.token
user_email = ctx.auth.claims.get("email")
obo_response = obo_client.acquire_token_on_behalf_of(
user_assertion=user_token,
scopes=["api://crm-api/Customer.Read"],
)
if "access_token" not in obo_response:
raise ToolError(f"User {user_email} hat keine Lese-Berechtigung im CRM.")
crm_token = obo_response["access_token"]
response = httpx.get(
f"{CRM_URL}/customers/{customer_id}",
headers={"Authorization": f"Bearer {crm_token}"},
)
return response.json()
Mehr zur FastMCP-Auth-Integration im FastMCP-Advanced-Blog.
Häufig gestellte Fragen
Funktioniert OBO auch außerhalb von Entra ID?
Ja. Keycloak unterstützt seit Version 22 den Token-Exchange-Flow nach RFC 8693, der funktional OBO entspricht. Okta hat ähnliche Patterns über Custom Authorization Server. Für offene OAuth2-IdPs ist der Token-Exchange-Standard die portierbare Antwort.
Was, wenn das Backend OBO nicht versteht?
Häufiger Fall bei Legacy-Systemen. Wir bauen dann ein Token-Translation-Pattern: Der Agent macht den OBO-Flow gegen einen Pexon-Token-Service, der den User-Token gegen einen Backend-spezifischen Format-Token tauscht (Basic-Auth-Credentials, API-Key mit User-Tagging, etc.). Audit-Trail wird im Token-Service plus im Backend separat geführt.
Wie behandle ich Token-Refresh in lange laufenden Agent-Sessions?
Bei mehrstufigen Agent-Workflows können Token-Lebenszyklen kritisch werden. Wir bauen typisch einen Token-Manager, der Token-Expiry vorhersieht und proaktiv refresht. Bei mehrstufigen Agent-Loops mit MCP-Calls über mehrere Minuten ist das Pflicht.
Was, wenn der User eine Permission nicht hat, die der Agent braucht?
Klare Fehlermeldung an den User. Im Tool-Handler werfen wir einen ToolError mit User-freundlicher Beschreibung. Der Agent gibt das dem User zurück: „Ich kann diese Aktion nicht durchführen, weil dir die Berechtigung X fehlt. Wende dich an deinen Vorgesetzten oder den IT-Help-Desk.“ Damit ist die Permission-Lage transparent statt im Hintergrund maskiert.
Wie viele Tokens sind in einem typischen Agent-Run im Spiel?
Bei einem Multi-Tool-Agent typisch 2-5 verschiedene Backend-Token im Spiel — CRM, ERP, Wissensbasis, ggf. externe APIs. Jeder Tool-Call macht einen eigenen OBO-Flow. Performance-Impact: typisch 50-200ms pro OBO-Aufruf, was bei Multi-Tool-Conversations spürbar wird. Wir cachen OBO-Tokens pro User und Audience für 10-30 Minuten, was den Overhead auf ein vernachlässigbares Niveau drückt.
Nächster Schritt
Wenn dein Agent-Setup heute mit Service-Accounts läuft und der nächste Audit naht: Wir machen einen 60-Minuten-Architektur-Call mit dir und idealerweise dem CISO oder IT-Sicherheits-Beauftragten. Du beschreibst die Backend-Landschaft und das IdP, wir skizzieren den OBO-Setup mit Festpreis-Sprint.
Verwandte Themen
→AKS für regulierte Branchen: KRITIS- und BaFin-konforme Plattform
→Agent Registry im Unternehmen: Discovery für 50+ Agents
→Universal MCP Client: Chatbot trifft 50 Custom-Apps



