You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Azure Function代表已认证调用方访问Azure资源?

实现Azure Function代表已认证调用方访问Azure资源

要让Azure Function承接已登录AD用户的身份,去访问Cosmos DB、Key Vault等资源,核心是用On-Behalf-Of (OBO) 令牌委派流程,结合Azure AD认证和RBAC权限控制,步骤如下:

1. 配置Azure Function的AD身份验证

  • 给你的Function App启用Azure AD身份验证:在Azure门户的Function App「身份验证」面板,选择「添加身份提供者」,选Azure AD,配置为「需要身份验证」(拒绝未认证的请求)。
  • 关联的应用注册需支持获取用户的access_token(而非仅id_token),若为前端调用Function,还需开启隐式流中的access_token选项。

2. 配置应用注册的委派权限

  • 找到Function对应的Azure AD应用注册,在「API权限」中添加以下委派权限(按需调整):
    • Cosmos DB:Microsoft.DocumentDB/databaseAccounts/readMetadata、Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*(或更细粒度的数据权限)
    • Key Vault:Microsoft.KeyVault/vaults/secrets/read、Microsoft.KeyVault/vaults/secrets/write等
    • 若要检查用户组成员身份,需添加Microsoft Graph的GroupMember.Read.All委派权限
  • 点击「授予管理员同意」,确保权限生效(避免用户每次调用都需授权)。

3. 用OBO流程获取资源访问令牌

在Function代码中,通过用户的身份令牌,请求目标资源的访问令牌,以代表用户访问资源:

代码示例(C#)

using Microsoft.Identity.Client;
using System.Net.Http.Headers;
using Microsoft.Azure.Cosmos;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    // 从请求头提取用户的Bearer令牌
    if (!req.Headers.TryGetValue("Authorization", out var authHeader) || !authHeader.ToString().StartsWith("Bearer "))
    {
        return new UnauthorizedResult();
    }
    var userToken = authHeader.ToString().Substring("Bearer ".Length);

    // 初始化MSAL客户端
    var clientId = Environment.GetEnvironmentVariable("AzureAD_ClientId");
    var clientSecret = Environment.GetEnvironmentVariable("AzureAD_ClientSecret");
    var authority = Environment.GetEnvironmentVariable("AzureAD_Authority"); // 格式:https://login.microsoftonline.com/{租户ID}

    var confidentialClient = ConfidentialClientApplicationBuilder
        .Create(clientId)
        .WithClientSecret(clientSecret)
        .WithAuthority(new Uri(authority))
        .Build();

    // 请求Cosmos DB的访问令牌
    var cosmosScope = "https://cosmos.azure.com/.default";
    var userAssertion = new UserAssertion(userToken);
    var tokenResult = await confidentialClient.AcquireTokenOnBehalfOf(new[] { cosmosScope }, userAssertion).ExecuteAsync();

    // 使用令牌访问Cosmos DB
    var cosmosClient = new CosmosClient("https://your-cosmos-account.documents.azure.com:443/", tokenResult.AccessToken);
    var database = cosmosClient.GetDatabase("your-db");
    var container = database.GetContainer("your-container");
    // 执行Cosmos DB操作(如查询、写入)...

    // 同理可获取Key Vault令牌,请求scope为"https://vault.azure.net/.default"
    return new OkObjectResult("资源访问完成");
}

4. 配置资源的RBAC权限

  • 针对Cosmos DB、Key Vault,将用户所属的AD组添加到对应的RBAC角色中:
    • Cosmos DB:可分配Cosmos DB Built-in Data Reader/Cosmos DB Built-in Data Contributor等数据角色
    • Key Vault:可分配Key Vault Secrets Reader/Key Vault Secrets Contributor等角色
  • 当用用户委派的令牌访问资源时,Azure会自动验证用户(或其所属组)的权限,返回对应访问结果。

5. 可选:在Function中提前验证用户组

如果需要在Function层面先判断用户是否属于指定组,可调用Microsoft Graph API获取用户的组成员身份:

// 获取Graph API的令牌(OBO流程,scope为"https://graph.microsoft.com/.default")
var graphTokenResult = await confidentialClient.AcquireTokenOnBehalfOf(new[] { "https://graph.microsoft.com/.default" }, userAssertion).ExecuteAsync();

// 调用Graph API获取用户所属组
var graphClient = new HttpClient();
graphClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphTokenResult.AccessToken);
var groupsResponse = await graphClient.GetAsync($"https://graph.microsoft.com/v1.0/me/memberOf");
if (!groupsResponse.IsSuccessStatusCode)
{
    return new ForbidResult();
}
// 解析响应,检查是否包含允许的组ID/名称,不符合则返回403
var groups = await groupsResponse.Content.ReadFromJsonAsync<dynamic>();
var allowedGroupId = "your-group-id";
var isInAllowedGroup = groups.value.Any(g => g.id == allowedGroupId);
if (!isInAllowedGroup)
{
    return new ForbidResult();
}

关键注意事项

  • OBO流程要求Function的应用注册是机密客户端,需配置客户端密钥或证书,不能用公共客户端。
  • 缓存获取到的资源令牌,避免频繁调用MSAL,提升性能。
  • 处理令牌过期、权限不足等异常,返回合适的HTTP状态码(401 Unauthorized、403 Forbidden)。

内容的提问来源于stack exchange,提问作者webish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 11:25:30