App-Registrierungen App Registrations
Referenz zu Identität, Authentifizierung, Berechtigungen und API-Design für registrierte Anwendungen in Entra ID. Reference for identity, authentication, permissions, and API design for registered applications in Entra ID.
Eine Registrierung erzeugt ein App Object. Zugriff im Tenant erfolgt über Service Principals. One registration creates an app object. Access inside a tenant is represented by service principals.
Client Secrets sind schnell eingerichtet, Zertifikate sind für produktive Workloads sicherer und besser rotierbar. Client secrets are quick to set up, but certificates are safer and easier to rotate for production workloads.
Delegierte Rechte laufen im Kontext eines Benutzers, Anwendungsrechte ohne Benutzerkontext. Delegated permissions run in the context of a user, while application permissions run without a user context.
Portal, PowerShell und Microsoft Graph decken den gesamten CRUD-Lebenszyklus ab. Portal, PowerShell, and Microsoft Graph cover the full CRUD lifecycle.
App-Registrierungen definieren Identität und Token-Ausgabe. Die eigentliche Zuweisung von Zugriff in einem Tenant erfolgt über den zugehörigen Service Principal. App registrations define identity and token issuance. Actual tenant-side access assignment is done through the corresponding service principal.
Was ist eine App-Registrierung? What is an app registration?
Eine App-Registrierung ist die globale Definition einer Anwendung im Home-Tenant. Sie enthält die Client-ID, Redirect URIs, erlaubte Kontotypen, Geheimnisse oder Zertifikate sowie die Definition eigener Scopes und App-Rollen. An app registration is the global definition of an application in its home tenant. It contains the client ID, redirect URIs, supported account types, secrets or certificates, and the definition of custom scopes and app roles.
Typische Szenarien sind Web-Apps, Daemons, Automatisierungen, APIs, mobile Clients oder Integrationen mit Microsoft Graph. Sobald ein anderer Tenant die Anwendung verwendet oder ihr Zugriff gewährt, entsteht dort ein Enterprise-Application-Eintrag beziehungsweise Service Principal. Typical scenarios include web apps, daemons, automations, APIs, mobile clients, or integrations with Microsoft Graph. As soon as another tenant uses the application or grants it access, an enterprise application entry, that is, a service principal, is created there.
- Wichtige Kennungen sind Application (client) ID, Directory (tenant) ID und optional die Object ID. Important identifiers are the Application (client) ID, Directory (tenant) ID, and optionally the object ID.
- Die Plattformwahl bestimmt zulässige Redirect-URI-Formate und Tokenflüsse. The selected platform defines allowed redirect URI formats and token flows.
- Bei APIs steuern Expose an API und App Roles das nachgelagerte Berechtigungsmodell. For APIs, Expose an API and App Roles control the downstream authorization model.
App Object vs. Service Principal App object vs. service principal
Das App Object lebt nur im Home-Tenant und beschreibt die Anwendung selbst. Der Service Principal ist die tenant-lokale Instanz, über die Zuweisungen, Consent und Richtlinien technisch greifen. The app object exists only in the home tenant and describes the application itself. The service principal is the tenant-local instance through which assignments, consent, and policies technically apply.
| Aspekt Aspect | App Object App object | Service Principal Service principal |
|---|---|---|
| Reichweite Scope | Globale Definition Global definition | Tenant-lokale Instanz Tenant-local instance |
| Erzeugung Creation | Beim Registrieren Created during registration | Beim ersten Consent oder manueller Erstellung Created on first consent or manual creation |
| Zuweisungen Assignments | Keine Benutzerzuweisungen No user assignments | Benutzer- und Gruppenzuweisungen User and group assignments |
| Conditional Access Conditional Access | Nicht direkt Not directly | Greift auf Enterprise App Applies to the enterprise app |
| Anmeldeprotokolle Sign-in logs | Nein No | Ja Yes |
| Mandantenanzahl Tenant count | Eins One | Eins pro Tenant One per tenant |
| Eigenschaft Property | Beschreibung Description |
|---|---|
| Reichweite Scope | Globale App-Definition im Home-Tenant Global app definition in the home tenant |
| Lebenszyklus Lifecycle | Bleibt bestehen, auch wenn kein Tenant sie nutzt Persists even if no tenant currently uses it |
| Mandantenbezug Tenant relation | Genau ein App Object pro Registrierung Exactly one app object per registration |
| Instanzen Instances | Kann viele Service Principals in fremden Mandanten erzeugen Can create many service principals in other tenants |
| Konfiguration Configuration | Redirect URIs, Secrets, Zertifikate, Manifest Redirect URIs, secrets, certificates, manifest |
| Berechtigungsziel Permission target | Definiert Rollen und Scopes für Clients Defines roles and scopes for clients |
Erstellen: Portal, PowerShell und Graph Create: portal, PowerShell, and Graph
Navigiere zu Entra ID → App registrations → New registration. Lege Namen, Kontotyp und Redirect URI fest. Go to Entra ID → App registrations → New registration. Define the name, account type, and redirect URI.
Füge unter Authentication die benötigten Plattformen wie Web, SPA oder Mobile/Desktop hinzu. Under Authentication, add the required platforms such as Web, SPA, or Mobile/Desktop.
Füge API permissions hinzu und prüfe, ob Admin Consent erforderlich ist. Add API permissions and verify whether admin consent is required.
Erzeuge möglichst Zertifikate statt Secrets und dokumentiere Ablauf- und Rotationsdaten. Prefer certificates over secrets and document expiry and rotation dates.
Connect-MgGraph -Scopes Application.ReadWrite.All
$app = New-MgApplication `
-DisplayName "EntraRef Demo App" `
-SignInAudience "AzureADMyOrg" `
-Web @{ RedirectUris = @("https://localhost:5001/signin-oidc") }
New-MgServicePrincipal -AppId $app.AppId
Get-MgApplication -ApplicationId $app.Id |
Select-Object Id, AppId, DisplayName
$body = @{
displayName = "EntraRef Graph App"
signInAudience = "AzureADMultipleOrgs"
spa = @{
redirectUris = @(
"http://localhost:3000/auth/callback"
)
}
} | ConvertTo-Json -Depth 5
Invoke-MgGraphRequest -Method POST `
-Uri "https://graph.microsoft.com/v1.0/applications" `
-Body $body `
-ContentType "application/json"
Client Credentials: Secrets vs. Zertifikate Client credentials: secrets vs certificates
Client Secrets sind schnell, aber aus Sicht der Sicherheit die schwächere Option. Zertifikate reduzieren das Risiko von versehentlicher Offenlegung, unterstützen Hardware-Schutz und eignen sich besser für automatisierte Rotation. Client secrets are quick, but from a security standpoint they are the weaker option. Certificates reduce the risk of accidental disclosure, support hardware protection, and are better suited for automated rotation.
| Kriterium Criterion | Secret Secret | Zertifikat Certificate |
|---|---|---|
| Einrichtung Setup | Einfach Simple | Etwas aufwendiger Slightly more involved |
| Sicherheit Security | Niedriger Lower | Höher Higher |
| Ablauf Expiry | Kurz halten Keep short | Planbar mit PKI Managed with PKI |
| Rotation Rotation | Manuell oder per Vault Manual or via vault | Gut automatisierbar Easy to automate |
| Empfehlung Recommendation | Nur für Dev/Test oder Legacy Only for dev/test or legacy | Für Produktion bevorzugt Preferred for production |
- Secrets sollten nie im Quellcode, in Skripten oder in CI-Variablen ohne Secret Store liegen. Secrets should never be stored in source code, scripts, or CI variables without a secret store.
- Nutze Azure Key Vault oder GitHub Actions Secrets in Kombination mit kurzlebigen oder föderierten Identitäten. Use Azure Key Vault or GitHub Actions Secrets together with short-lived or federated identities.
- Plane überlappende Gültigkeiten für Rotation ein, damit keine Downtime entsteht. Plan overlapping validity periods during rotation so that no downtime occurs.
# Neues Secret anlegen
Add-MgApplicationPassword `
-ApplicationId $app.Id `
-PasswordCredential @{
DisplayName = "Prod-Secret-2026H2"
EndDateTime = (Get-Date).AddMonths(6)
}
# Zertifikat hinterlegen
$cert = Get-Item Cert:\CurrentUser\My\THUMBPRINT
Update-MgApplication `
-ApplicationId $app.Id `
-KeyCredentials @(
@{
Type = "AsymmetricX509Cert"
Usage = "Verify"
Key = [System.Convert]::ToBase64String($cert.RawData)
DisplayName = "Prod-Cert-2026"
}
)
Redirect URIs Redirect URIs
Redirect URIs müssen exakt zum Client-Typ passen. Für Web-Apps werden HTTPS-URIs erwartet, bei Single-Page-Apps müssen SPA-Plattformen genutzt werden, und für native Clients gelten spezielle Schemata wie localhost oder eigene URI-Schemes. Redirect URIs must exactly match the client type. Web apps typically require HTTPS URIs, single-page applications must use the SPA platform, and native clients use patterns such as localhost or custom URI schemes.
| Plattform Platform | Typische URI Typical URI | Hinweis Notes |
|---|---|---|
| Web Web | https://app.contoso.com/signin-oidc https://app.contoso.com/signin-oidc | Für vertrauliche Clients, Authorization Code Flow For confidential clients using authorization code flow |
| SPA SPA | http://localhost:3000/auth/callback http://localhost:3000/auth/callback | PKCE aktivieren, keine Client Secrets im Browser Use PKCE, never store client secrets in the browser |
| Mobile/Desktop Mobile/Desktop | http://localhost oder myapp://auth http://localhost or myapp://auth | Public Client, Device Code oder Interactive Flow Public client with device code or interactive flow |
Ein abweichender Pfad, fehlender Slash oder falscher Plattformtyp führt sehr häufig zu AADSTS50011 oder ähnlichen Redirect-Fehlern. A different path, missing slash, or wrong platform type commonly results in AADSTS50011 and related redirect errors.
API Permissions Referenz API permissions reference
Die folgende Tabelle enthält häufig verwendete Microsoft-Graph-Berechtigungen. Die reale Einsetzbarkeit hängt von Authentifizierungsfluss, Rollen im Mandanten und eventuellen Resource Specific Consent-Szenarien ab. The following table lists commonly used Microsoft Graph permissions. Actual usability depends on the authentication flow, tenant roles, and any resource-specific consent scenarios.
| Permission Permission | Typ Type | Admin Consent Admin consent | Typischer Zweck Typical use |
|---|---|---|---|
| User.Read User.Read | Delegiert Delegated | Nein No | Profil des angemeldeten Benutzers lesen Read signed-in user profile |
| User.ReadBasic.All User.ReadBasic.All | Delegiert Delegated | Nein No | Basisprofil aller Benutzer lesen Read basic profile of all users |
| User.ReadWrite User.ReadWrite | Delegiert Delegated | Nein No | Eigenes Profil aktualisieren Update own profile |
| User.ReadWrite.All User.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Benutzerobjekte verwalten Manage user objects |
| User.Invite.All User.Invite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Gastbenutzer einladen Invite guest users |
| Group.Read.All Group.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Gruppen lesen Read groups |
| Group.ReadWrite.All Group.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Gruppen und Mitglieder verwalten Manage groups and membership |
| Directory.Read.All Directory.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Verzeichnisweite Leserechte Directory-wide read access |
| Directory.ReadWrite.All Directory.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Verzeichnisobjekte ändern Modify directory objects |
| Application.Read.All Application.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Anwendungsdefinitionen lesen Read application definitions |
| Application.ReadWrite.All Application.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | App-Registrierungen verwalten Manage app registrations |
| AppRoleAssignment.ReadWrite.All AppRoleAssignment.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | App-Rollen zuweisen Manage app role assignments |
| RoleManagement.Read.Directory RoleManagement.Read.Directory | Delegiert + Anwendung Delegated + Application | Ja Yes | Rollen lesen Read directory roles |
| Policy.Read.All Policy.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Richtlinien lesen Read policies |
| Policy.ReadWrite.ConditionalAccess Policy.ReadWrite.ConditionalAccess | Delegiert + Anwendung Delegated + Application | Ja Yes | Conditional Access verwalten Manage Conditional Access |
| AuditLog.Read.All AuditLog.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Audit- und Sign-In-Logs lesen Read audit and sign-in logs |
| Organization.Read.All Organization.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Mandantinformationen lesen Read tenant information |
| Mail.Read Mail.Read | Delegiert + Anwendung Delegated + Application | Ja Yes | E-Mails lesen Read mail |
| Mail.ReadBasic Mail.ReadBasic | Delegiert Delegated | Nein No | Betreff und Metadaten lesen Read subject and metadata |
| Mail.ReadWrite Mail.ReadWrite | Delegiert + Anwendung Delegated + Application | Ja Yes | E-Mails ändern Modify mail |
| Mail.Send Mail.Send | Delegiert + Anwendung Delegated + Application | Ja Yes | Im Namen des Benutzers senden Send mail as the user |
| Calendars.Read Calendars.Read | Delegiert + Anwendung Delegated + Application | Ja Yes | Kalender lesen Read calendars |
| Calendars.ReadWrite Calendars.ReadWrite | Delegiert + Anwendung Delegated + Application | Ja Yes | Kalender verwalten Manage calendars |
| Files.Read Files.Read | Delegiert Delegated | Nein No | Eigene Dateien lesen Read own files |
| Files.Read.All Files.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Alle Dateien lesen Read all files |
| Files.ReadWrite.All Files.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Alle Dateien schreiben Write all files |
| Sites.Read.All Sites.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | SharePoint Sites lesen Read SharePoint sites |
| Sites.ReadWrite.All Sites.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | SharePoint Sites verwalten Manage SharePoint sites |
| Team.ReadBasic.All Team.ReadBasic.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Teams-Basisdaten lesen Read basic teams data |
| TeamSettings.ReadWrite.All TeamSettings.ReadWrite.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Teams-Einstellungen ändern Change team settings |
| ChannelMessage.Read.All ChannelMessage.Read.All | Delegiert + Anwendung Delegated + Application | Ja Yes | Kanalnachrichten lesen Read channel messages |
| ChannelMessage.Send ChannelMessage.Send | Delegiert Delegated | Nein No | Nachrichten in Kanälen senden Send channel messages |
| openid openid | Delegiert Delegated | Nein No | ID-Token für OIDC ID token for OIDC |
| profile profile | Delegiert Delegated | Nein No | Basisprofil im ID-Token Basic profile in ID token |
| offline_access offline_access | Delegiert Delegated | Nein No | Refresh Token erhalten Obtain refresh token |
Admin Consent vs. User Consent Admin consent vs user consent
Delegierte Rechte mit geringem Risiko können per User Consent akzeptiert werden, sofern der Tenant dies zulässt. Höhere Rechte wie Directory.Read.All oder jede Application Permission erfordern in der Praxis fast immer Administratorzustimmung. Lower-risk delegated permissions can be accepted through user consent if the tenant allows it. Higher privileges such as Directory.Read.All or practically any application permission usually require administrator consent.
- User Consent lässt sich tenantweit einschränken oder auf verifizierte Publisher begrenzen. User consent can be restricted tenant-wide or limited to verified publishers.
- Admin Consent wirkt stets auf den Service Principal im Ziel-Tenant. Admin consent always applies to the service principal in the target tenant.
- Nach Berechtigungsänderungen müssen oft neue Tokens angefordert werden, damit die Claims aktualisiert werden. After permission changes, new tokens often need to be requested so that claims are refreshed.
Token Configuration Token configuration
Unter Token configuration können optionale Claims wie groups, email oder ID-spezifische Attribute hinzugefügt werden. Nutze zusätzliche Claims sparsam, weil größere Tokens Proxy-, Header- oder Gruppen-Overage-Probleme verursachen können. Under Token configuration, optional claims such as groups, email, or ID-specific attributes can be added. Use extra claims sparingly because larger tokens can lead to proxy, header, or group overage issues.
- ID-Token: für Client-Anwendungen, um den Benutzer zu identifizieren. ID token: for client applications to identify the user.
- Access Token: für den Zugriff auf APIs wie Microsoft Graph oder eigene APIs. Access token: for calling APIs such as Microsoft Graph or custom APIs.
- SAML Token: für ältere Enterprise- oder SaaS-Integrationen. SAML token: for older enterprise or SaaS integrations.
Expose an API: Scopes und App Roles Expose an API: scopes and app roles
Wenn die Registrierung eine API repräsentiert, definierst du unter Expose an API den Application ID URI und Delegated Scopes. Für service-zu-service Zugriff werden App Roles verwendet, die Client-Anwendungen als Application Permission anfordern. If the registration represents an API, you define the Application ID URI and delegated scopes under Expose an API. For service-to-service access, use app roles that client applications request as application permissions.
| Element Element | Zweck Purpose | Typisches Beispiel Typical example |
|---|---|---|
| Scope Scope | Delegierter Zugriff mit Benutzerkontext Delegated access with user context | access_as_user access_as_user |
| App Role App role | Anwendungszugriff ohne Benutzerkontext Application access without user context | Files.Read.All for daemon Files.Read.All for daemon |
| Pre-authorized client Pre-authorized client | Vertrauenswürdige Client-App vorautorisieren Pre-authorize a trusted client app | Frontend erhält Scope ohne separaten Consent-Dialog Frontend receives scope without separate consent dialog |
$scopeBody = @{
api = @{
requestedAccessTokenVersion = 2
oauth2PermissionScopes = @(
@{
id = [guid]::NewGuid()
value = "access_as_user"
type = "User"
adminConsentDisplayName = "API im Namen des Benutzers aufrufen"
adminConsentDescription = "Erlaubt den Aufruf der API im Namen des Benutzers."
isEnabled = $true
}
)
}
} | ConvertTo-Json -Depth 10
Invoke-MgGraphRequest -Method PATCH `
-Uri "https://graph.microsoft.com/v1.0/applications/$($app.Id)" `
-Body $scopeBody `
-ContentType "application/json"
Single-Tenant vs. Multi-Tenant Single-tenant vs multi-tenant
Single-Tenant eignet sich für interne Line-of-Business-Anwendungen. Multi-Tenant ist für SaaS oder Partnerlösungen gedacht, bei denen ein fremder Tenant einen eigenen Service Principal erzeugt und Consent erteilt. Single-tenant is suitable for internal line-of-business applications. Multi-tenant is intended for SaaS or partner solutions in which another tenant creates its own service principal and grants consent.
- AzureADMyOrg: nur Benutzer des eigenen Tenants. AzureADMyOrg: only users from the home tenant.
- AzureADMultipleOrgs: alle Entra ID Tenants. AzureADMultipleOrgs: all Entra ID tenants.
- AzureADandPersonalMicrosoftAccount: zusätzlich Microsoft-Konten. AzureADandPersonalMicrosoftAccount: includes personal Microsoft accounts.
Manifest-Felder Manifest fields
| Feld Field | Bedeutung Meaning | Praxis-Hinweis Operational note |
|---|---|---|
| signInAudience signInAudience | Steuert Single-Tenant, Multi-Tenant oder MSA-Unterstützung Controls single-tenant, multi-tenant, or MSA support | Vor Änderung exportieren und versionieren Export and version before changes |
| identifierUris identifierUris | App-ID-URI für APIs App ID URI for APIs | Vor Änderung exportieren und versionieren Export and version before changes |
| replyUrlsWithType replyUrlsWithType | Redirect URIs inkl. Plattformtyp Redirect URIs including platform type | Vor Änderung exportieren und versionieren Export and version before changes |
| requiredResourceAccess requiredResourceAccess | Angeforderte API-Berechtigungen Requested API permissions | Vor Änderung exportieren und versionieren Export and version before changes |
| appRoles appRoles | Anwendungsrollen für Benutzer oder Apps Application roles for users or apps | Vor Änderung exportieren und versionieren Export and version before changes |
| oauth2PermissionScopes oauth2PermissionScopes | Delegierte Scopes bei Expose an API Delegated scopes in Expose an API | Vor Änderung exportieren und versionieren Export and version before changes |
| optionalClaims optionalClaims | Zusätzliche Claims in Tokens Additional claims in tokens | Vor Änderung exportieren und versionieren Export and version before changes |
| groupMembershipClaims groupMembershipClaims | Gruppen in Token aufnehmen Emit groups in tokens | Vor Änderung exportieren und versionieren Export and version before changes |
| knownClientApplications knownClientApplications | Vorausautorisation verbundener Clients Pre-authorize related clients | Vor Änderung exportieren und versionieren Export and version before changes |
| requestedAccessTokenVersion requestedAccessTokenVersion | Token-Version 1 oder 2 Token version 1 or 2 | Vor Änderung exportieren und versionieren Export and version before changes |
PowerShell + Graph CRUD PowerShell + Graph CRUD
Für wiederholbare Betriebsprozesse lohnt sich Automatisierung. Nutze lesende Abfragen für Inventarisierung, PATCH für Konfigurationsänderungen und DELETE nur mit klarer Abhängigkeitsprüfung. For repeatable operational processes, automation is worthwhile. Use read operations for inventory, PATCH for configuration changes, and DELETE only after checking dependencies.
# Read
Get-MgApplication -Filter "displayName eq 'EntraRef Demo App'"
# Update
Update-MgApplication `
-ApplicationId $app.Id `
-DisplayName "EntraRef Demo App - Prod"
# Delete service principal first if required
$sp = Get-MgServicePrincipal -Filter "appId eq '$($app.AppId)'"
if ($sp) {
Remove-MgServicePrincipal -ServicePrincipalId $sp.Id
}
# Delete application
Remove-MgApplication -ApplicationId $app.Id
Verifiziere Publisher, nutze Zertifikate oder Federation statt langlebiger Secrets und dokumentiere jede Permission mit Business-Begründung. Verify the publisher, use certificates or federation instead of long-lived secrets, and document every permission with a business justification.
OAuth 2.0 Flows KomplettreferenzComplete OAuth 2.0 flows reference
Die folgende Referenz bündelt die wichtigsten OAuth 2.0- und OIDC-Flows der Microsoft Identity Platform inklusive Sequenzdiagramm, HTTP-Beispielen und PowerShell-Beispielen.The following reference consolidates the most important OAuth 2.0 and OIDC flows of the Microsoft identity platform, including sequence diagrams, HTTP examples, and PowerShell examples.
| FlowFlow | Geeignet fürBest fit | Wichtige ParameterKey parameters |
|---|---|---|
| Authorization Code FlowAuthorization Code Flow | Vertrauliche Web-AppsConfidential web apps | response_type=code, client_secret oder Zertifikat, redirect_uri, scope, state, nonceresponse_type=code, client_secret or certificate, redirect_uri, scope, state, nonce |
| Authorization Code mit PKCEAuthorization Code with PKCE | SPA, Mobile, DesktopSPA, mobile, desktop | code_challenge, code_challenge_method=S256, code_verifiercode_challenge, code_challenge_method=S256, code_verifier |
| Client Credentials FlowClient Credentials Flow | Daemons und WorkerDaemons and workers | grant_type=client_credentials, scope=.defaultgrant_type=client_credentials, scope=.default |
| Device Code FlowDevice Code Flow | CLI und Geräte ohne BrowserCLI and devices without a browser | device_code, user_code, verification_uri, intervaldevice_code, user_code, verification_uri, interval |
| On-Behalf-Of FlowOn-Behalf-Of Flow | Mehrschichtige APIsMulti-tier APIs | assertion, requested_token_use=on_behalf_of, scopeassertion, requested_token_use=on_behalf_of, scope |
| Implicit Flow (Legacy)Implicit Flow (Legacy) | Nur Legacy-SPAsLegacy SPAs only | response_type=token id_token, response_mode=fragmentresponse_type=token id_token, response_mode=fragment |
| ROPC (Legacy)ROPC (Legacy) | Eng begrenzte Legacy-AutomationTightly constrained legacy automation | grant_type=password, username, password, scopegrant_type=password, username, password, scope |
Authorization Code FlowAuthorization Code Flow
Der Standard-Flow für serverseitige Anwendungen. Der Browser sieht nur den Code; Tokens werden erst im Back-End abgeholt.The default flow for server-side applications. The browser sees only the code; tokens are retrieved in the back end.
Browser -> /authorize: client_id, response_type=code, redirect_uri, scope, state, nonce
Authorization Endpoint -> User: sign-in, MFA, Conditional Access
Authorization Endpoint -> redirect_uri: code, state, session_state
Web App -> /token: grant_type=authorization_code, code, redirect_uri, client_id, client_secret
Token Endpoint -> Web App: access_token, id_token, refresh_token
GET https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/authorize?client_id=11111111-1111-1111-1111-111111111111&response_type=code&redirect_uri=https%3A%2F%2Fapp.contoso.com%2Fsignin-oidc&response_mode=query&scope=api%3A%2F%2Fresource-api%2Fuser.read%20offline_access%20openid%20profile&state=9f0c0d&nonce=7ad2
HTTP/1.1 302 Found
Location: https://app.contoso.com/signin-oidc?code=0.AVAA...&state=9f0c0d&session_state=8b6c...
POST https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&client_id=11111111-1111-1111-1111-111111111111&client_secret=client-secret-value&code=0.AVAA...&redirect_uri=https%3A%2F%2Fapp.contoso.com%2Fsignin-oidc&scope=api%3A%2F%2Fresource-api%2Fuser.read%20offline_access%20openid%20profile
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"scope": "api://resource-api/user.read openid profile offline_access",
"expires_in": 3600,
"access_token": "eyJ...",
"id_token": "eyJ...",
"refresh_token": "0.AVAA..."
}
$token = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{
client_id = $clientId
client_secret = $clientSecret
grant_type = "authorization_code"
code = $authCode
redirect_uri = "https://app.contoso.com/signin-oidc"
scope = "api://resource-api/user.read offline_access openid profile"
}
$token.access_token
Authorization Code mit PKCEAuthorization Code with PKCE
PKCE ist der empfohlene Flow für Public Clients. code_challenge und code_verifier verhindern, dass ein abgefangener Code missbraucht wird.PKCE is the recommended flow for public clients. code_challenge and code_verifier prevent abuse of an intercepted code.
Public Client -> local verifier store: generate code_verifier
Public Client -> /authorize: client_id, response_type=code, redirect_uri, scope, code_challenge, code_challenge_method=S256, state
Authorization Endpoint -> redirect_uri: code, state
Public Client -> /token: grant_type=authorization_code, client_id, code, redirect_uri, code_verifier
Token Endpoint -> Public Client: access_token, refresh_token, id_token
GET https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=22222222-2222-2222-2222-222222222222&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8400&scope=openid%20profile%20offline_access%20api%3A%2F%2Fresource-api%2FTasks.Read&code_challenge=V5n9mR8l3lO2Qp7bj2x3mU3o-V7F2wO_VkL2Z_HS6J4&code_challenge_method=S256&state=pkce123
HTTP/1.1 302 Found
Location: http://localhost:8400/?code=0.AVAA...&state=pkce123
POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&client_id=22222222-2222-2222-2222-222222222222&code=0.AVAA...&redirect_uri=http%3A%2F%2Flocalhost%3A8400&code_verifier=YzY4MzQ1YjQtODU1ZC00OGM0LWJhMGEtZjA3N2FlNDk1Y2Nh
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"scope": "openid profile offline_access api://resource-api/Tasks.Read",
"expires_in": 3600,
"access_token": "eyJ...",
"refresh_token": "0.AVAA...",
"id_token": "eyJ..."
}
$codeVerifier = [Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Minimum 0 -Maximum 256 }))
$sha = [System.Security.Cryptography.SHA256]::Create()
$challengeBytes = $sha.ComputeHash([Text.Encoding]::ASCII.GetBytes($codeVerifier))
$codeChallenge = [Convert]::ToBase64String($challengeBytes).TrimEnd('=') -replace '\+','-' -replace '/','_'
$token = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{
client_id = $clientId
grant_type = "authorization_code"
code = $authCode
redirect_uri = "http://localhost:8400"
code_verifier = $codeVerifier
}
Client Credentials FlowClient Credentials Flow
Es gibt keinen Benutzerkontext. Das Token enthält Application Permissions und wird typischerweise für Graph, interne APIs oder Automatisierung verwendet.There is no user context. The token carries application permissions and is typically used for Graph, internal APIs, or automation.
Daemon -> /token: grant_type=client_credentials, client_id, client_secret or client_assertion, scope=resource/.default
Token Endpoint -> Daemon: access_token
Daemon -> Resource API: Authorization: Bearer access_token
Resource API -> Daemon: app-only authorization decision
POST https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=33333333-3333-3333-3333-333333333333&client_secret=client-secret-value&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ..."
}
$appToken = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{
client_id = $clientId
client_secret = $clientSecret
grant_type = "client_credentials"
scope = "https://graph.microsoft.com/.default"
}
Invoke-RestMethod -Headers @{ Authorization = "Bearer $($appToken.access_token)" } `
-Uri "https://graph.microsoft.com/v1.0/applications?$top=1"
Device Code FlowDevice Code Flow
Das Gerät erhält zuerst device_code und user_code. Der Benutzer bestätigt die Anmeldung auf einem zweiten Gerät.The device receives a device_code and user_code first. The user completes sign-in on a second device.
Device -> /devicecode: client_id, scope
Device Code Endpoint -> Device: user_code, device_code, verification_uri, interval, expires_in
User -> verification_uri: enters user_code and signs in
Device -> /token polling: grant_type=urn:ietf:params:oauth:grant-type:device_code, device_code, client_id
Token Endpoint -> Device: authorization_pending until approval, then access_token and refresh_token
POST https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode
Content-Type: application/x-www-form-urlencoded
client_id=44444444-4444-4444-4444-444444444444&scope=https%3A%2F%2Fgraph.microsoft.com%2FUser.Read%20offline_access
HTTP/1.1 200 OK
{
"device_code": "DAAAABQBAAAAE...",
"user_code": "F7K2-MQ9D",
"verification_uri": "https://microsoft.com/devicelogin",
"expires_in": 900,
"interval": 5,
"message": "Open https://microsoft.com/devicelogin and enter F7K2-MQ9D."
}
POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=44444444-4444-4444-4444-444444444444&device_code=DAAAABQBAAAAE...
HTTP/1.1 400 Bad Request
{ "error": "authorization_pending" }
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"scope": "https://graph.microsoft.com/User.Read offline_access",
"access_token": "eyJ...",
"refresh_token": "0.AVAA..."
}
$deviceCode = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/devicecode" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{ client_id = $clientId; scope = "https://graph.microsoft.com/User.Read offline_access" }
$deviceCode.message
Start-Sleep -Seconds $deviceCode.interval
$token = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{
grant_type = "urn:ietf:params:oauth:grant-type:device_code"
client_id = $clientId
device_code = $deviceCode.device_code
}
On-Behalf-Of FlowOn-Behalf-Of Flow
API A nimmt ein Benutzertoken entgegen und tauscht es für API B in ein neues Downstream-Token um.API A receives a user token and exchanges it for a new downstream token for API B.
Client -> API A: bearer token for API A
API A -> /token: grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, assertion=incoming_token, requested_token_use=on_behalf_of, client_id, client_secret, scope=api://api-b/.default
Token Endpoint -> API A: delegated access_token for API B
API A -> API B: Authorization: Bearer downstream token
POST https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&client_id=55555555-5555-5555-5555-555555555555&client_secret=api-a-secret&assertion=eyJ...&requested_token_use=on_behalf_of&scope=api%3A%2F%2Fapi-b%2F.default
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"expires_in": 3600,
"scope": "api://api-b/.default",
"access_token": "eyJ..."
}
$oboToken = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{
client_id = $apiAClientId
client_secret = $apiAClientSecret
grant_type = "urn:ietf:params:oauth:grant-type:jwt-bearer"
assertion = $incomingAccessToken
requested_token_use = "on_behalf_of"
scope = "api://api-b/.default"
}
$oboToken.access_token
Implicit Flow (Legacy)Implicit Flow (Legacy)
Implicit gibt Tokens direkt an den Browser zurück. Neue Apps sollten auf Authorization Code mit PKCE wechseln.Implicit returns tokens directly to the browser. New applications should move to authorization code with PKCE.
Browser -> /authorize: response_type=token id_token, client_id, redirect_uri, scope, nonce
Authorization Endpoint -> Browser: interactive sign-in
Authorization Endpoint -> redirect_uri#fragment: access_token, id_token, expires_in, state
SPA -> Resource API: bearer access_token
GET https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/authorize?client_id=66666666-6666-6666-6666-666666666666&response_type=token%20id_token&redirect_uri=https%3A%2F%2Flegacyspa.contoso.com%2Fauth&scope=openid%20profile%20api%3A%2F%2Fresource-api%2Fuser.read&nonce=implicit-nonce&response_mode=fragment
HTTP/1.1 302 Found
Location: https://legacyspa.contoso.com/auth#access_token=eyJ...&id_token=eyJ...&token_type=Bearer&expires_in=3600&state=legacy
$authorizeUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/authorize?client_id=$clientId&response_type=token%20id_token&redirect_uri=https%3A%2F%2Flegacyspa.contoso.com%2Fauth&scope=openid%20profile%20api%3A%2F%2Fresource-api%2Fuser.read&nonce=legacy"
Start-Process $authorizeUrl
# Nur für dokumentierte Legacy-Ausnahmen verwenden.
# Use only for documented legacy exceptions.
ROPC (Legacy)ROPC (Legacy)
ROPC umgeht interaktive Kontrollen und ist häufig nicht mit MFA, Passwordless oder Föderation kompatibel.ROPC bypasses interactive controls and is often incompatible with MFA, passwordless, or federation.
Client -> /token: grant_type=password, client_id, username, password, scope
Token Endpoint -> Identity System: validate credentials and policy
Token Endpoint -> Client: access_token, refresh_token, id_token if allowed
Client -> Resource API: bearer access_token
POST https://login.microsoftonline.com/contoso.onmicrosoft.com/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=password&client_id=77777777-7777-7777-7777-777777777777&username=user%40contoso.com&password=P%40ssw0rd%21&scope=openid%20profile%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2FUser.Read
HTTP/1.1 200 OK
{
"token_type": "Bearer",
"scope": "openid profile offline_access https://graph.microsoft.com/User.Read",
"expires_in": 3600,
"access_token": "eyJ...",
"refresh_token": "0.AVAA...",
"id_token": "eyJ..."
}
$ropc = Invoke-RestMethod -Method POST `
-Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
-ContentType "application/x-www-form-urlencoded" `
-Body @{
client_id = $clientId
grant_type = "password"
username = $userName
password = $plainPassword
scope = "openid profile offline_access https://graph.microsoft.com/User.Read"
}
$ropc.access_token
Für neue Anwendungen sollte Authorization Code mit PKCE der Normalfall sein. Implicit und ROPC sind Legacy-Ausnahmen mit Migrationsplan.For new applications, authorization code with PKCE should be the norm. Implicit and ROPC are legacy exceptions that require a migration plan.
Token Deep DiveToken deep dive
Für belastbare Integrationen ist entscheidend, welche Claims ausgewertet werden, wie Refresh Tokens rotieren und warum tokenLifetimePolicy heute nicht mehr das bevorzugte Steuerungsinstrument ist.For resilient integrations, it is crucial to understand which claims are evaluated, how refresh tokens rotate, and why tokenLifetimePolicy is no longer the preferred control mechanism.
Access Token JWT StrukturAccess token JWT structure
| TeilPart | BedeutungMeaning | PrüfungValidation |
|---|---|---|
| HeaderHeader | alg, typ, kid oder x5t beschreiben die Signaturalg, typ, kid, or x5t describe the signature | Nur Discovery/JWKS vertrauenTrust only discovery/JWKS |
| PayloadPayload | Claims wie iss, aud, tid, oid, scp, roles, exp, nbf steuern Akzeptanz und AutorisierungClaims such as iss, aud, tid, oid, scp, roles, exp, and nbf determine acceptance and authorization | aud, iss, tid, ver, exp, nbf immer prüfenAlways validate aud, iss, tid, ver, exp, and nbf |
| SignatureSignature | Schützt vor ManipulationProtects against tampering | Key Rotation kurz cachen und kid beachtenCache key rotation briefly and honor kid |
eyJ0eXAiOiJKV1QiLCJraWQiOiJrZXktaWQifQ.
{
"aud": "api://resource-api",
"iss": "https://login.microsoftonline.com/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/v2.0",
"iat": 1718092800,
"nbf": 1718092800,
"exp": 1718096400,
"azp": "33333333-3333-3333-3333-333333333333",
"scp": "Tasks.Read Tasks.Write",
"oid": "99999999-9999-9999-9999-999999999999",
"tid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"ver": "2.0"
}.
<signature>
ID Token Claims ReferenzID token claims reference
| ClaimClaim | BeschreibungDescription | HinweisNote |
|---|---|---|
| acracr | Auth-Kontext oder Policy-LevelAuthentication context or policy level | MFA/CA-SignalMFA/CA signal |
| acctacct | KontotypinformationAccount type information | OptionalOptional |
| aioaio | Interner Telemetrie-HinweisInternal telemetry hint | Nicht parsenDo not parse |
| altsecidaltsecid | Alternativer SicherheitsbezeichnerAlternate security identifier | Hybrid/FederationHybrid/federation |
| amramr | AuthentifizierungsmethodenAuthentication methods | Beispiel pwd,mfaExample pwd,mfa |
| at_hashat_hash | Hash des Access TokensHash of access token | OIDC HybridOIDC hybrid |
| audaud | Ziel-App/APITarget app/API | Muss passenMust match |
| auth_timeauth_time | Zeitpunkt der PrimärauthentifizierungTime of primary authentication | Für ReauthFor reauth |
| azpazp | Authorized party / ClientAuthorized party / client | Mehrschichtige AppsMulti-tier apps |
| c_hashc_hash | Hash des CodesHash of the code | OIDC HybridOIDC hybrid |
| cnfcnf | BestätigungsclaimConfirmation claim | PoP/MTLSPoP/MTLS |
| ctryctry | BenutzerlandUser country | OptionalOptional |
| emailemail | E-Mail-AdresseEmail address | Nur wenn vorhandenOnly when present |
| employeeidemployeeid | PersonalnummerEmployee ID | OptionalOptional |
| expexp | AblaufzeitExpiration time | Epoch secondsEpoch seconds |
| family_namefamily_name | NachnameFamily name | OIDCOIDC |
| fwdfwd | Forwarding-HinweisForwarding hint | SeltenRare |
| given_namegiven_name | VornameGiven name | OIDCOIDC |
| groupsgroups | Gruppen-IDsGroup IDs | Kann overage auslösenCan trigger overage |
| hasgroupshasgroups | Gruppen-Overage-HinweisGroup overage indicator | Graph nachladenLoad via Graph |
| iatiat | Issued-atIssued-at | Epoch secondsEpoch seconds |
| idpidp | Identity ProviderIdentity provider | Gast/FöderationGuest/federation |
| in_corpin_corp | Internes NetzwerksignalInside corporate network signal | OptionalOptional |
| ipaddripaddr | Client-IPClient IP | SignalabhängigSignal-dependent |
| ississ | IssuerIssuer | Tenant prüfenValidate tenant |
| jtijti | Token-IDToken ID | LoggingLogging |
| login_hintlogin_hint | Login-HinweisLogin hint | OptionalOptional |
| namename | AnzeigenameDisplay name | Nicht für AuthZNot for authZ |
| noncenonce | Replay-SchutzReplay protection | Muss matchenMust match |
| oidoid | Objekt-IDObject ID | Stabiler IdentifikatorStable identifier |
| onprem_sidonprem_sid | On-Prem SIDOn-prem SID | HybridHybrid |
| preferred_usernamepreferred_username | Bevorzugter LoginnamePreferred username | Kann sich ändernCan change |
| pwd_exppwd_exp | Restzeit bis PasswortablaufTime until password expiry | LegacyLegacy |
| pwd_urlpwd_url | Reset-URLReset URL | LegacyLegacy |
| rhrh | Refresh/Session-HinweisRefresh/session hint | OpaqueOpaque |
| rolesroles | App-RollenApp roles | Bei Role AssignmentsFor role assignments |
| scpscp | Delegierte ScopesDelegated scopes | Access TokensAccess tokens |
| sidsid | Session-IDSession ID | Logout-HilfeLogout support |
| sign_in_statesign_in_state | Sign-in ZustandSign-in state | OptionalOptional |
| subsub | SubjektidentifierSubject identifier | OIDC KernclaimOIDC core claim |
| tenant_ctrytenant_ctry | Tenant-LandTenant country | OptionalOptional |
| tenant_region_scopetenant_region_scope | Tenant-RegionTenant region scope | Cloud/GeoCloud/geo |
| tidtid | Tenant-IDTenant ID | Multi-TenantMulti-tenant |
| unique_nameunique_name | Legacy NameLegacy name | V1 TokensV1 tokens |
| upnupn | User Principal NameUser principal name | Nicht immer vorhandenNot always present |
| utiuti | Interne TokeninstanzInternal token instance | LoggingLogging |
| verver | Token-VersionToken version | 1.0 oder 2.01.0 or 2.0 |
| widswids | Directory-Rollen-IDsDirectory role IDs | AdminportaleAdmin portals |
| xms_ccxms_cc | CAE-HinweisCAE hint | OptionalOptional |
| xms_idrelxms_idrel | Identity-RelationshipIdentity relationship | GastkontenGuest accounts |
| xms_pdlxms_pdl | Preferred Data LocationPreferred data location | Workload-abhängigWorkload-specific |
| xms_plxms_pl | PlattformhinweisPlatform hint | Interner SteuerclaimInternal steering claim |
| xms_pdlidxms_pdlid | PDL-IDPDL ID | OptionalOptional |
| xms_stxms_st | Sessiontyp/StatusSession type/status | OptionalOptional |
| xms_tcdtxms_tcdt | Token-ErstellungszeitToken creation time | AnalyseAnalysis |
| xms_tplxms_tpl | Tenant Policy LocationTenant policy location | OptionalOptional |
| ztdidztdid | Zero Trust Device IDZero Trust device ID | GerätebindungDevice binding |
Refresh Tokens: Verhalten, Lifetime, WiderrufRefresh tokens: behavior, lifetime, revocation
| ThemaTopic | DetailsDetails | BetriebsrelevanzOperational relevance |
|---|---|---|
| AusstellungIssuance | Refresh Tokens werden typischerweise bei Authorization Code, PKCE, Device Code und einigen Legacy-Flows mit offline_access ausgestellt.Refresh tokens are typically issued for authorization code, PKCE, device code, and some legacy flows when offline_access is requested. | App-only Client Credentials liefert kein Refresh Token.App-only client credentials does not return a refresh token. |
| RotationRotation | Der zuletzt zurückgegebene Refresh Token sollte stets gespeichert werden, weil Microsoft Tokens rotieren kann.Always store the most recently returned refresh token because Microsoft may rotate them. | Kein absichtliches Reuse alter Tokens.Do not intentionally reuse older tokens. |
| LaufzeitLifetime | SPAs haben meist kürzere Refresh-Token-Fenster; native und vertrauliche Clients längere, aber serverseitig kontrollierte Laufzeiten.SPAs usually have shorter refresh token windows; native and confidential clients have longer, but server-controlled lifetimes. | Nicht auf fixe Tageswerte kodieren.Do not code against fixed day counts. |
| WiderrufRevocation | Passwortänderung, Session-Invalidierung, Conditional Access oder Kontoänderungen können Refresh Tokens ungültig machen.Password resets, session invalidation, Conditional Access, or account changes can invalidate refresh tokens. | invalid_grant sauber behandeln.Handle invalid_grant cleanly. |
| RichtlinienPolicies | tokenLifetimePolicy gilt als veraltet; bevorzugt werden heute Conditional Access Session Controls, Sign-in Frequency und Continuous Access Evaluation.tokenLifetimePolicy is considered deprecated; Conditional Access session controls, sign-in frequency, and Continuous Access Evaluation are preferred today. | Neue Designs nicht auf tokenLifetimePolicy aufbauen.Do not build new designs around tokenLifetimePolicy. |
function Convert-Base64UrlToBytes {
param([string]$Value)
$padded = $Value.Replace('-', '+').Replace('_', '/')
switch ($padded.Length % 4) {
2 { $padded += '==' }
3 { $padded += '=' }
}
[Convert]::FromBase64String($padded)
}
$token = $env:ACCESS_TOKEN
$parts = $token.Split('.')
$header = [Text.Encoding]::UTF8.GetString((Convert-Base64UrlToBytes $parts[0])) | ConvertFrom-Json
$payload = [Text.Encoding]::UTF8.GetString((Convert-Base64UrlToBytes $parts[1])) | ConvertFrom-Json
$header
$payload | Format-List *
Optional Claims, Claims Mapping und GruppenOptional claims, claims mapping, and groups
| KonfigurationConfiguration | BeispielExample | NutzenBenefit |
|---|---|---|
| optionalClaims.idTokenoptionalClaims.idToken | email, upn, auth_time, ctry, tenant_region_scopeemail, upn, auth_time, ctry, tenant_region_scope | Gezielte Anreicherung von ID Tokens.Targeted enrichment of ID tokens. |
| optionalClaims.accessTokenoptionalClaims.accessToken | idtyp, ipaddr, acct, groupsidtyp, ipaddr, acct, groups | Hilfreich für APIs und Telemetrie.Useful for APIs and telemetry. |
| optionalClaims.saml2TokenoptionalClaims.saml2Token | upn, email, family_nameupn, email, family_name | Angleichung von OIDC- und SAML-Ausgabe.Aligns OIDC and SAML output. |
| Claims Mapping Policies für SAMLClaims mapping policies for SAML | Quelle, Transformation, Zielclaim, Konstante, Regexsource, transformation, target claim, constant, regex | SAML-spezifische Namen, Formate und Werte steuern.Control SAML-specific names, formats, and values. |
| groupMembershipClaimsgroupMembershipClaims | None, SecurityGroup, DirectoryRole, ApplicationGroup, AllNone, SecurityGroup, DirectoryRole, ApplicationGroup, All | Bestimmt, welche Gruppen im Token erscheinen.Determines which groups appear in the token. |
| GruppenfilterungGroup filtering | Nur App-zugewiesene Gruppen oder Filter auf Anzeigename/AttributOnly app-assigned groups or filters on display name/attribute | Verhindert Token-Overage und reduziert Größe.Prevents token overage and reduces size. |
Wenn ein Benutzer in sehr vielen Gruppen ist, erscheinen statt vollständiger groups-Liste oft hasgroups oder ein Overage-Hinweis. APIs sollten dann Graph nutzen.When a user belongs to many groups, tokens often contain hasgroups or an overage hint instead of a full groups list. APIs should then query Graph.
Consent Deep DiveConsent deep dive
Consent ist das Zusammenspiel aus Tenant-Setting, Publisher-Vertrauen, Risiko der Berechtigungen und sauberer Scope-Strategie. Besonders bei Multi-Tenant-Apps entscheidet gutes Consent-Design über Akzeptanz und Sicherheit.Consent combines tenant settings, publisher trust, permission risk, and a clean scope strategy. Especially for multi-tenant apps, good consent design determines both acceptance and security.
| BenutzereinwilligungUser consent option | BedeutungMeaning | Typischer EinsatzTypical use |
|---|---|---|
| Nicht zulassenDo not allow | Benutzer dürfen keine App-Consent-Entscheidung treffen.Users cannot make app consent decisions. | Stark regulierte UmgebungenHighly regulated environments |
| Nur verifizierte Publisher und ausgewählte BerechtigungenOnly verified publishers and selected permissions | Empfohlene Balance zwischen Self-Service und Governance.Recommended balance between self-service and governance. | Unternehmen mit zentralem ReviewEnterprises with central review |
| Alle Apps zulassenAllow all apps | Weiteste Einstellung mit höherem Shadow-IT-Risiko.Broadest setting with higher shadow IT risk. | Nur kleine oder isolierte TestumgebungenOnly small or isolated test environments |
Admin Consent WorkflowAdmin consent workflow
| SchrittStep | BeschreibungDescription | PraxispunktOperational tip |
|---|---|---|
| 1. Antrag1. Request | App-Team dokumentiert Business-Zweck, Datenarten, Redirect URIs und gewünschte Scopes.The app team documents business purpose, data types, redirect URIs, and requested scopes. | Owner, Datenklassifikation und Supportkontakt erfassen.Capture owner, data classification, and support contact. |
| 2. Prüfung2. Review | Identity und Security prüfen Least Privilege, Publisher Verification und Redirect-Hygiene.Identity and security review least privilege, publisher verification, and redirect hygiene. | Delegierte und Application Permissions getrennt bewerten.Evaluate delegated and application permissions separately. |
| 3. Genehmigung3. Approval | Ein Admin erteilt tenantweite Zustimmung über Portal, /adminconsent oder Graph.An admin grants tenant-wide consent via the portal, /adminconsent, or Graph. | Wenn möglich zuerst Pilot-Tenant nutzen.Use a pilot tenant when possible first. |
| 4. Nachkontrolle4. Post-check | oauth2PermissionGrants und AppRoleAssignments werden inventarisiert und einem Review-Zyklus zugeordnet.oauth2PermissionGrants and app role assignments are inventoried and assigned to a review cycle. | Ablaufdatum und Review-Termin festlegen.Set an expiration date and review date. |
Publisher VerificationPublisher verification
| ElementElement | Warum relevantWhy it matters | PrüfungValidation |
|---|---|---|
| Verified Publisher BadgeVerified publisher badge | Senkt Phishing-Risiko im Consent-Dialog.Reduces phishing risk in the consent dialog. | MPN, Partner Center und Domänenbesitz korrekt koppeln.Correctly link MPN, Partner Center, and domain ownership. |
| App BrandingApp branding | Name, Logo und Support-URL erhöhen Erkennbarkeit.Name, logo, and support URL improve recognizability. | Keine generischen Logos oder irreführenden Namen.Avoid generic logos or misleading names. |
| Privacy Statement und TermsPrivacy statement and terms | Hilft der Risikoabwägung.Helps with risk assessment. | Links regelmäßig prüfen.Review links regularly. |
Statische, inkrementelle und dynamische Consent-ArtenStatic, incremental, and dynamic consent types
| ArtType | MerkmalCharacteristic | BeispielExample |
|---|---|---|
| StatischStatic | Scopes sind von Beginn an fest vorgesehen.Scopes are defined up front. | openid profile offline_access User.Readopenid profile offline_access User.Read |
| InkrementellIncremental | Zusätzliche Scopes erst anfordern, wenn die Funktion genutzt wird.Request additional scopes only when a feature is used. | Files.Read erst beim ersten DateizugriffRequest Files.Read on first file access |
| DynamischDynamic | Scopes abhängig von Modul, Ziel-API oder Workflow zusammensetzen.Assemble scopes based on module, target API, or workflow. | api://crm-api/Orders.Read nur im BestellmodulRequest api://crm-api/Orders.Read only in the order module |
Consent prüfen und widerrufenReview and revoke consent
| ObjektObject | Wo prüfenWhere to review | WiderrufHow to revoke |
|---|---|---|
| Delegierte ZustimmungDelegated consent | Enterprise App, Graph /oauth2PermissionGrants, Audit LogsEnterprise app, Graph /oauth2PermissionGrants, audit logs | Grant löschen oder Benutzerzustimmung entfernen.Delete the grant or remove user consent. |
| Application PermissionsApplication permissions | App Registration / Enterprise App -> API PermissionsApp registration / enterprise app -> API permissions | Admin consent zurückziehen oder App Role Assignment löschen.Withdraw admin consent or delete the app role assignment. |
| BenutzerzugriffUser access | My Apps, Assignment-Listen, Enterprise App PropertiesMy Apps, assignment lists, enterprise app properties | Assignment entfernen oder Service Principal deaktivieren.Remove the assignment or disable the service principal. |
Connect-MgGraph -Scopes "Application.Read.All","DelegatedPermissionGrant.ReadWrite.All","AppRoleAssignment.ReadWrite.All"
Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants?$top=50"
Invoke-MgGraphRequest -Method GET `
-Uri "https://graph.microsoft.com/v1.0/servicePrincipals/$servicePrincipalId/appRoleAssignedTo?$top=50"
Microsoft Identity Platform EndpunkteMicrosoft identity platform endpoints
Die folgende Tabelle dient als Betriebsreferenz für Discovery, Authentifizierung, Consent und Tokenvalidierung.The following table acts as an operational reference for discovery, authentication, consent, and token validation.
| EndpunktEndpoint | ZweckPurpose | Erforderliche ParameterRequired parameters | AntwortformatResponse format |
|---|---|---|---|
| https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorizehttps://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize | OIDC/OAuth AutorisierungOIDC/OAuth authorization | client_id, response_type, redirect_uri, scope, state, optional nonce/prompt/login_hint/code_challengeclient_id, response_type, redirect_uri, scope, state, optional nonce/prompt/login_hint/code_challenge | 302 Redirect302 redirect |
| https://login.microsoftonline.com/{tenant}/oauth2/v2.0/tokenhttps://login.microsoftonline.com/{tenant}/oauth2/v2.0/token | Tokenausgabe für v2Token issuance for v2 | grant_type plus code, refresh_token, client_secret, code_verifier, assertion oder scopegrant_type plus code, refresh_token, client_secret, code_verifier, assertion, or scope | JSONJSON |
| https://login.microsoftonline.com/{tenant}/oauth2/v2.0/devicecodehttps://login.microsoftonline.com/{tenant}/oauth2/v2.0/devicecode | Startpunkt Device CodeDevice code start | client_id, scopeclient_id, scope | JSONJSON |
| https://login.microsoftonline.com/{tenant}/oauth2/v2.0/logouthttps://login.microsoftonline.com/{tenant}/oauth2/v2.0/logout | AbmeldenSign-out | post_logout_redirect_uri optional, logout_hint optionalpost_logout_redirect_uri optional, logout_hint optional | 302 Redirect302 redirect |
| https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configurationhttps://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration | Discovery MetadatenDiscovery metadata | keinenone | JSONJSON |
| https://login.microsoftonline.com/{tenant}/discovery/v2.0/keyshttps://login.microsoftonline.com/{tenant}/discovery/v2.0/keys | JWKS SignaturschlüsselJWKS signing keys | keinenone | JSON (JWKS)JSON (JWKS) |
| https://graph.microsoft.com/oidc/userinfohttps://graph.microsoft.com/oidc/userinfo | OIDC userinfoOIDC userinfo | Bearer Token mit passenden ScopesBearer token with appropriate scopes | JSONJSON |
| https://login.microsoftonline.com/{tenant}/oauth2/authorizehttps://login.microsoftonline.com/{tenant}/oauth2/authorize | Legacy v1 authorizeLegacy v1 authorize | client_id, response_type, redirect_uri, resource, stateclient_id, response_type, redirect_uri, resource, state | 302 Redirect302 redirect |
| https://login.microsoftonline.com/{tenant}/oauth2/tokenhttps://login.microsoftonline.com/{tenant}/oauth2/token | Legacy v1 tokenLegacy v1 token | grant_type plus resource und flowspezifische Parametergrant_type plus resource and flow-specific parameters | JSONJSON |
| https://login.microsoftonline.com/{tenant}/adminconsenthttps://login.microsoftonline.com/{tenant}/adminconsent | Tenantweite Admin-ZustimmungTenant-wide admin consent | client_id, redirect_uri optional, state optionalclient_id, redirect_uri optional, state optional | 302 Redirect302 redirect |
| https://login.microsoftonline.com/common/oauth2/v2.0/authorizehttps://login.microsoftonline.com/common/oauth2/v2.0/authorize | Multi-Tenant + MSAMulti-tenant + MSA | wie authorizesame as authorize | 302 Redirect302 redirect |
| https://login.microsoftonline.com/organizations/oauth2/v2.0/authorizehttps://login.microsoftonline.com/organizations/oauth2/v2.0/authorize | Nur Arbeits- und SchulkontenWork/school accounts only | wie authorizesame as authorize | 302 Redirect302 redirect |
| https://login.microsoftonline.com/consumers/oauth2/v2.0/authorizehttps://login.microsoftonline.com/consumers/oauth2/v2.0/authorize | Nur Microsoft-KontenMicrosoft accounts only | wie authorizesame as authorize | 302 Redirect302 redirect |
| https://login.microsoftonline.com/{tenant}/federationmetadata/2007-06/federationmetadata.xmlhttps://login.microsoftonline.com/{tenant}/federationmetadata/2007-06/federationmetadata.xml | WS-Fed/SAML MetadatenWS-Fed/SAML metadata | keinenone | XMLXML |
| https://graph.microsoft.com/v1.0/oauth2PermissionGrantshttps://graph.microsoft.com/v1.0/oauth2PermissionGrants | Delegierte Zustimmungen lesenRead delegated grants | Graph Bearer TokenGraph bearer token | JSONJSON |
| https://graph.microsoft.com/v1.0/servicePrincipals/{id}/appRoleAssignedTohttps://graph.microsoft.com/v1.0/servicePrincipals/{id}/appRoleAssignedTo | App Role Assignments lesenRead app role assignments | Graph Bearer Token und servicePrincipalIdGraph bearer token and servicePrincipalId | JSONJSON |