簡體   English   中英

ID 令牌中缺少 Azure AD v2.0 特定的可選聲明

[英]Azure AD v2.0-specific optional claims missing from ID Token

我正在嘗試使用 Microsoft Identity Web - NuGet 添加可選聲明,以在 NET Core 3.1 WebApp 中進行用戶身份驗證。 閱讀 MS Docs,似乎唯一需要的步驟是在 Azure 的應用注冊清單文件中聲明可選聲明。 但是,當使用兩個不同的應用程序(我自己的代碼和一個 MS 項目示例)測試登錄過程時,在成功登錄后從 Azure 返回時,似乎沒有將可選聲明添加到 ID 令牌中,即它們根本不存在在調試中查看令牌詳細信息時。

我不確定如何診斷此問題以及在何處跟蹤問題,即我是否缺少 Azure 設置中的任何必需步驟?

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 參考: v2.0 特定的可選聲明集

下面是 Manifest 文件的摘錄:(請注意,我什至聲明了“accessTokenAcceptedVersion”:2,因為我使用的可選聲明在 ver.1 中不可用,如果上述內容保留為默認“null”值然后 Azure 將假設我們使用的是舊版 1 - 一個可能的陷阱)

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

從啟動 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>(); 
    }

示例 Razor PageModel 方法:

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");
    }

更新

越來越接近解決方案,但還沒有完全解決。 解決了幾個問題:

  1. 我最初在 Azure 中創建租戶以使用 B2C AD,即使我不再使用 B2C 並已切換到 Azure AD。 直到我刪除了租戶並創建了一個新租戶,我才開始看到可選聲明正確地傳遞到 webapp。 創建新租戶並分配租戶類型以使用 Azure AD 后,我發現“令牌配置”菜單現在可用於通過 UI 配置可選聲明,似乎仍然需要修改 App 清單,如上圖所示。

在此處輸入圖像描述

  1. 我必須將“配置文件”scope 作為“委托”類型添加到 webapp API 權限中 Azure。

在此處輸入圖像描述

最后一個仍未解決的問題是,雖然我可以在調試期間看到存在的聲明,但我無法弄清楚如何檢索聲明值。

在下面的方法中,我可以在使用 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("" + username + " requested the Index page");
    }

調試屏幕截圖顯示 given_name 和 family_name 存在:

在此處輸入圖像描述

在此處輸入圖像描述

我已經嘗試使用聲明主體嘗試不同的代碼示例來嘗試獲取值,但沒有什么對我有用。 希望這個最后的謎語對於知道所需語法的人來說是相當簡單的,正如我們現在所說的,我們現在有所需的可選聲明,只是不知道如何實際獲取這些值。

非常感謝“Dhivya G - MSFT Identity”的幫助(請參閱我原來的問題下方的評論)方法現在允許我從成功登錄后從 Azure 返回的令牌 ID 訪問所需的聲明值。

    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");
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM