Microsoft Identity Web
repository·master·Indexed 21 days ago
https://github.com/azuread/microsoft-identity-webA library for ASP.NET Core that simplifies integration with the Microsoft identity platform and Azure AD B2C. It provides reusable classes for web applications, protected web APIs, and daemon applications to handle user authentication and downstream API calls.
What's inside Microsoft Identity Web
- Microsoft Identity Web is a library providing reusable classes to integrate authentication and authorization with the Microsoft identity platform into .NET services. It supports various application types including ASP.NET Core, ASP.NET OWIN, .NET Core, and the .NET Framework.
Overview of Microsoft.Identity.Web.Sidecar
masterThe
Microsoft.Identity.Web.Sidecaris a minimal ASP.NET Core Web API designed to run as a sidecar. It handles Microsoft Entra token acquisition, downstream API calls, and token validation (including for agents).Key capabilities:
- Token Validation: Validates incoming tokens and surfaces their claims.
- Decryption: Decrypts tokens if configured.
- Token Acquisition: Acquires User On-Behalf-Of (OBO) or Application tokens for configured downstream APIs.
Overview of customization in Microsoft.Identity.Web
masterMicrosoft.Identity.Web provides secure defaults for authentication and authorization, but allows for several customization areas. You can customize:
- Configuration: All
MicrosoftIdentityOptions,OpenIdConnectOptions, andJwtBearerOptionsproperties. - Events: OpenID Connect events like
OnTokenValidated,OnRedirectToIdentityProvider, etc. - Token Acquisition: Correlation IDs and extra query parameters.
- Claims: Adding custom claims to the
ClaimsPrincipal. - UI: Sign-out pages and redirect behavior.
- Sign-In: Login hints and domain hints.
Customization Methods
You can use two primary approaches to apply customizations:
Configure<TOptions>: Configures options before they are used.PostConfigure<TOptions>: Configures options after allConfigurecalls have been executed.
Execution Order:
Configure$\rightarrow$Configure$\rightarrow$ ... $\rightarrow$PostConfigure$\rightarrow$PostConfigure$\rightarrow$ ... $\rightarrow$ Options used- Configuration: All
What is Certificateless Authentication (FIC + Managed Identity)?
masterCertificateless authentication is the recommended approach for production applications running on Azure. It uses Federated Identity Credentials (FIC) combined with Azure Managed Identity to authenticate your application without requiring certificates or client secrets.
Instead of managing credentials manually,
Microsoft.Identity.Webhandles the process: it requests a signed assertion from the Azure Managed Identity, exchanges that assertion with Microsoft Entra ID for an access token using the configured FIC trust, and then caches the token for use in downstream API calls.Overview of Token Caching in Microsoft.Identity.Web
masterMicrosoft.Identity.Web caches several types of tokens to improve performance (reducing round trips to Microsoft Entra ID), increase reliability (resilience during outages), and reduce costs (avoiding throttling).
Cached Token Types
Token Type Size Scope Eviction Access Tokens ~2 KB Per (user/app, tenant, resource) Automatic (lifetime-based) Refresh Tokens Variable Per user account Manual or policy-based ID Tokens ~2-7 KB Per user Automatic Application Contexts
- Web apps calling APIs: User tokens for delegated access.
- Web APIs calling downstream APIs: OBO (On-Behalf-Of) tokens.
- Daemon applications: App-only tokens for service-to-service calls.
What is Token Binding with mTLS Proof-of-Possession (mTLS PoP)?
masterToken Binding (mTLS PoP) is an advanced security feature that cryptographically binds access tokens to a specific X.509 certificate (as described in RFC 8705).
How it works:
- Token Acquisition: The client requests a token including the certificate's thumbprint.
- Token Binding: The authorization server issues a token containing a
cnf(confirmation) claim with the certificate's SHA-256 thumbprint (x5t#S256). - API Call: The client sends both the bound token and the client certificate to the downstream API.
- Verification: The API validates that the certificate presented in the TLS connection matches the thumbprint in the token's
cnfclaim.
Security Benefits:
- Token Theft Protection: Stolen tokens cannot be used without the corresponding private key.
- Replay Attack Prevention: Tokens cannot be replayed from different clients.
- Zero Trust Alignment: Binds credentials to specific devices.
What is Token Decryption and when to use it
masterToken decryption is a security feature where Microsoft Entra ID encrypts tokens using your application's public key, and your application decrypts them using its private key. This provides defense-in-depth by protecting token contents in transit and at rest, even if HTTPS is compromised.
Use Token Decryption if you have:
- High-security or compliance requirements (e.g., HIPAA, PCI-DSS).
- A Zero-trust architecture implementation.
- Applications handling extremely sensitive data.
Note: Most applications do not need this, as HTTPS already provides encryption in transit. Token decryption adds complexity and is an additional requirement to your standard client credentials.
How Authorization Policies work in Microsoft.Identity.Web
masterFor complex authorization logic, use ASP.NET Core Authorization Policies. Policies allow you to centralize rules, combine multiple requirements (scopes, roles, and custom claims), and make authorization logic testable and reusable.
Common Patterns:
- Policy with RequireScope: Use
policyBuilder.RequireScope("scope1", "scope2")withinAddAuthorizationto define a named policy. - Default Policy: Set a
DefaultPolicyinAddAuthorizationso that every[Authorize]attribute automatically enforces those requirements. - Combining Requirements: Use
policyBuilder.RequireRole("Admin")alongsideRequireScopeto create multi-factor authorization rules. - Custom Requirements: Use
policyBuilder.AddRequirements(new ScopeAuthorizationRequirement(...))for low-level policy construction.
builder.Services.AddAuthorization(options => { // Pattern 1: Named Policy options.AddPolicy("TodoReadPolicy", policyBuilder => { policyBuilder.RequireScope("read", "access_as_user"); }); // Pattern 2: Default Policy (applies to all [Authorize] attributes) options.DefaultPolicy = new AuthorizationPolicyBuilder() .RequireScope("access_as_user") .Build(); // Pattern 3: Complex Policy options.AddPolicy("AdminPolicy", policyBuilder => { policyBuilder.RequireScope("admin"); policyBuilder.RequireRole("Admin"); policyBuilder.RequireAuthenticatedUser(); }); }); // Usage in Controller [Authorize(Policy = "TodoReadPolicy")] public IActionResult Get() => Ok();- Policy with RequireScope: Use
Understand the Credential Architecture in Microsoft Identity Web
masterMicrosoft Identity Web uses a provider-based architecture to resolve credentials (like client secrets, certificates, or Managed Identity assertions) and wire them into MSAL (Microsoft Authentication Library) for token acquisition.
High-Level Flow
- App requests an authorization header via
DefaultAuthorizationHeaderProvider. - TokenAcquisition service determines if token binding is required.
- CredentialsProvider calls a Credential Loader to resolve the actual credential.
- The resolved credential is passed to MSAL (e.g., via
.WithClientSecret,.WithCertificate, or.WithClientAssertion) to execute the token request.
Credential Type vs. Token Type Support
Credential Source Bearer token mTLS PoP token Certificate (KeyVault, Store, Path, Base64) ✅ WithCertificate✅ WithCertificate+WithMtlsProofOfPossessionClient Secret ✅ WithClientSecret❌ Not supported FIC via MI ( SignedAssertionFromManagedIdentity)✅ WithClientAssertion✅ if SupportsTokenBindingOIDC FIC ( CustomSignedAssertion)✅ WithClientAssertion✅ via GetSignedAssertionWithBindingAsyncManaged Identity (direct) ✅ AcquireTokenForMI✅ WithMtlsProofOfPossession+WithAttestationSupport- App requests an authorization header via
How Federated Identity Credentials (FIC) work with token binding
masterToken binding can be used in conjunction with Federated Identity Credentials (FIC). In these flows, the binding certificate is automatically returned by the inner token acquisition process and flows through to the outer application.
Scenario 1: Final
mtls_poptokenWhen the caller requests
ProtocolScheme = "MTLS_POP", the inner OIDC exchange is performed in token-binding mode. The final access token ismtls_pop, bound to the certificate returned by the inner acquisition.Configuration Example:
{ "AzureAd": { "Instance": "https://login.microsoftonline.com/", "TenantId": "<outer-tenant>", "ClientId": "<outer-client-id>", "ClientCapabilities": [ "cp1" ], "ClientCredentials": [ { "SourceType": "CustomSignedAssertion", "CustomSignedAssertionProviderName": "OidcIdpSignedAssertion", "CustomSignedAssertionProviderData": { "ConfigurationSection": "OidcFicIdp" } } ] }, "OidcFicIdp": { "Instance": "https://login.microsoftonline.com/", "TenantId": "<inner-tenant>", "ClientId": "<inner-client-id>", "ClientCredentials": [ { "SourceType": "StoreWithDistinguishedName", "CertificateStorePath": "CurrentUser/My", "CertificateDistinguishedName": "CN=MyInnerAppCert" } ] } }Note: Register the provider with
services.AddOidcFic();.Scenario 2: Final
Bearertoken using bound client assertionIf you want the client assertion to be sender-constrained (sent as
jwt-popover mTLS) but want the resulting access token to be a regularBearertoken (to avoid affecting downstream APIs), setUseBoundCredential = trueon the outer OIDCCustomSignedAssertioncredential and do not requestMTLS_POP.Configuration Example:
{ "ClientCredentials": [ { "SourceType": "CustomSignedAssertion", "CustomSignedAssertionProviderName": "OidcIdpSignedAssertion", "CustomSignedAssertionProviderData": { "ConfigurationSection": "OidcFicIdp" }, "UseBoundCredential": true } ] }Key Takeaways for FIC + Token Binding
- The binding certificate flows automatically from the inner acquisition to the outer application.
- You do not need to configure a second binding-certificate credential.
UseBoundCredentialis used for theBearertoken scenario.ProtocolScheme = "MTLS_POP"is used for themtls_poptoken scenario.
How to use Correlation IDs for troubleshooting
masterA Correlation ID is a GUID that uniquely identifies an authentication or token acquisition request across your application, the Microsoft Identity platform, MSAL.NET, and Microsoft backend services. These are critical when contacting Microsoft support.
Obtaining Correlation IDs
1. From
AuthenticationResultWhen a token is successfully acquired, the
CorrelationIdis available on the result object.2. From
MsalServiceExceptionIf token acquisition fails, the exception contains a
CorrelationIdthat can be logged or returned to the user.3. Setting a Custom Correlation ID
You can pass a custom correlation ID (such as an
Activity.Current.IdorHttpContext.TraceIdentifier) when calling downstream APIs usingTokenAcquisitionOptions.// Example: Obtaining CorrelationId from MsalServiceException try { var token = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { "user.read" }); } catch (MsalServiceException ex) { _logger.LogError(ex, "Token acquisition failed. CorrelationId: {CorrelationId}, ErrorCode: {ErrorCode}", ex.CorrelationId, ex.ErrorCode); } // Example: Setting a custom CorrelationId for downstream API calls await _downstreamApi.GetForUserAsync<Todo>("TodoListService", options => { options.TokenAcquisitionOptions = new TokenAcquisitionOptions { CorrelationId = Guid.Parse(customCorrelationId) }; });Configure Authority Precedence and Resolution Rules
masterMicrosoft.Identity.Web follows strict rules to prevent configuration conflicts. You must choose one of two approaches. Setting both will cause an
InvalidOperationExceptionat startup.The Two Approaches
- Authority Only: Provide a single
AuthorityURL. The library parses this into an Instance and TenantId. - Instance + TenantId: Provide
InstanceandTenantIdseparately. This is the preferred method for Azure AD (AAD) to enable AAD-specific security and resilience.
Precedence Table
Authority Set Instance Set TenantId Set Result ✅ ❌ ❌ Authority is parsed into Instance + TenantId ❌ ✅ ✅ Instance + TenantId used directly ❌ ✅ ❌ Instance used, tenant resolved at runtime* ✅ ✅ ❌ Throws InvalidOperationException✅ ❌ ✅ Throws InvalidOperationException✅ ✅ ✅ Throws InvalidOperationException❌ ❌ ✅ Invalid configuration *Note: For single-tenant apps, always specify
TenantIdwhen usingInstance.- Authority Only: Provide a single