AzureAD / microsoft-identity-web

Helps creating protected web apps and web APIs with Microsoft identity platform and Azure AD B2C
MIT License
676 stars 209 forks source link

ConfidentialClient does not get authenticated when role-claims empty in token #2123

Open michiproep opened 1 year ago

michiproep commented 1 year ago

Microsoft.Identity.Web Library

Microsoft.Identity.Web

Microsoft.Identity.Web version

1.26.0

Web app

Not Applicable

Web API

Protected web APIs (validating tokens)

Token cache serialization

In-memory caches

Description

If I add groups as optional claims with option "Emit groups as role claims" in AzureAd Token Configuration, the resulting token for a client credential flow / confidentialClientApplication might have no roles[] claim.

When sending this token to a web-api which just "RequiresAuthenticatedUser()" the httpContext.User is not populated by the authentication middleware although I can see a valid ClaimsPrincipal within OnTokenValidated=>context.Principal.

As a result, Authorization fails.

Reproduction steps

  1. Setup AzureAd AppRegistration with optional claims "groups" and "emit groups as role claims". (do not assign any groups to the corresponding serivce principal which calls this api at the end)
  2. In code "aquireTokenAsApp"
  3. call Api
  4. =>User not authenticated

Error message

Authorize-Policy => Failure => Do not allow anonymous user

Id Web logs


Relevant code snippets

---

Regression

No response

Expected behavior

Even if a token is missing role claims, the confidentialClient should still get authenticated.

nis-spiir commented 1 year ago

This could be due to the "Roles" claim being mapped incorrectly by Microsoft.Identity.Web.

Might be solved with the code in https://github.com/AzureAD/microsoft-identity-web/pull/2027 ? (or using some rather ugly builder.Services.AddTransient<IClaimsTransformation, RenameRolesClaim>(); code that remaps roles claims:

using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;

public class RenameRolesClaim : IClaimsTransformation
{
    /// <summary>
    /// Rename AAD claims from "roles" to "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
    /// </summary>
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var roles = principal.Claims.Where(claim => claim.Type == "roles").ToList();
        if (roles.Any())
            principal.AddIdentity(new ClaimsIdentity(roles.Select(role => new Claim(ClaimTypes.Role, role.Value))));

        return Task.FromResult(principal);
    }
}
michiproep commented 1 year ago

I'll try but in this case there are no roles at all. well, maybe the scope stays... let's see

kopfsick commented 1 week ago

@michiproep did you ever find a reasonable solution to this? I'm having the same issue. The authentication should still be successful even if there are no specific roles. I got this behavior after updating Microsoft.Identity.Web from 1.7.0 -> 3.1.0.

michiproep commented 1 week ago

@kopfsick No, I did not find a (good) solution. What you can do is adding a dummy role (or empty) within the tokenValidated event. But I agree, this should not be the final solution