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

调用Azure管理API获取函数密钥时遭遇403 Forbidden错误求助

调用Azure函数密钥接口返回403 Forbidden错误排查

调用以下HTTP POST请求获取Azure函数密钥时,收到403禁止访问错误:
URL:

https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{appName}/functions/{functionName}/listkeys?api-version=2022-03-01

错误信息:

StatusCode: 403, ReasonPhrase: 'Forbidden'

客户端代码

let tenantId = "<some_tenant_id>"
let clientId = "<some_client_id>"
let secret   = "<some_secret>"
let scope    = "<some_scope>"

let token = BearerToken.Create(tenantId, clientId, secret, scope).Result

let tokenRequestBody = Dictionary<string, string>() 
tokenRequestBody.Add("grant_type"   , "client_credentials")
tokenRequestBody.Add("client_id"    , clientId)
tokenRequestBody.Add("client_secret", secret)
tokenRequestBody.Add("scope"        , scope)

let content = new FormUrlEncodedContent(tokenRequestBody);

let httpKeysClient = new HttpClient();
httpKeysClient.DefaultRequestHeaders.Authorization <- new AuthenticationHeaderValue("Bearer", token);
httpKeysClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

let subscriptionId    = "<some_scubscription_id>"
let resourceGroupName = "<some_resource_group_name>"
let appName           = "<some_function_app_name>"
let functionName      = "<some_function_name>"

let apiKeyUrl = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{appName}/functions/{functionName}/listkeys?api-version=2022-03-01";

let response = httpKeysClient.PostAsync(apiKeyUrl, content).Result;

response.IsSuccessStatusCode |> should equal true // ** StatusCode: 403, ReasonPhrase: 'Forbidden' **

令牌生成代码(可正常运行)

public static class BearerToken
{
    public async static Task<string> Create(string tenantId, string clientId, string clientSecret, string scope)
    {
        var tokenRequestBody = new Dictionary<string, string> {

            { "grant_type"   , "client_credentials" },
            { "client_id"    , clientId },
            { "client_secret", clientSecret },
            { "scope"        , scope }
            };

        var url      = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
        var client   = new HttpClient() { BaseAddress = new Uri(url) };
        var content  = new FormUrlEncodedContent(tokenRequestBody);
        var response = await client.PostAsync("", content);

        if (response.IsSuccessStatusCode)
        {
            var tokenResponse = await response.Content.ReadAsStringAsync();
            var valueFor      = JsonConvert.DeserializeObject<JsonSupport.AccessToken.Root>(tokenResponse);

            return valueFor.access_token;
        }

        throw new Exception(response.ReasonPhrase);
    }
}

排查原因及解决方法

1. 请求体冗余导致格式错误

调用listkeys接口时不需要传递请求体,代码错误地将获取令牌时的Form请求体再次传递给了密钥接口,服务器收到不符合要求的请求内容后返回403错误。
解决:调用PostAsync时传入null作为内容,即执行httpKeysClient.PostAsync(apiKeyUrl, null)。

2. 服务主体权限不足

clientId对应的Azure AD服务主体没有足够权限访问函数密钥。
解决:在Azure门户中,找到目标函数应用所在的资源组或订阅,为该服务主体分配**网站参与者(Website Contributor)**角色,或者更细粒度的权限:Microsoft.Web/sites/functions/listkeys/action。

3. 令牌Scope设置错误

获取令牌时的scope必须是https://management.azure.com/.default,这是调用Azure管理API的固定scope。使用其他scope会导致令牌不具备访问管理API的权限,进而返回403。
解决:将代码中的scope值改为"https://management.azure.com/.default"。

4. 资源参数拼写错误

确认subscriptionId、resourceGroupName、appName、functionName的拼写完全正确,参数错误可能导致服务器无法找到资源,部分场景下会返回403错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:00:15