在 Azure App Service 驗證中使用使用者身分識別

本文說明使用 App Service 中內建的驗證和授權時,如何使用使用者身分識別。

在應用程式程式碼中存取使用者宣告

針對所有語言架構,App Service 會藉由將宣告插入要求標頭,讓傳入權杖中的宣告 (無論是否來自已驗證的使用者或用戶端應用程式) 可供您的程式碼使用。 外部要求不被允許設定這些標頭,因此僅在由 App Service 設定時,這些標頭才會出現。 某些範例標頭包括︰

標頭 描述
X-MS-CLIENT-PRINCIPAL 可用宣告的 Base64 編碼 JSON 表示法。 如需詳細資訊,請參閱解碼用戶端主體標頭
X-MS-CLIENT-PRINCIPAL-ID 識別提供者所設定呼叫者的識別碼。
X-MS-CLIENT-PRINCIPAL-NAME 識別提供者所設定呼叫者的人類可讀名稱,例如電子郵件地址、使用者主體名稱。
X-MS-CLIENT-PRINCIPAL-IDP App Service 驗證所使用識別提供者的名稱。

提供者權杖也會透過類似的標頭公開。 例如,Microsoft 識別提供者也會視情況設定 X-MS-TOKEN-AAD-ACCESS-TOKENX-MS-TOKEN-AAD-ID-TOKEN

注意

這些應用程式程式碼的標題可能會因不同的語言架構,而以不同的格式呈現,例如小寫或標題字體。

以任何語言或架構撰寫的程式碼可以從這些標頭中取得所需的資訊。 解碼用戶端主體標頭涵蓋此程序。 針對某些架構,平台也提供可能更方便的額外選項。

解碼用戶端主體標頭

X-MS-CLIENT-PRINCIPAL 包含一組完整的可用宣告,作為 Base64 編碼的 JSON。 這些宣告會經過預設的宣告對應程序,因此有些宣告的名稱可能會與您直接處理權杖時看到的名稱不同。 解碼的承載的結構如下:

{
    "auth_typ": "",
    "claims": [
        {
            "typ": "",
            "val": ""
        }
    ],
    "name_typ": "",
    "role_typ": ""
}
屬性 類型​ 描述
auth_typ string App Service 驗證所使用識別提供者的名稱。
claims 物件陣列 物件的陣列,表示可用的宣告。 每個物件都包含 typval 屬性。
typ string 宣告的名稱。 這可能受限於預設宣告對應,而且可能與權杖中包含的對應宣告不同。
val string 宣告的值。
name_typ string 名稱宣告類型,通常是在定義宣告時提供 name 宣告配置資訊的 URI。
role_typ string 角色宣告類型,通常是在定義宣告時提供 role 宣告配置資訊的 URI。

若要處理此標頭,您的應用程式必須解碼承載並逐一查看 claims 陣列,以尋找感興趣的宣告。 將這些項目轉換成應用程式語言架構所使用的表示法可能很方便。 以下是 C# 中此程序的範例,其會建構 ClaimsPrincipal 類型供應用程式使用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http;

public static class ClaimsPrincipalParser
{
    private class ClientPrincipalClaim
    {
        [JsonPropertyName("typ")]
        public string Type { get; set; }
        [JsonPropertyName("val")]
        public string Value { get; set; }
    }

    private class ClientPrincipal
    {
        [JsonPropertyName("auth_typ")]
        public string IdentityProvider { get; set; }
        [JsonPropertyName("name_typ")]
        public string NameClaimType { get; set; }
        [JsonPropertyName("role_typ")]
        public string RoleClaimType { get; set; }
        [JsonPropertyName("claims")]
        public IEnumerable<ClientPrincipalClaim> Claims { get; set; }
    }

    public static ClaimsPrincipal Parse(HttpRequest req)
    {
        var principal = new ClientPrincipal();

        if (req.Headers.TryGetValue("x-ms-client-principal", out var header))
        {
            var data = header[0];
            var decoded = Convert.FromBase64String(data);
            var json = Encoding.UTF8.GetString(decoded);
            principal = JsonSerializer.Deserialize<ClientPrincipal>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
        }

        /** 
         *  At this point, the code can iterate through `principal.Claims` to
         *  check claims as part of validation. Alternatively, we can convert
         *  it into a standard object with which to perform those checks later
         *  in the request pipeline. That object can also be leveraged for 
         *  associating user data, etc. The rest of this function performs such
         *  a conversion to create a `ClaimsPrincipal` as might be used in 
         *  other .NET code.
         */

        var identity = new ClaimsIdentity(principal.IdentityProvider, principal.NameClaimType, principal.RoleClaimType);
        identity.AddClaims(principal.Claims.Select(c => new Claim(c.Type, c.Value)));
        
        return new ClaimsPrincipal(identity);
    }
}

架構特定替代方案

在 ASP.NET 4.6 應用程式中,App Service 會使用已驗證的使用者宣告填入 ClaimsPrincipal.Current,因此您可以遵循標準的 .NET 程式碼模式,包括 [Authorize] 屬性。 同樣地,在 PHP 應用程式中,App Service 會填入 _SERVER['REMOTE_USER'] 變數。 針對 Java 應用程式,宣告可從 Tomcat servlet 存取

對於 Azure FunctionsClaimsPrincipal.Current 未針對 .NET 程式碼填入,但您仍可以在要求標頭中找到使用者宣告,或從要求內容或甚至透過繫結參數取得 ClaimsPrincipal 物件。 如需詳細資訊,請參閱在 Azure Functions 中使用用戶端身分識別

針對 .NET Core,Microsoft.Identity.Web 支援為目前的使用者填入 App Service 驗證。 若要深入了解,您可以在 Microsoft.Identity.Web Wiki 上閱讀相關資訊,或查看存取 Microsoft Graph 的 Web 應用程式的此教學課程中的示範。

注意

為了讓宣告對應運作,您必須啟用權杖存放區

使用 API 存取使用者宣告

如果為您的應用程式啟用權杖存放區,則也可以呼叫 /.auth/me 來取得已驗證使用者的其他詳細資料。

下一步