ClaimsPrincipal receiving failure when using EasyAuth to authenticate against AAD in Azure App Service in Asp.Net Core web application

We have a web application built on the Asp.Net core. It does not contain the authentication middleware configured in it.

We host the Azure App Service and use the Authentication / Authorization (EasyAuth) option for authentication using Azure AD.

Authentication works well - we get the necessary headers inserted, and we can see the authenticated identifier in /.auth/me. But the HttpContext.User property is not populated.

Is this a compatibility issue for the Asp.Net kernel? Or am I doing something wrong?

+5
source share
4 answers

Yes, this is a compatibility issue. Unfortunately, ASP.NET Core does not support current authentication information from the IIS module (such as Easy Auth) to the application code. This means that HttpContext.User and similar code will not work, as with normal ASP.NET.

The workaround for now is to call the endpoint of your web application / .auth / me from your server code to get user complaints. You can then cache this data appropriately using the x-ms-client-main-id request header value as the cache key. The call to /.auth/me must be authenticated correctly in the same way that calls to your web application must be authenticated (auth cookie or request header marker).

+7
source

I created custom middleware that populates the User property until it is resolved by the Azure team.

It reads the headers from the Application Service Authentication and creates a user who will be recognized by [Authorize] and have a claim to name .

 // Azure app service will send the x-ms-client-principal-id when authenticated app.Use(async (context, next) => { // Create a user on current thread from provided header if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID")) { // Read headers from Azure var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0]; var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0]; // Create claims id var claims = new Claim[] { new System.Security.Claims.Claim("http://schemas.microsoft.com/identity/claims/objectidentifier", azureAppServicePrincipalIdHeader), new System.Security.Claims.Claim("name", azureAppServicePrincipalNameHeader) }; // Set user in current context as claims principal var identity = new GenericIdentity(azureAppServicePrincipalIdHeader); identity.AddClaims(claims); // Set current thread user to identity context.User = new GenericPrincipal(identity, null); }; await next.Invoke(); }); 
+7
source

I wrote a little basic middleware for this. This will create a personality based on the .auth / me endpoint. An identifier is created in the authentication pipeline so that the attributes and policies [authorize] work with the identifier.

You can find it here:

https://github.com/lpunderscore/azureappservice-authentication-middleware

or on nuget:

https://www.nuget.org/packages/AzureAppserviceAuthenticationMiddleware/

After adding, just add this line to your run:

app.UseAzureAppServiceAuthentication ();

+3
source

The following code decrypts the AAD token from the Azure App Service HTTP header and populates the HttpContext.User request. This is rude because you want to cache the configuration, rather than looking for it for every request:

  OpenIdConnectConfigurationRetriever r = new OpenIdConnectConfigurationRetriever(); ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.Endpoint, r); OpenIdConnectConfiguration config = await configManager.GetConfigurationAsync(); var tokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKeys = config.SigningKeys.ToList(), ValidateIssuer = true, ValidIssuer = config.Issuer, ValidateAudience = true, ValidAudience = options.Audience, ValidateLifetime = true, ClockSkew = new TimeSpan(0, 0, 10) }; JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); ClaimsPrincipal principal = null; SecurityToken validToken = null; string token = context.Request.Headers["X-MS-TOKEN-AAD-ID-TOKEN"]; if (!String.IsNullOrWhiteSpace(token)) { principal = handler.ValidateToken(token, tokenValidationParameters, out validToken); var validJwt = validToken as JwtSecurityToken; if (validJwt == null) { throw new ArgumentException("Invalid JWT"); } if (principal != null) { context.User.AddIdentities(principal.Identities); } } 

It works only for Azure AD. To support other ID providers (Facebook, Twitter, etc.), you will need to find the appropriate headers and figure out how to parse the provider tokens. However, these should only be variations on a given topic.

+2
source

Source: https://habr.com/ru/post/1262405/


All Articles