'How to set TokenValidationParameters.NameClaimType to "username" instead of "name" for Azure AD B2C user?

I have the following code to configure the process of authentication in my ASP.NET MVC web application, including the setting a claim to the user's "name" when validating the user's identity token received by the application.

(Note that I am following this sample code)

public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        CookieSecure = CookieSecureOption.Always
    });

    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        // Generate the metadata address using the tenant and policy information
        MetadataAddress = String.Format(AadInstance, Tenant, DefaultPolicy),

            // These are standard OpenID Connect parameters, with values pulled from web.config
            ClientId = ClientId,
            Authority = Authority,
            PostLogoutRedirectUri = RedirectUri,
            RedirectUri = RedirectUri,

            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                RedirectToIdentityProvider = OnRedirectToIdentityProvider,
                AuthenticationFailed = OnAuthenticationFailed,
                AuthorizationCodeReceived = OnAuthorizationCodeReceived,
            },

            // Specify the claims to validate
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name"
            },

            // Specify the scope by appending all of the scopes requested into one string (separated by a blank space)
            Scope = $"{OpenIdConnectScopes.OpenId} {ReadTasksScope} {WriteTasksScope}"
    });
}

The "name" claim type maps to the user's DisplayName, which is returned when I use the code User.Identity.Name.

How can I get User.Identity.Name to map to the user's Username, like in the below screenshot of an Azure Active Directory B2C user?

enter image description here



Solution 1:[1]


Here is the 2nd half of the answer above, which includes the code changes that were made:

  1. Add the line of code commented with "Added line here" so that the user's ObjectId is claimed:

    private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
    {
        // Extract the code from the response notification
        var code = notification.Code;
    
        string signedInUserID = notification.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
        TokenCache userTokenCache = new MSALSessionCache(signedInUserID, notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase).GetMsalCacheInstance();
        ConfidentialClientApplication cca = new ConfidentialClientApplication(ClientId, Authority, RedirectUri, new ClientCredential(ClientSecret), userTokenCache, null);
    
        ///////////////////////////////////
        // Added line here
        ///////////////////////////////////
        // Add a custom claim to the user's ObjectId ('oid' in the token); Access it with this code: ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("ObjectId").Value
        notification.AuthenticationTicket.Identity.AddClaim(new System.Security.Claims.Claim("ObjectId", signedInUserID));
    
        try
        {
            AuthenticationResult result = await cca.AcquireTokenByAuthorizationCodeAsync(code, Scopes);
        }
        catch (Exception ex)
        {
            MyLogger.LogTrace("Failed to retrieve AuthenticationResult Token for user " + signedInUserID, MyLogger.LogLevel.Critical);
            return;
        }
    }
    
  2. Then later in the web application, when you need to get and use the user's ObjectId, do this:

    try
    {
        string signedInUserObjectId = ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("ObjectId").Value;
    }
    catch (Exception e)
    {
        ... This should never happen, but better safe than sorry ...
    }
    
  3. And lastly, using the Azure AD graph client, you can get the user object using ObjectId, which contains the user name. The specific query you will need is GET https://graph.windows.net/myorganization/users/{user_id}?api-version. You may need to get the UserPrincipalName or a SignInName, depending on your type of user. For more information, see the "Get a user" section here.

Solution 2:[2]

I'm not sure how you can get the username into that property as B2C does not return that value.


You can still get this value but it will take more work. B2C does allow you to return the "User's Object ID" which will come back as claim oid. Sample Token.

You can get the oid claim and then query Azure AD to get the username value. See this SO answer on querying Azure AD.

Return User's Object ID

user's object id app claim screenshot


Azure feedback item: include username in JWT claims

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2