首页 > 解决方案 > 如何从本地运行的非交互式进程获取 Azure 访问目录访问令牌,而不共享机密?

问题描述

在 Azure Active Directory 上对非交互式进程进行身份验证的标准模式是:

  1. 当服务在 Azure 上运行时,使用托管标识。
  2. 只要托管身份不可用,请使用OAuth 2.0 客户端凭据流。

但是,#1 不适用于在本地运行的服务,而#2 需要共享机密,这增加了很多操作复杂性——密钥存储、保护和轮换。

问题:

对于 Azure Active Directory 与 Active Directory 联合的设置(参见图表),是否有办法让本地运行的非交互式服务在不共享任何机密的情况下从 Azure Active Directory 获取访问令牌?所有必需的信任关系似乎都已到位,但有没有办法完成它?

设置图

标签: azureoauth-2.0azure-active-directory

解决方案


简短的回答是肯定的。

成分

  1. 与 Active Directory 联合的 Azure Active Directory 租户,能够使用 Windows 身份验证进行单点登录
  2. 授予 user_impersonation 权限的应用程序注册。
  3. 您的 MSAL 请求的特定配置。

细节

为了实现这一点,您需要使用 OAuth 2.0 代表流程,为此,您需要在 AAD 上创建应用程序注册。确保为您希望本地应用程序能够访问的每个 API 的“user_impersonation”范围“授予管理员同意”。典型的例子是:

  • Azure Key Vault.user_impersonation
  • Azure SQL 数据库.user_impersonation
  • Azure Storage.user_impersonation
  • Microsoft Graph.user_impersonation

但实际上,没有限制。此外,请注意安全影响很小,因为您没有授予任何权限。您只是允许任何能够针对此应用程序注册进行身份验证的用户继续并尝试在他们自己的权限下访问授予的资源。

应用程序注册准备就绪后,您需要使用以下代码获取令牌:

const string ApplicationRegistrationId = "the id";
const string Tenant = "YourDomain.com";

// Any user name will do as long as it's in your domain. This is because AAD will redirect the request to the federated Identity Provider, which will then use Kerberos, which will the real user.
const fakeUsername = "anything@YourDomain.com";

// The user_impersonation scopes you want to access. They need to have been granted on the Application Registration. The example below is for Azure Storage:
var scopes = new string[] { "https://storage.azure.com/user_impersonation" };

var app = PublicClientApplicationBuilder.Create(ApplicationRegistrationId).WithAuthority(Tenant).Build();
var authenticationResult = await app.AcquireTokenByIntegratedWindowsAuth(scopes).WithUsername(fakeUsername).ExecuteAsync();
// Go ahead and use the AccessToken from authenticationResult.AccessToken

图表

在此处输入图像描述

笔记

我没有发现上述方法记录在其他任何地方,但它被证明是有效的,并且鉴于它消除了共享任何秘密的需要 - 没有管理、轮换等 - 很高兴看到它被 Microsoft 记录下来。

它在具有混合设置的企业环境中特别适用和有用,即在本地运行的服务和部署到 Azure 的资源。


推荐阅读