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

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

问题描述

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

我不确定如何诊断此问题以及在哪里跟踪问题,即我是否遗漏了 Azure 设置中的任何必需步骤?

旁注:只是为了确认它是我想要接收附加声明的 jwt ID 令牌,而不是用于调用图形或其他 Web API 端点的 jwt 访问令牌.

MS 文档参考:

  1. 我必须将配置文件"范围作为委托"类型添加到 Azure 中的 webapp API 权限.

最后一个仍未解决的问题是,虽然我可以在调试期间看到声明,但我无法弄清楚如何检索声明值.

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

public void OnGet(){var 用户名 = 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("" + 用户名 + "请求索引页");}

调试屏幕截图显示了 given_name &family_name 存在:

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

解决方案

非常感谢 'Dhivya G - MSFT Identity' 的帮助(请参阅我的原始问题下方的评论)下面的方法现在允许我访问所需的声明值成功登录后从 Azure 返回的令牌 ID.

 public void OnGet(){var 用户名 = 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天全站免登陆