aDi*_*ame 2 azure azure-active-directory azure-keyvault
Azure Key Vault 支持“复合身份”来控制访问(https://learn.microsoft.com/en-us/azure/key-vault/general/secure-your-key-vault),但是有人有一些经验吗关于如何使用复合身份在.NET 中执行身份验证?
当使用本机应用程序从桌面运行时,我相信身份验证将涉及以下两者:
身份验证工作流程会是什么样子?有可用的例子吗?我们可以通过使用 MSAL 来实现吗?
假设我们创建了一个 Azure Key Vault 并在该保管库中保存了一些机密。如何在 Windows 10 下运行的桌面应用程序中实现以下功能:
换句话说,我希望可以通过两种身份验证的组合来访问密钥保管库资源
我要回答我的问题。简短的答案是使用
IConfidentialClientApplication.AcquireTokenOnBehalfOf(
IEnumerable<string> scopes,
UserAssertion userAssertion);
Run Code Online (Sandbox Code Playgroud)
交互获取的用户令牌可以用作 UserAssertion。
长版本,因为我是新手用户,所以我将详细介绍我发现的所有细节。事实证明,这里和那里都有一些位可以创建一个完整的可运行的 .net 应用程序,所以并非所有内容都与我的问题直接相关。
平台:移动和桌面应用程序
设置证书或秘密:我们将在本演示中使用秘密。
重定向 URI:在该部分下添加一个新的Mobile and desktop application,并将其设置为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”。
在“公开 API”部分设置 API,并添加范围。
在代表工作流中,用户使用应用提供的范围登录,而不是直接访问密钥保管库资源。我们需要“设置”应用程序 ID URI,并创建至少一个供交互式登录使用的范围。
创建密钥保管库。
在“访问策略”中,添加新的访问策略。
要创建复合身份,请选择 的有效用户或组帐户Seelct principal,然后为 选择我们在上一步中创建的同一应用程序Authorized application。
创建 .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" />
Run Code Online (Sandbox Code Playgroud)
这是使用复合身份访问密钥库的代码
<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" />
Run Code Online (Sandbox Code Playgroud)
如果我们不使用复合身份,我们可以Azure.Security.KeyVault.Secrets.SecretClient通过以下方法之一访问密钥库数据
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);
Run Code Online (Sandbox Code Playgroud)
和
// 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);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3722 次 |
| 最近记录: |