ID令牌缺少特定于Azure AD v2.0的可选声明 [英] Azure AD v2.0-specific optional claims missing from ID Token

查看:60
本文介绍了ID令牌缺少特定于Azure AD v2.0的可选声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Microsoft Identity Web-NuGet添加可选声明,以在NET Core 3.1 WebApp中进行用户身份验证.阅读MS Docs,似乎唯一需要做的步骤就是在Azure的App Registration Manifest文件中声明可选声明.但是,当使用两个不同的应用程序(我自己的代码和一个MS项目示例)测试登录过程时,成功登录后从Azure返回时似乎没有将可选声明添加到ID令牌中,即它们根本不存在在调试中查看令牌详细信息时.

我不确定如何诊断该问题以及在何处跟踪问题,即我是否缺少Azure安装程序中的所有必需步骤?

侧面注意:只是要确认这是我要接收其他声明的jwt ID令牌,而不是用于调用图形或另一个Web API端点的jwt访问令牌.

MS Docs参考:

  1. 我必须在Azure中将配置文件"范围添加为代理"类型,添加到Azure Webapp API权限中.

最后一个尚未解决的问题是,尽管我可以看到在调试过程中出现的声明,但是我无法弄清楚如何检索声明值.

在下面的方法中,使用Debug时可以看到所需的声明,但无法弄清楚如何检索值:

  public void OnGet(){var username = HttpContext.User.Identity.Name;var forename = HttpContext.User.Claims.FirstOrDefault(c => c.Type =="given_name")?. Value;var surname = HttpContext.User.Claims.FirstOrDefault(c => c.Type =="family_name")?. Value;_logger.LogInformation("+" +用户名+已请求索引页面");} 

Debug屏幕截图显示了给定名称&存在family_name:

我尝试了使用Claims主体尝试不同的代码示例来尝试获取值,但没有任何工作对我有用.对于知道所需语法的人来说,希望最终的谜语相当简单,正如我们现在所说的,现在存在所需的可选声明,只是不知道如何实际获取值.

解决方案

非常感谢'Dhivya G-MSFT Identity'的帮助(请参见我的原始问题下方的注释),下面的方法现在允许我从以下位置访问所需的索赔值:成功登录后从Azure返回的令牌ID.

 公共无效的OnGet(){var username = HttpContext.User.Identity.Name;var forename = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?. Value;var surname = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?. Value;_logger.LogInformation("+" +用户名+已请求索引页面");} 

I'm trying to add optional claims using Microsoft Identity Web - NuGet for user authentication in NET Core 3.1 WebApp. Reading the MS Docs, it seems that the only steps needed are to declare the optional claims within the App Registration Manifest file in Azure. But when testing the login process using two different apps (my own code and an MS project example) it looks like the optional claims are not being added to the ID Token when returned from Azure following a successful login i.e they're not present at all when viweing the token details in Debug.

I'm not sure how to diagnose this and where to trace the issue i.e am I missing any required steps in Azure setup?

Side Note: Just to confirm it is the jwt ID Token I want to receive the additional claims, NOT the jwt access token used for calling the graph or another Web API endpoint.

MS Docs reference: v2.0-specific optional claims set

Below is the extract from the Manifest file: (note I've even declared the "accessTokenAcceptedVersion": 2, given that optional claims I'm using are not available in ver.1, which if the above was left at default 'null' value then Azure will assume we're using legacy ver.1 - a possible gotcha)

"accessTokenAcceptedVersion": 2,
"optionalClaims": {
    "idToken": [
        {
            "name": "given_name",
            "source": "user",
            "essential": false,
            "additionalProperties": []
        },
        {
            "name": "family_name",
            "source": "user",
            "essential": false,
            "additionalProperties": []
        }
    ],
    "accessToken": [],
    "saml2Token": []
},

Extract from startup class:

public void ConfigureServices(IServiceCollection services)
    {
        // Added to original .net core template.
        // ASP.NET Core apps access the HttpContext through the IHttpContextAccessor interface and 
        // its default implementation HttpContextAccessor. It's only necessary to use IHttpContextAccessor 
        // when you need access to the HttpContext inside a service.
        // Example usage - we're using this to retrieve the details of the currrently logged in user in page model actions.
        services.AddHttpContextAccessor();

        // DO NOT DELETE (for now...)
        // This 'Microsoft.AspNetCore.Authentication.AzureAD.UI' library was originally used for Azure Ad authentication 
        // before we implemented the newer Microsoft.Identity.Web and Microsoft.Identity.Web.UI NuGet packages. 
        // Note after implememting the newer library for authetication, we had to modify the _LoginPartial.cshtml file.
        //services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
        //    .AddAzureAD(options => Configuration.Bind("AzureAd", options));

        ///////////////////////////////////

        // Add services required for using options.
        // e.g used for calling Graph Api from WebOptions class, from config file.
        services.AddOptions();

        // Add service for MS Graph API Service Client.
        services.AddTransient<OidcConnectEvents>();

        // Sign-in users with the Microsoft identity platform
        services.AddSignIn(Configuration);

        // Token acquisition service based on MSAL.NET
        // and chosen token cache implementation
        services.AddWebAppCallsProtectedWebApi(Configuration, new string[] { Constants.ScopeUserRead })
            .AddInMemoryTokenCaches();

        // Add the MS Graph SDK Client as a service for Dependancy Injection.
        services.AddGraphService(Configuration);

        ///////////////////////////////////

        // The following lines code instruct the asp.net core middleware to use the data in the "roles" claim in the Authorize attribute and User.IsInrole()
        // See https://docs.microsoft.com/aspnet/core/security/authorization/roles?view=aspnetcore-2.2 for more info.
        services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
        {
            // The claim in the Jwt token where App roles are available.
            options.TokenValidationParameters.RoleClaimType = "roles";
        });

        // Adding authorization policies that enforce authorization using Azure AD roles. Polices defined in seperate classes.
        services.AddAuthorization(options =>
        {
            options.AddPolicy(AuthorizationPolicies.AssignmentToViewLogsRoleRequired, policy => policy.RequireRole(AppRole.ViewLogs));
        });

        ///////////////////////////////////

        services.AddRazorPages().AddMvcOptions(options =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
        }).AddMicrosoftIdentityUI();

        // Adds the service for creating the Jwt Token used for calling microservices.
        // Note we are using our independant bearer token issuer service here, NOT Azure AD
        services.AddScoped<JwtService>(); 
    }

Sample Razor PageModel method:

public void OnGet()
    {
        var username = HttpContext.User.Identity.Name;
        var forename = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "given_name")?.Value;
        var surname = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "family_name")?.Value;

        _logger.LogInformation("" + username + " requested the Index page");
    }

UPDATE

Getting closer to a solution but not quite there yet. Couple of issues resolved:

  1. I originally created the Tenant in Azure to use B2C AD, even though I was no longer using B2C and had switched to Azure AD. It wasn't until I deleted the tenant and created a new one before I started to see the optional claims come through to the webapp correctly. After creating the new tenant and assigning the tenant type to use Azure AD, I then found that the 'Token Configuration' menu was now available for configuring the optional claims through the UI, it seems that modifying the App manifest is still required as well, as shown above.

  1. I had to add the 'profile' scope as type 'delegated' to the webapp API Permissions in Azure.

The final issue still unresolved is that although I can see the claims present during Debug, I cant figure out how to retrieve the claim values.

In the method below, I can see the required claims when using Debug, but can't figure out how to retrieve the values:

public void OnGet()
    {
        var username = HttpContext.User.Identity.Name;

        var forename = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "given_name")?.Value;
        var surname = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "family_name")?.Value;

        _logger.LogInformation("" + username + " requested the Index page");
    }

Debug Screenshots shows the given_name & family_name are present:

I've tried different code examples using the claims principal to try and get the values out, but nothing is working for me. Hoping this final riddle is fairly simple to someone who knows the required syntax, as said we now have the required optional claims present, its just not knowing how to actually get the values out.

解决方案

Big thanks to 'Dhivya G - MSFT Identity' for their assistance (see comments below my original question) method below now allows me to access the required claim values from the Token ID returned from Azure following successful login.

    public void OnGet()
    {
        var username = HttpContext.User.Identity.Name;

        var forename = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
        var surname = HttpContext.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;

        _logger.LogInformation("" + username + " requested the Index page");
    }

这篇关于ID令牌缺少特定于Azure AD v2.0的可选声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆