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

Node.js使用DefaultAzureCredential认证Azure API Management报错如何解决

问题描述

我尝试在Node.js中使用@azure/identity包的DefaultAzureCredential完成Azure身份认证,以获取Azure API Management Service的报表数据,目前遇到认证及权限报错,具体操作和现象如下:

已完成操作

  • 在Azure Portal创建了API Management Service实例
  • 完成Azure AD应用注册并创建了服务主体
  • 正确配置了使用DefaultAzureCredential所需的环境变量:AZURE_TENANT_ID、AZURE_CLIENT_ID、AZURE_CLIENT_SECRET、AZURE_SUBSCRIPTION、AZURE_RESOURCE_GROUP、AZURE_SERVICE_NAME

现在遇到两个问题:

  1. 打印new DefaultAzureCredential()的返回结果显示UnavailableMessage: 'DefaultAzureCredential => failed to retrieve a token from the included credentials'
    相关代码:
require("dotenv").config();
const { DefaultAzureCredential } = require("@azure/identity");
const { ApiManagementClient } = require("@azure/arm-apimanagement");

if (!process.env.AZURE_TENANT_ID) throw Error("AZURE_TENANT_ID is missing from environment variables.");
if (!process.env.AZURE_CLIENT_ID) throw Error("AZURE_CLIENT_ID is missing from environment variables.");
if (!process.env.AZURE_CLIENT_SECRET) throw Error("AZURE_CLIENT_SECRET is missing from environment variables.");
if (!process.env.AZURE_RESOURCE_GROUP) throw Error("AZURE_RESOURCE_GROUP is missing from environment variables.");
if (!process.env.AZURE_SERVICE_NAME) throw Error("AZURE_SERVICE_NAME is missing from environment variables.");
if (!process.env.AZURE_SUBSCRIPTION) throw Error("AZURE_SUBSCRIPTION is missing from environment variables.");

const subscriptionId = process.env.AZURE_SUBSCRIPTION;

const credentials = new DefaultAzureCredential();

console.log(credentials);

返回内容:

DefaultAzureCredential {
  UnavailableMessage: 'DefaultAzureCredential => failed to retrieve a token from the included credentials',
  _sources: [
    EnvironmentCredential { _credential: [ClientSecretCredential] },
    ManagedIdentityCredential {
      isEndpointUnavailable: null,
      clientId: 'c8xxxxxxxx5ac8',
      identityClient: [IdentityClient]
    },
    AzureCliCredential {},
    VisualStudioCodeCredential {
      cloudName: 'AzureCloud',
      identityClient: [IdentityClient],
      tenantId: 'common'
    }
  ]
}
  1. 继续调用APIM报表接口返回403权限错误
    相关代码:
const client = new ApiManagementClient(credentials, subscriptionId);

const resourceGroupName = process.env.AZURE_RESOURCE_GROUP;
const serviceName = process.env.AZURE_SERVICE_NAME;
const filter = "callCountSuccess";

client.reports
    .listBySubscription(
        resourceGroupName,
        serviceName,
        filter
    )
    .then((result) => {
        console.log(JSON.stringify(result));
    })
    .catch((err) => {
        console.log(err);
    });

错误返回:

response: {
    body: `{"error":
    {"code":"AuthorizationFailed",
    "message":
    "The client 'cxxxxxxxxxxxxxxx569' with object id 'cxxxxxxxxxxxxxxx569' 
    does not have authorization to perform action 'Microsoft.ApiManagement/service/reports/read' 
    over scope '/subscriptions/85xxxxxxx3c5/resourceGroups/axxxb/providers/Microsoft.ApiManagement/service/Axxxx/reports/bySubscription' 
    or the scope is invalid. 
    If access was recently granted, please refresh your credentials."}}`,
    headers: HttpHeaders { _headersMap: [Object] },
    status: 403
  },

补充说明

已经为服务主体授予了API Management Service的Reader角色,仍然返回上述403错误,角色配置截图如下:
角色配置截图


排查解决步骤

1. 处理DefaultAzureCredential的提示问题

你看到的不可用消息是初始化阶段的预检测提示,不代表实际调用时无法获取凭证,不需要纠结这个输出,只要后续接口能正常拿到token就属于正常情况。如果要完全消除这个提示,可以直接显式使用ClientSecretCredential代替DefaultAzureCredential,规避其他无关凭证源的检测逻辑,代码修改如下:

// 替换原有DefaultAzureCredential引入
const { ClientSecretCredential } = require("@azure/identity");
// 初始化凭证
const credentials = new ClientSecretCredential(
  process.env.AZURE_TENANT_ID,
  process.env.AZURE_CLIENT_ID,
  process.env.AZURE_CLIENT_SECRET
);

2. 解决403权限问题

通用Reader角色默认没有APIM报表的读取权限,按以下步骤排查修改即可:

  • 确认角色分配范围:确认给服务主体分配角色的范围和403错误里提示的scope路径匹配,错误里的scope是单个APIM实例级别,要确保角色是分配在当前调用的APIM实例上,而不是其他层级。
  • 替换对应角色:通用Reader角色不包含Microsoft.ApiManagement/service/reports/read权限,给服务主体分配「API管理服务读者」内置角色即可,该角色专门包含APIM相关的所有读取权限,包括报表读取权限。
  • 等待权限生效:新分配的Azure角色最长需要15分钟才能完全生效,分配后可以等待几分钟再测试,也可以重新生成服务主体的client secret,更新环境变量后再测试。
  • 修正filter参数格式:当前的filter参数不符合APIM报表接口的OData格式要求,正确格式比如要筛选成功调用数相关数据,应该写成$filter=callCountSuccess ge 0,参数格式错误也可能触发权限类错误提示。

内容的提问来源于stack exchange,提问作者Ammar Abdul Aziz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:45:00