共用方式為


設定應用程式以信任受控識別 (預覽)

本文說明如何設定 Microsoft Entra 應用程式以信任受控識別。 然後,您可以將受控識別令牌交換為可存取Microsoft Entra 受保護資源的存取令牌,而不需要使用或管理應用程式秘密。

先決條件

重要考慮和限制

若要建立、更新或刪除同盟身分識別認證,執行動作的帳戶必須具有 應用程式管理員應用程式開發人員Cloud Application Administrator或應用程式擁有者角色。 需要 microsoft.directory/applications/credentials/update 許可權,才能更新聯邦身分識別憑證。

最多可以將 20 個聯合身分識別憑證新增至應用程式或使用者指派的受管理的身分識別。

當您設定聯合身分識別憑證時,需要提供一些重要資訊:

  • 簽發者主體 是建立信任關係所需的關鍵資訊。 issuersubject 的組合在應用程式上必須是唯一的。 當 Azure 工作負載要求 Microsoft 身分識別平臺交換受控識別令牌以獲得存取令牌時,系統會根據受控識別令牌中提供的 issuersubject 宣告,檢查同盟身分識別認證的 簽發者主體 值。 如果該驗證檢查通過,Microsoft身分識別平臺會對外部軟體工作負載發出存取令牌。

  • Issuer 是 Microsoft Entra 租使用者授權單位的 URL,格式為 https://login.microsoftonline.com/{tenant}/v2.0。 Microsoft Entra 應用程式和受控身份必須屬於相同的租戶。 如果 issuer 宣告的值中有前置空格或尾隨空格,則會封鎖令牌交換。

    重要

    雖然應用程式註冊和受控識別必須位於相同的租戶中,但應用程式註冊的服務主體仍然可以兌換受控識別令牌。

  • 主體 是指派給 Azure 工作負載之受控識別物件識別碼(主體標識符)的 GUID。 Microsoft身分識別平臺會查看傳入的外部令牌,如果同盟身分識別認證中所設定 主體 字段不符合受控識別的主體標識符,則會拒絕存取令牌的交換。 GUID 區分大小寫。

  • 重要

    您只能在此功能中使用 User-Assigned 受控識別。

  • *受眾會列出可以出現在外部令牌中的受眾(必填項)。 您必須新增單一受眾值,其限制為600個字元。 此值必須是下列其中一項,且必須符合受控識別令牌中 aud 宣告的值。

    • 公用雲端api://AzureADTokenExchange
    • 費爾法克斯api://AzureADTokenExchangeUSGov
    • 月餅api://AzureADTokenExchangeChina
    • USNatapi://AzureADTokenExchangeUSNat
    • USSecapi://AzureADTokenExchangeUSSec

    重要

    如果您不小心在 簽發者主體受眾 中新增不正確的資訊,那麼同盟身分識別認證還是會成功建立,且不會出現錯誤。 在令牌交換失敗之前,錯誤不會變得明顯。

  • 名稱 是聯合身份憑證的唯一識別碼。 (必要)此欄位的字元限制為 3-120 個字元,而且必須是 URL 易記。 支援英數位元、虛線或底線字元,且第一個字元必須是英數位元。 一旦建立它就不可變了。

  • 描述 是由使用者提供的同盟身份憑證描述(選填)。 Microsoft Entra ID 不會驗證或檢查描述。 此欄位的限制為 600 個字元。

身分識別同盟的任何認證屬性值都不支援通配符。

取得受控識別的物件標識碼

  1. 登入 Azure 入口網站
  2. 在搜尋方塊中,輸入 受控識別。 在 [Services] 下,選取 [受管理的身分]。
  3. 搜尋並選擇您在 先決條件中建立的使用者指派的受控識別
  4. 在 [概觀] 窗格中,複製 [物件 (主體) ID] 值。 此值會當做同盟認證組態中 主體 字段使用。

zh-TW: Azure 入口網站中使用者指派的受控識別螢幕快照。物件 ID 已被反白顯示,將用作同盟憑證設定中的 *subject* 欄位。

在現有的應用程式上設定同盟身分識別認證

在本節中,您會在現有的應用程式上設定同盟身分識別認證,以信任受控識別。 使用下列索引標籤,選擇如何在現有應用程式上設定同盟身分識別認證。

  1. 登入到 Microsoft Entra 系統管理中心。 檢查您是否在註冊應用程式的租戶中。

  2. 流覽至 [身分識別>應用程式>應用程式註冊],然後在主視窗中選取您的應用程式。

  3. 在 [管理] 底下,選取 [憑證 &] 和 [秘密]。

  4. 選取 [同盟認證] 索引標籤,然後選取 [新增認證]

    Microsoft Entra 系統管理中心憑證和秘密窗格的螢幕快照,其中已標示同盟認證索引標籤。

  5. 從 [同盟認證案例] 的下拉式清單中選取 [其他簽發者],然後根據下表填入值:

    領域 描述
    發行者 Microsoft Entra 識別授權機構的 OAuth 2.0 / OIDC 發行方 URL。 https://login.microsoftonline.com/{tenantID}/v2.0
    主體標識碼 受控識別 Principal ID GUID。 aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb
    名字 獨特的描述性名稱,用於該認證。 msi-webapp1
    描述(選擇性) 使用者提供之同盟身分識別認證的描述。 信任工作負載UAMI來模擬應用程式
    觀眾 必須出現在外部令牌中的受眾值。 公用雲端api://AzureADTokenExchange
    Fairfaxapi://AzureADTokenExchangeUSGov
    月餅api://AzureADTokenExchangeChina
    USNatapi://AzureADTokenExchangeUSNat
    USSecapi://AzureADTokenExchangeUSSec

    Microsoft Entra 系統管理中心認證視窗的螢幕快照。

更新您的應用程式程式代碼以要求存取令牌

下表中的下列程式代碼範例顯示客戶端認證「服務對服務」流程。 不過,作為認證的受控識別資訊可以在其他驗證流程中使用,例如代理者(OBO)流程。 這些範例在以下兩種情況中均有效:資源租用戶與應用程式註冊和受控識別在相同的租用戶中,或它們位於不同的租用戶。

Azure.Identity

下列範例示範如何使用 Azure.Identity連線到 Azure 記憶體容器,但可調整為存取受 Microsoft Entra 保護的任何資源。 在這兩種情況下,資源租使用者都與應用程式註冊和受控識別或不同的租用戶位於相同的租使用者中,這些範例都是有效的。

using Azure.Identity;
using Azure.Storage.Blobs;

internal class Program
{
    // This example demonstrates how to access an Azure blob storage account by utilizing the manage identity credential.
  static void Main(string[] args)
  {
        string storageAccountName = "YOUR_STORAGE_ACCOUNT_NAME";
        string containerName = "CONTAINER_NAME";
        
        // The application must be granted access on the target resource
      string appClientId = "YOUR_APP_CLIENT_ID";

        // The tenant where the target resource is created, in this example, the storage account tenant
        // If the resource tenant different from the app tenant, your app needs to be 
      string resourceTenantId = "YOUR_RESOURCE_TENANT_ID";

        // The managed identity which you configured as a Federated Identity Credential (FIC)
      string miClientId = "YOUR_MANAGED_IDENTITY_CLIENT_ID"; 

        // Audience value must be one of the below values depending on the target cloud.
        // Public cloud: api://AzureADTokenExchange
        //  Fairfax: api://AzureADTokenExchangeUSGov
        //  Mooncake: api://AzureADTokenExchangeChina
        //  USNat: api://AzureADTokenExchangeUSNat
        //  USSec: api://AzureADTokenExchangeUSSec
      string audience = "api://AzureADTokenExchange";

        // 1. Create an assertion with the managed identity access token, so that it can be exchanged an app token
        var miCredential = new ManagedIdentityCredential(managedIdentityClientId);
        ClientAssertionCredential assertion = new(
            tenantId,
            appClientId,
            async (token) =>
            {
                // fetch Managed Identity token for the specified audience
                var tokenRequestContext = new Azure.Core.TokenRequestContext(new[] { $"{audience}/.default" });
                var accessToken = await miCredential.GetTokenAsync(tokenRequestContext).ConfigureAwait(false);
                return accessToken.Token;
            });

        // 2. The assertion can be used to obtain an App token (taken care of by the SDK)
        var containerClient  = new BlobContainerClient(new Uri($"https://{storageAccountName}.blob.core.windows.net/{containerName}"), assertion);

        await foreach (BlobItem blob in containerClient.GetBlobsAsync())
        {
            // TODO: perform operations with the blobs
            BlobClient blobClient = containerClient.GetBlobClient(blob.Name);
            Console.WriteLine($"Blob name: {blobClent.Name}, uri: {blobClient.Uri}");            
        }
  }
}

Microsoft.Identity.Web

Microsoft.Identity.Web中,Web 應用程式或 Web API 可以將用戶端憑證取代為已簽署的客戶端判斷提示以進行驗證。 在您的應用程式中,您可以將 appsettings.json 中的 ClientCredentials 區段更新為下列組態:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "YOUR_APPLICATION_ID",
    "TenantId": "YOUR_TENANT_ID",

   "ClientCredentials": [
      {
        "SourceType": "SignedAssertionFromManagedIdentity",
        "ManagedIdentityClientId": "YOUR_USER_ASSIGNED_MANAGED_IDENTITY_CLIENT_ID",
        "TokenExchangeUrl":"api://AzureADTokenExchange"
      }
   ]
  }
}

MSAL (.NET)

MSAL中,您可以使用 ManagedClientApplication 類別來取得受控識別令牌。 接著,在構建保密用戶端應用程式時,可以使用此令牌作為用戶端聲明。

警告

對於 .NET 應用程式,我們強烈建議使用以 MSAL 為基礎的較高層級連結庫,例如 Microsoft.Identity.WebAzure.Identity

using Microsoft.Identity.Client;
using Azure.Storage.Blobs;
using Azure.Core;

internal class Program
{
  static async Task Main(string[] args)
  {
        string storageAccountName = "YOUR_STORAGE_ACCOUNT_NAME";
        string containerName = "CONTAINER_NAME";

      string appClientId = "YOUR_APP_CLIENT_ID";
      string resourceTenantId = "YOUR_RESOURCE_TENANT_ID";
      Uri authorityUri = new($"https://login.microsoftonline.com/{resourceTenantId}");
      string miClientId = "YOUR_MI_CLIENT_ID";
      string audience = "api://AzureADTokenExchange";

      // Get mi token to use as assertion
      var miAssertionProvider = async (AssertionRequestOptions _) =>
      {
            var miApplication = ManagedIdentityApplicationBuilder
                .Create(ManagedIdentityId.WithUserAssignedClientId(miClientId))
                .Build();

            var miResult = await miApplication.AcquireTokenForManagedIdentity(audience)
                .ExecuteAsync()
                .ConfigureAwait(false);
            return miResult.AccessToken;
      };

      // Create a confidential client application with the assertion.
      IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(appClientId)
        .WithAuthority(authorityUri, false)
        .WithClientAssertion(miAssertionProvider)
        .WithCacheOptions(CacheOptions.EnableSharedCacheOptions)
        .Build();

        // Get the federated app token for the storage account
      string[] scopes = [$"https://{storageAccountName}.blob.core.windows.net/.default"];
      AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync().ConfigureAwait(false);

        TokenCredential tokenCredential = new AccessTokenCredential(result.AccessToken);
        var client = new BlobContainerClient(
            new Uri($"https://{storageAccountName}.blob.core.windows.net/{containerName}"),
            tokenCredential);

        await foreach (BlobItem blob in containerClient.GetBlobsAsync())
        {
            // TODO: perform operations with the blobs
            BlobClient blobClient = containerClient.GetBlobClient(blob.Name);
            Console.WriteLine($"Blob name: {blobClient.Name}, URI: {blobClient.Uri}");
        }
  }
}

另請參閱