如何在非Azure托管Web API中用用户Azure访问令牌获取Key Vault密钥
问题:使用登录用户凭据访问Azure Key Vault而非服务主体
我正在开发一个采用Azure AD认证的网站,用户通过Azure AD凭据登录。当用户触发网站操作时,Angular前端调用.NET 6 Web API端点,并将Azure访问令牌传递给Web API。该端点随后调用Azure Key Vault获取密钥并执行其他操作。
目前我已通过ClientSecretCredential使用Azure服务主体实现Web API获取Key Vault密钥,代码如下:
var credential = new ClientSecretCredential(TenantId, ClientId, ClientSecret); var client = new SecretClient(new Uri(VaultName), credential); var success = await client.SetSecretAsync(secretName, value);
这段代码运行正常,但我希望改用登录用户的凭据而非服务主体账户来获取密钥。Web API仅能收到访问令牌,我尝试从该令牌构造Azure.Core.TokenCredential对象却未能成功——文档中所有继承自Azure.Core.TokenCredential的类均无对应构造方法。
Web前端与Web API均托管在Azure外部,恳请指点实现目标的方法。
相关TokenCredential派生类列表:
Azure.Identity.AuthorizationCodeCredential Azure.Identity.AzureCliCredential Azure.Identity.AzureDeveloperCliCredential Azure.Identity.AzurePowerShellCredential Azure.Identity.ChainedTokenCredential Azure.Identity.ClientAssertionCredential Azure.Identity.ClientCertificateCredential Azure.Identity.ClientSecretCredential Azure.Identity.DefaultAzureCredential Azure.Identity.DeviceCodeCredential Azure.Identity.EnvironmentCredential Azure.Identity.InteractiveBrowserCredential Azure.Identity.ManagedIdentityCredential Azure.Identity.OnBehalfOfCredential Azure.Identity.SharedTokenCacheCredential Azure.Identity.UsernamePasswordCredential Azure.Identity.VisualStudioCodeCredential Azure.Identity.VisualStudioCredential Azure.Identity.WorkloadIdentityCredential
解决方案:通过On-Behalf-Of流程实现用户身份委托
你需要使用OnBehalfOfCredential类来实现用户身份委托(OBO)流程,这正是为Web API接收用户令牌后,以用户身份调用下游服务(如Key Vault)的场景设计的。
步骤1:配置Azure AD应用权限
- 为Web API的应用注册添加Key Vault的委托权限(如
Key Vault Secrets User),并确保用户已同意该权限。 - 为Web API应用注册配置自身的客户端凭据(Client Secret或Client Certificate),用于向Azure AD请求代表用户的令牌。
- 前端请求用户令牌时,需包含Key Vault的作用域(如
https://vault.azure.net/user_impersonation)。
步骤2:实现OnBehalfOfCredential代码
在Web API中,从请求头提取用户访问令牌,再用OnBehalfOfCredential构造凭据调用Key Vault:
// 从Authorization头提取用户访问令牌 var authHeader = Request.Headers.Authorization.ToString(); var userAccessToken = authHeader.Replace("Bearer ", string.Empty); // 初始化OnBehalfOfCredential var oboCredential = new OnBehalfOfCredential( tenantId: "你的Azure AD租户ID", clientId: "Web API的应用注册ID", clientSecret: "Web API的客户端密钥", userAssertionToken: userAccessToken); // 创建SecretClient并执行操作 var secretClient = new SecretClient(new Uri("你的Key Vault URI"), oboCredential); var secret = await secretClient.GetSecretAsync("目标密钥名称");
替代方案:自定义TokenCredential
如果不需要OBO流程(比如用户令牌已直接包含Key Vault访问权限),可以自定义一个TokenCredential实现,直接复用用户令牌:
public class UserTokenCredential : TokenCredential { private readonly string _token; private readonly DateTimeOffset _expiresAt; public UserTokenCredential(string accessToken) { _token = accessToken; var jwtHandler = new JwtSecurityTokenHandler(); var jwtToken = jwtHandler.ReadJwtToken(accessToken); _expiresAt = jwtToken.ValidTo; } public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken) { return ValueTask.FromResult(new AccessToken(_token, _expiresAt)); } public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken) { return new AccessToken(_token, _expiresAt); } }
使用示例:
var userCredential = new UserTokenCredential(userAccessToken); var secretClient = new SecretClient(new Uri(VaultName), userCredential); var success = await secretClient.SetSecretAsync(secretName, value);
内容的提问来源于stack exchange,提问作者Viet Nguyen
相关产品推荐
相关产品推荐

