azure - 如何使用复合身份向 Azure 进行身份验证以访问 Azure Key Vault

标签 azure azure-active-directory azure-keyvault

问题:

Azure Key Vault 支持“复合身份”来控制访问( https://learn.microsoft.com/en-us/azure/key-vault/general/secure-your-key-vault ),但是有人对如何使用复合身份在 .NET 中执行身份验证有一些经验吗?

当使用 native 应用程序从桌面运行时,我相信身份验证将涉及两者:

  1. 用户的交互式登录和同意,以及
  2. 应用程序使用客户端 key 进行身份验证

身份验证工作流程是什么样的?有可用的例子吗?我们可以通过使用 MSAL 来实现吗?

关于化合物身份的一些解释:

假设我们创建了一个 Azure Key Vault,并在该保管库中保存了一些 secret 。如何在 Windows 10 下运行的桌面应用程序中实现以下功能:

  • 当前 Windows 用户属于 Azure AD 组 GroupA,位于 Azure Key Vault 的同一租户下。
  • 当当前用户从同一用户 session 启动桌面应用程序时,该应用程序可以访问所述 key 保管库中的 secret 。
  • 当前用户从浏览器登录 Azure 门户时无法直接访问 secret 。
  • 如果应用程序由不属于 Azure AD 组 (GroupA) 的其他用户启动,则应用程序无法访问所述 key 保管库中的 secret 。

换句话说,我希望可以通过两种身份验证的组合来访问 key 保管库资源

  • 用户凭据,以及
  • 应用程序 secret

最佳答案

我要回答我的问题了。简短的答案是使用

IConfidentialClientApplication.AcquireTokenOnBehalfOf(
      IEnumerable<string> scopes,
      UserAssertion userAssertion);

交互式获取的用户 token 可以用作 UserAssertion。

长版本,由于我是新手用户,我将详细介绍我发现的所有细节。事实证明,这里和那里都有一些位可以创建一个完整的可运行的 .net 应用程序,因此并非所有内容都与我的问题直接相关。

1。在 Azure AD 中创建应用程序注册。

  1. 平台:移动和桌面应用程序

  2. 设置证书或 secret :我们将在此演示中使用 secret 。

  3. 重定向 URI:在 Mobile and desktop application 下添加一个新的 URI部分,并将其设置为 http://127.0.0.1

    如果作为控制台应用程序运行,则没有与正在运行的应用程序直接关联的窗口,因此执行用户登录的最简单方法是使用系统默认的 Web 浏览器应用程序。因此,使用返回代码的唯一方法是使用“http://localhost”或“http://127.0.0.1”(也称为环回 URL)形式的 redir URL。在运行时,MSAL 将使用动态端口作为本地 Web 服务器来捕获来自 Web 浏览器的 redir URL 调用。由于它在本地运行,因此允许使用 http://或 https://,除非有人使用 DNS 或主机文件劫持了“localhost”。

  4. 在“公开 API”部分中设置 API,并添加范围。

    在代表工作流中,用户使用应用提供的范围登录,而不是直接访问 key 保管库资源。我们需要“设置”应用程序 ID URI,并创建至少一个供交互式登录使用的范围。

2。创建 key 保管库,并在数据平面中设置访问策略。

  1. 创建 key 保管库。

  2. 在“访问策略”中,添加新的访问策略。

    要创建复合身份,请为 Seelct principal 选择有效的用户或组帐户,然后选择我们在上一步中为 Authorized application 创建的相同应用程序.

3。编写代码

创建 .NET Core 控制台应用程序。添加以下nuget包

<PackageReference Include="Microsoft.Identity.Client" Version="4.18.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.8" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.5" />

这是使用复合身份访问 keystore 的代码


const string AppClientId = "[Enter_your_Application_(client)_ID";
const string AppClientSecret = "[Enter_your_Application_(secret)";
const string TenantId = "[Enter_your_tenantId]";
const string KeyVaultBaseUri = "https://[your_keyvault_name].vault.azure.net/";

// In on-behalf-of flow, the following scope needs to be consented when acquiring the user token. Otherwise, the app cannot access the key vault on-behalf-of user.
const string KeyVaultUserImScope = "https://vault.azure.net/user_impersonation";
// In on-behalf-of flow, the following scope is used to access key vault data when acquiring client token
const string KeyVaultScope = "https://vault.azure.net/.default";
// An "Exposed API" in app registration is required when using on-behalf-of flow. 
const string AppClientScope = "[Enter_your_Application_ID_URI]/[Enter_Your_Scope_Name]";
const string Instance = "https://login.microsoftonline.com/";

Console.WriteLine("Acquire User token");
var pubClient = PublicClientApplicationBuilder.Create(AppClientId)
                .WithAuthority($"{Instance}{TenantId}")
                .WithRedirectUri("http://localhost")    // Make sure the "http://localhost" is added and selected as the app Redirect URI
                .Build();
var userResult= pubClient
                .AcquireTokenInteractive(new[] {AppClientScope })
                .WithExtraScopesToConsent(new [] {KeyVaultUserImScope})
                .WithPrompt(Prompt.Consent)
                .ExecuteAsync().Result;

// In normal case, when user token is directly given from outside, we should validate if the user Result has consented to the required customized scope AppClientScope before proceeded with next steps. Here we will ignore this step.


Console.WriteLine("Acquire Client token");
// The following two steps are equivalent to https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#middle-tier-access-token-request
var conClient = ConfidentialClientApplicationBuilder.Create(AppClientId)
                .WithAuthority($"{Instance}{TenantId}")
                .WithClientSecret(AppClientSecret)
                .Build();

            
var OboResult= conClient.AcquireTokenOnBehalfOf(
                    new[] {KeyVaultScope},
                    new UserAssertion(userReult.AccessToken))
                .ExecuteAsync().Result;



Console.WriteLine("Access Key Vault");
var kc = new KeyVaultCredential((authority, resource, scope) =>
                {
                    Console.WriteLine($"Authority: {authority}, Resource: {resource}, Scope: {scope}");
                    return Task.FromResult(OboResult.AccessToken);
                });

var kvClient = new KeyVaultClient(kc);
var secretBundle = await kvClient.GetSecretAsync(KeyVaultBaseUri, SecretName);

Console.WriteLine("Secret:" + secretBundle.Value);

如果我们不使用复合身份,我们可以使用 Azure.Security.KeyVault.Secrets.SecretClient通过以下方法之一访问 key 保管库数据

// For access policy assigned to confidential application 
var client = new SecretClient(new Uri(KeyVaultBaseUri),
                new ClientSecretCredential(TenantId, AppClientId, AppClientSecret));
var secretBundle = await client.GetSecretAsync(SecretName);
Console.WriteLine("Secret:" + secretBundle.Value.Value);

// For access policy assigned to User or Group account
var client = new SecretClient(new Uri(KeyVaultBaseUri), new InteractiveBrowserCredential());
var secretBundle = await client.GetSecretAsync(SecretName);
Console.WriteLine("Secret:" + secretBundle.Value.Value);

关于azure - 如何使用复合身份向 Azure 进行身份验证以访问 Azure Key Vault,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63699580/

相关文章:

Azure AD 应用程序角色授权 : Tenant Admin Delegation

c# - Azure Key Vault API 的有效 WebKeyType 列表是什么

azure - 将 EC key 导入 Key Vault

node.js - Azure Bot NodeJS 等待其他对话框完成

azure - 如何从我的 Azure AD 与另一个组织 Azure AD 联合

azure - 如何在 Azure Active Directory Graph API 中创建具有指定目录角色的用户(工作帐户)

.net - 在云中混淆应用程序设置文件,但允许本地应用程序开发

azure - 如何在门户 Azure 中添加自定义域?

azure - 创建Web App Bot时如何选择模板?

c# - SubscriptionClient.RecieveBatch 未检索所有代理消息