Microsoft Identity Platform Microsoft Identity Platform
Entwicklerreferenz zur Microsoft Identity Platform mit MSAL für JavaScript, .NET, Python, Java, Go und Node, Azure.Identity, Tokenvalidierung, Claims, Conditional Access und OAuth-Flows. Developer reference for the Microsoft Identity Platform with MSAL for JavaScript, .NET, Python, Java, Go, and Node, Azure.Identity, token validation, claims, Conditional Access, and OAuth flows.
Die Microsoft Identity Platform wird erst dann robust genutzt, wenn App-Modell, Berechtigungen, Tokenverhalten, SDK-Caching, Claims-Challenges und Laufzeitvalidierung als zusammenhängendes System verstanden werden. The Microsoft Identity Platform is used robustly only when the app model, permissions, token behavior, SDK caching, claims challenges, and runtime validation are understood as one connected system.
Endpoint, Accounts, App-Modell Endpoint, accounts, app model
Browser und SPA Browser and SPA
Public und Confidential Clients Public and confidential clients
Python, Java, Go, Node Python, Java, Go, Node
DefaultAzureCredential DefaultAzureCredential
Claims, Lifetime, Validation Claims, lifetime, validation
Claims Challenges und PoP Claims challenges and PoP
OAuth, OIDC, OBO, Best Practices OAuth, OIDC, OBO, best practices
Überblick: v2.0 Endpoint und Application Model Overview: v2.0 endpoint and application model
Die Microsoft Identity Platform verwendet den v2.0-Endpoint für OAuth 2.0 und OpenID Connect. Er unterstützt Organisationskonten, persönliche Microsoft-Konten und Multi-Tenant-Szenarien, sofern die App-Registrierung korrekt auf supported account types, Redirect URIs und Permissions abgestimmt ist. The Microsoft Identity Platform uses the v2.0 endpoint for OAuth 2.0 and OpenID Connect. It supports organizational accounts, personal Microsoft accounts, and multi-tenant scenarios if the app registration is aligned correctly for supported account types, redirect URIs, and permissions.
| Thema Topic | Beschreibung Description | Entwicklerhinweis Developer guidance |
|---|---|---|
| Supported Account Types Supported account types | Single tenant, multitenant, persönliche Konten oder Kombination Single tenant, multitenant, personal accounts, or combinations | Früh festlegen, weil es Issuer-Prüfung und UX beeinflusst Choose early because it affects issuer validation and UX |
| Application Object Application object | Globale Definition der App im Home Tenant Global definition of the app in the home tenant | Manifest und Rollen sauber versionieren Version manifest and roles cleanly |
| Service Principal Service principal | Lokale Instanz der App in einem Tenant Local instance of the app in a tenant | Bei Multi-Tenant-Problemen immer auch den Service Principal prüfen For multi-tenant issues always inspect the service principal too |
| Delegated Permissions Delegated permissions | App handelt im Kontext eines Benutzers App acts in the context of a user | Für Frontends und OBO zentral Central for front ends and OBO |
| Application Permissions Application permissions | App handelt ohne Benutzerkontext App acts without a user context | Für Daemons und Automatisierung; Admin Consent nötig For daemons and automation; admin consent is required |
| .default Scope .default scope | Fordert alle statisch zugewiesenen Berechtigungen an Requests all statically assigned permissions | Pflicht für Client Credentials und häufig OBO Required for client credentials and often OBO |
MSAL.js für Browser und SPAs MSAL.js for browsers and SPAs
MSAL.js abstrahiert Auth Code Flow mit PKCE, Token Cache, Multi-Tab-Koordination und Claims-Challenges im Browser. Entscheidend sind Cache-Strategie, Redirect-Modell und robustes Error Handling. MSAL.js abstracts the auth code flow with PKCE, token cache, multi-tab coordination, and claims challenges in the browser. The key decisions are cache strategy, redirect model, and robust error handling.
| Thema Topic | Inhalt Content | Best Practice Best practice |
|---|---|---|
| PublicClientApplication PublicClientApplication | Zentrale Instanz für SPA-Auth Central instance for SPA auth | Nur eine Instanz pro Laufzeitkontext initialisieren Initialize only one instance per runtime context |
| acquireTokenSilent acquireTokenSilent | Bevorzugter Weg für bestehende Sessions Preferred path for existing sessions | Immer zuerst silent versuchen und UI nur bei Bedarf öffnen Always try silent first and open UI only when needed |
| Popup vs Redirect Popup vs redirect | Interaktiver Auth-Flow Interactive auth flow | Redirect ist robuster in restriktiven Browserumgebungen Redirect is more robust in restrictive browser environments |
| Cache Location Cache location | sessionStorage oder localStorage sessionStorage or localStorage | sessionStorage reduziert Persistenzrisiko, localStorage verbessert UX sessionStorage reduces persistence risk; localStorage improves UX |
| BroadcastChannel BroadcastChannel | Synchronisiert Status über Tabs Synchronizes state across tabs | Wichtig für Logout und Token-Erneuerung in Multi-Tab-Szenarien Important for logout and token renewal in multi-tab scenarios |
| InteractionRequiredAuthError InteractionRequiredAuthError | Signalisiert notwendige Benutzerinteraktion Signals that user interaction is required | Zentral behandeln, nicht an jeder Call Site duplizieren Handle centrally rather than duplicating at every call site |
import { PublicClientApplication } from '@azure/msal-browser';
const msal = new PublicClientApplication({
auth: {
clientId: '11111111-1111-1111-1111-111111111111',
authority: 'https://login.microsoftonline.com/common',
redirectUri: 'http://localhost:3000'
},
cache: {
cacheLocation: 'sessionStorage'
}
});
await msal.initialize();
const account = msal.getActiveAccount() ?? msal.getAllAccounts()[0];
try {
const token = await msal.acquireTokenSilent({ account, scopes: ['User.Read'] });
console.log(token.accessToken);
} catch (err) {
if (err.name === 'InteractionRequiredAuthError') {
await msal.acquireTokenRedirect({ scopes: ['User.Read'] });
}
}
window.addEventListener('storage', () => {
const accounts = msal.getAllAccounts();
if (!accounts.length) {
window.location.assign('/signed-out');
}
});
MSAL.NET MSAL.NET
MSAL.NET deckt PublicClientApplication für interaktive Clients und ConfidentialClientApplication für Web-Apps, APIs und Daemons ab. Zertifikatsauthentifizierung, Token Cache Serialization und OBO sind die prägenden Enterprise-Szenarien. MSAL.NET covers PublicClientApplication for interactive clients and ConfidentialClientApplication for web apps, APIs, and daemons. Certificate authentication, token cache serialization, and OBO are the defining enterprise scenarios.
| Typ Type | Einsatz Use case | Hinweis Guidance |
|---|---|---|
| PublicClientApplication PublicClientApplication | Desktop, CLI, Device Code Desktop, CLI, device code | Nur Public Clients ohne Geheimnis verwenden Use only for public clients without a secret |
| ConfidentialClientApplication ConfidentialClientApplication | Web-App, API, Hintergrunddienst Web app, API, background service | Geheimnisse vermeiden und Zertifikate bevorzugen Avoid secrets and prefer certificates |
| Token Cache Serialization Token cache serialization | Persistenter Cache über Sessions oder Nodes Persistent cache across sessions or nodes | Verschlüsselt speichern und mandantenfähig designen Store encrypted and design for multitenancy |
| Certificate Auth Certificate auth | Starke App-Identität ohne Client Secret Strong app identity without a client secret | Rotation früh automatisieren Automate rotation early |
| Managed Identity Managed identity | Azure-hosted Workloads ohne explizite App-Secrets Azure-hosted workloads without explicit app secrets | Bevorzugte Option in Azure Preferred option in Azure |
| On-Behalf-Of On-Behalf-Of | API ruft Downstream-API im Benutzerkontext API calls downstream API in user context | Scopes, consent und issuer validation sauber planen Plan scopes, consent, and issuer validation carefully |
using Microsoft.Identity.Client;
var app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}")
.WithCertificate(cert)
.Build();
var result = await app.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }).ExecuteAsync();
var pca = PublicClientApplicationBuilder
.Create(clientId)
.WithAuthority(AzureCloudInstance.AzurePublic, tenantId)
.WithRedirectUri("http://localhost")
.Build();
var result = await pca.AcquireTokenInteractive(new[] { "User.Read" }).ExecuteAsync();
var userAssertion = new UserAssertion(incomingAccessToken);
var result = await app.AcquireTokenOnBehalfOf(new[] { "api://downstream-api/.default" }, userAssertion)
.ExecuteAsync();
MSAL für Python, Java, Go und Node MSAL for Python, Java, Go, and Node
Die Sprachfamilien folgen denselben Mustern: Public vs. Confidential Client, Silent Cache zuerst, Device Code für headless Interaktion und Zertifikat oder Managed Identity für nicht-interaktive Workloads. Unterschiede liegen vor allem im Laufzeitmodell und in der Cache-Integration. The language families follow the same patterns: public versus confidential client, silent cache first, device code for headless interaction, and certificate or managed identity for non-interactive workloads. Differences are mostly in runtime model and cache integration.
| SDK SDK | Stärke Strength | Praxisnotiz Practical note |
|---|---|---|
| MSAL Python MSAL Python | Schnelle Automation und API-Clients Fast automation and API clients | Device Code und file-basierter Cache sind verbreitet Device code and file-based cache are common |
| MSAL Java MSAL Java | Server- und Enterprise-Anwendungen Server and enterprise applications | Async-Futures sauber kapseln und Cache serialisieren Wrap async futures cleanly and serialize the cache |
| MSAL Go MSAL Go | Cloud-Native Services und Tools Cloud-native services and tools | Context und Retry-Strategie bewusst designen Design context and retry strategy consciously |
| MSAL Node MSAL Node | SSR, Web-Backends und Automatisierung SSR, web back ends, and automation | ConfidentialClient und Cache-Plugin sauber trennen Separate confidential client and cache plugin cleanly |
| Device Code Flow Device code flow | Headless oder Terminal-Szenarien Headless or terminal scenarios | Benutzerhinweise und Timeouts UX-freundlich gestalten Make user prompts and timeouts user-friendly |
| Interactive Browser Interactive browser | Lokale Entwicklung und Testclients Local development and test clients | Produktiv lieber App- oder Systembrowser sauber integrieren In production prefer a clean app- or system-browser integration |
import msal
app = msal.ConfidentialClientApplication(
client_id=client_id,
authority=f'https://login.microsoftonline.com/{tenant_id}',
client_credential=client_secret
)
result = app.acquire_token_for_client(scopes=['https://graph.microsoft.com/.default'])
app = msal.PublicClientApplication(client_id, authority=f'https://login.microsoftonline.com/{tenant_id}')
flow = app.initiate_device_flow(scopes=['User.Read'])
print(flow['message'])
result = app.acquire_token_by_device_flow(flow)
ConfidentialClientApplication app = ConfidentialClientApplication
.builder(clientId, ClientCredentialFactory.createFromSecret(secret))
.authority("https://login.microsoftonline.com/" + tenantId)
.build();
IAuthenticationResult result = app.acquireToken(ClientCredentialParameters
.builder(Set.of("https://graph.microsoft.com/.default"))
.build()).get();
app, _ := confidential.New(clientID, cred)
result, err := app.AcquireTokenByCredential(context.Background(), []string{"https://graph.microsoft.com/.default"})
if err != nil { panic(err) }
fmt.Println(result.AccessToken)
const { ConfidentialClientApplication } = require('@azure/msal-node');
const cca = new ConfidentialClientApplication({
auth: { clientId, authority: `https://login.microsoftonline.com/${tenantId}`, clientSecret }
});
const token = await cca.acquireTokenByClientCredential({ scopes: ['https://graph.microsoft.com/.default'] });
Azure.Identity und DefaultAzureCredential Azure.Identity and DefaultAzureCredential
Azure.Identity standardisiert Authentifizierung für Azure-SDKs. DefaultAzureCredential bildet eine Credential Chain aus EnvironmentCredential, ManagedIdentityCredential, AzureCliCredential und weiteren Quellen. In Azure ist Managed Identity fast immer vorzuziehen. Azure.Identity standardizes authentication for Azure SDKs. DefaultAzureCredential forms a credential chain out of EnvironmentCredential, ManagedIdentityCredential, AzureCliCredential, and other sources. In Azure, managed identity is almost always preferable.
| Credential Credential | Wofür What for | Empfehlung Recommendation |
|---|---|---|
| EnvironmentCredential EnvironmentCredential | CI/CD oder lokale Konfiguration via Variablen CI/CD or local configuration via variables | Nur in sicheren Secret Stores nutzen Use only with secure secret stores |
| ManagedIdentityCredential ManagedIdentityCredential | Azure-hosted Ressourcen Azure-hosted resources | Standardwahl für produktive Azure-Workloads Default choice for production Azure workloads |
| AzureCliCredential AzureCliCredential | Lokale Entwicklung mit az login Local development with az login | Ideal für Dev, nicht für Produktion Ideal for dev, not for production |
| VisualStudioCodeCredential VisualStudioCodeCredential | Entwicklerumgebungen Developer environments | Bequem, aber tenantübergreifende Tests bewusst steuern Convenient, but control cross-tenant tests consciously |
| ChainedTokenCredential ChainedTokenCredential | Eigene Reihenfolge explizit definieren Define your own order explicitly | Sinnvoll, wenn DefaultAzureCredential zu breit ist Useful when DefaultAzureCredential is too broad |
| Ordering Ordering | Kette probiert mehrere Quellen nacheinander The chain tries multiple sources in order | Fehlerbilder dokumentieren, damit Fallbacks erklärbar bleiben Document failure patterns so fallbacks remain explainable |
using Azure.Identity;
using Azure.Storage.Blobs;
var credential = new DefaultAzureCredential();
var client = new BlobServiceClient(new Uri(storageUrl), credential);
var containers = client.GetBlobContainers();
const { DefaultAzureCredential } = require('@azure/identity');
const credential = new DefaultAzureCredential();
const token = await credential.getToken('https://graph.microsoft.com/.default');
console.log(token.token);
Tokenarten, Claims und Validierung Token types, claims, and validation
Entwickler müssen Access Tokens, ID Tokens und Refresh Tokens strikt unterscheiden. Genauso wichtig sind Claim-Interpretation, Lifetime-Verhalten, Signing Keys, Issuer-Prüfung und optionale Claims wie acct, ctry, email oder onprem_sid. Developers must clearly separate access tokens, ID tokens, and refresh tokens. Equally important are claim interpretation, lifetime behavior, signing keys, issuer validation, and optional claims such as acct, ctry, email, or onprem_sid.
| Thema Topic | Beschreibung Description | Entwicklerregel Developer rule |
|---|---|---|
| Access Token Access token | Für APIs bestimmt, nicht für UI-Anzeige Meant for APIs, not for UI display | Nur API-seitig validieren und konsumieren Validate and consume only on the API side |
| ID Token ID token | Authentifiziert den Benutzer gegenüber dem Client Authenticates the user to the client | Nicht als API-Token missbrauchen Do not misuse it as an API token |
| Refresh Token Refresh token | Dient Token-Erneuerung Used for token renewal | Nie an Browser-JavaScript exponieren, wenn vermeidbar Never expose to browser JavaScript when avoidable |
| Standard Claims Standard claims | sub, aud, iss, iat, exp, nbf, nonce sub, aud, iss, iat, exp, nbf, nonce | Claims immer gegen das konkrete Protokollszenario interpretieren Interpret claims in the context of the specific protocol scenario |
| Optional Claims Optional claims | acct, email, ctry, ipaddr, onprem_sid acct, email, ctry, ipaddr, onprem_sid | Nur anfordern, wenn fachlich wirklich benötigt Request only when truly needed |
| Token Lifetime Token lifetime | Standardlaufzeiten plus CAE- und Policy-Einfluss Default lifetimes plus CAE and policy influence | Immer mit möglicher vorzeitiger Invalidierung rechnen Always assume possible early invalidation |
| Signing Keys Signing keys | JWKS und Schlüsselrotation JWKS and key rollover | Schlüssel regelmäßig aktualisieren und Cache TTL respektieren Refresh keys regularly and respect cache TTL |
| Issuer Validation Issuer validation | Einzel- oder Multi-Tenant-Issuer korrekt prüfen Validate single- or multi-tenant issuer correctly | Multi-Tenant-Apis nicht nur auf common vertrauen lassen Do not let multitenant APIs trust only common |
{
"aud": "api://contoso-api",
"iss": "https://login.microsoftonline.com/contoso/v2.0",
"sub": "AAAAAAAAAAAAAAAAAAAAAA",
"exp": 1735689600,
"xms_cc": ["cp1"],
"roles": ["Invoice.Read.All"]
}
const jwksClient = require('jwks-rsa');
const jwt = require('jsonwebtoken');
const client = jwksClient({ jwksUri: `${authority}/discovery/v2.0/keys` });
function getKey(header, callback) { client.getSigningKey(header.kid, (err, key) => callback(err, key.getPublicKey())); }
jwt.verify(token, getKey, { audience: apiAudience, issuer: expectedIssuer });
Conditional Access, CAE und Proof of Possession Conditional Access, CAE, and proof of possession
Moderne Clients und APIs müssen Claims-Challenges verstehen. Conditional Access kann Step-up Authentication oder Auth Context erzwingen, CAE signalisiert vorzeitige Token-Invalidierung, und PoP bindet Tokens zusätzlich an Anfragen oder Schlüsselmaterial. Modern clients and APIs must understand claims challenges. Conditional Access can force step-up authentication or auth context, CAE signals early token invalidation, and PoP additionally binds tokens to requests or key material.
| Thema Topic | Worum es geht What it means | Entwicklerreaktion Developer response |
|---|---|---|
| Claims Challenge Claims challenge | API fordert zusätzliche Ansprüche oder stärkere Authentifizierung API requests additional claims or stronger auth | WWW-Authenticate auslesen und mit claims erneut anfordern Parse WWW-Authenticate and request again with claims |
| Step-up Authentication Step-up authentication | Höhere Assurance für sensible Aktionen Higher assurance for sensitive actions | UI-Fluss für erneute Anmeldung klar gestalten Provide a clear UI flow for reauthentication |
| Auth Context Auth context | Anwendungsspezifische CA-Anforderung Application-specific CA requirement | Kritische Features gezielt an höheren Kontext binden Bind critical features to higher auth context selectively |
| Continuous Access Evaluation Continuous Access Evaluation | Token kann vor exp ungültig werden Token may become invalid before exp | 401 mit xms_cc sauber behandeln Handle 401 with xms_cc properly |
| xms_cc Claim xms_cc claim | Signalisiert CAE-fähigen Kontext Signals a CAE-capable context | Nicht blind voraussetzen, sondern prüfen Do not assume blindly; inspect it |
| Proof of Possession Proof of possession | cnf bindet Token an Schlüssel oder Request cnf binds the token to a key or request | Für hohe Sicherheitsanforderungen interessant, aber komplexer im Betrieb Interesting for high-security scenarios but more complex operationally |
try {
await callApi(accessToken);
} catch (err) {
const claims = err?.claims;
if (claims) {
await msal.acquireTokenRedirect({ scopes: ['api://contoso-api/access'], claims });
}
}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer authorization_uri="https://login.microsoftonline.com/common/oauth2/v2.0/authorize", error="insufficient_claims", claims="{...}"
Scopes, App Roles, Protokolle und Best Practices Scopes, app roles, protocols, and best practices
OAuth 2.0, OIDC, Device Code, Client Credentials, OBO, ROPC, SAML Bearer und Well-Known Endpoints gehören zum Werkzeugkasten. Sichere Implementierungen bevorzugen moderne Flows, Managed Identity, strikte Tokenvalidierung und klare Autorisierung über Scopes oder Rollen. OAuth 2.0, OIDC, device code, client credentials, OBO, ROPC, SAML bearer, and well-known endpoints belong to the toolbox. Secure implementations prefer modern flows, managed identity, strict token validation, and clear authorization through scopes or roles.
Bevorzuge Managed Identity vor Secrets, rotiere Zertifikate automatisch, validiere Tokens serverseitig gegen Audience und Issuer, und mache Rollen- oder Scope-Autorisierung explizit im Code sichtbar. Sicherheit in der Identity Platform entsteht aus vielen kleinen, konsequenten Entscheidungen. Prefer managed identity over secrets, rotate certificates automatically, validate tokens server-side against audience and issuer, and make role or scope authorization explicit in code. Security on the identity platform emerges from many small, consistent decisions.
| Bereich Area | Beispiel Example | Best Practice Best practice |
|---|---|---|
| Authorization Code + PKCE Authorization code + PKCE | Standard für Browser und mobile Clients Standard for browser and mobile clients | Implicit Flow vermeiden Avoid the implicit flow |
| Client Credentials Client credentials | Daemon-zu-API ohne Benutzer Daemon-to-API without a user | .default und Zertifikate oder Managed Identity nutzen Use .default plus certificates or managed identity |
| On-Behalf-Of On-behalf-of | API zu Downstream-API im Benutzerkontext API to downstream API in user context | Delegierte Berechtigungen sauber designen Design delegated permissions cleanly |
| Device Code Device code | CLI und headless Szenarien CLI and headless scenarios | Benutzerführung deutlich und timeoutfest machen Make user guidance clear and timeout-safe |
| ROPC ROPC | Legacy-Ausnahmefall Legacy exception case | Wenn möglich vollständig vermeiden Avoid completely where possible |
| SAML Bearer SAML bearer | Spezielle Föderationsszenarien Special federation scenarios | Nur verwenden, wenn Business- oder Legacy-Zwang besteht Use only when business or legacy constraints require it |
| Well-Known Endpoints Well-known endpoints | OpenID Metadata und JWKS OpenID metadata and JWKS | Metadaten automatisiert abrufen statt statisch zu hinterlegen Retrieve metadata automatically instead of hardcoding it |
| App Roles App roles | Rollen im Manifest und roles-Claim Roles in the manifest and the roles claim | Backend-Autorisierung explizit auf Rollen oder Scopes aufbauen Build backend authorization explicitly on roles or scopes |
{
"appRoles": [
{
"allowedMemberTypes": ["User"],
"displayName": "Invoice Reader",
"id": "22222222-2222-2222-2222-222222222222",
"isEnabled": true,
"value": "Invoice.Read.All"
}
]
}
GET https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0/.well-known/openid-configuration
GET https://login.microsoftonline.com/contoso.onmicrosoft.com/discovery/v2.0/keys
def require_role(claims, required):
roles = claims.get('roles', [])
if required not in roles:
raise PermissionError('Missing role')