基于React+Express用Graph API构建Microsoft Partner Center自助服务门户遇权限问题求助
多租户登录改造 + Partner Center API集成分步指南
一、先解决客户无法登录的多租户问题
你当前的AD应用是单租户模式,所以只有你租户内的用户能登录,改成多租户即可:
- 登录Azure门户,找到你的AD应用注册
- 进入「概述」页,把「支持的账户类型」改成任何组织目录中的账户(多租户)(如果不需要个人微软账户,就选这个;需要的话选包含个人账户的选项)
- 在「身份验证」页,确认前端和后端的重定向URI都已正确添加(比如前端
http://localhost:3000/auth/callback、后端http://localhost:5000/api/auth/callback) - 更新认证代码:
- 前端(msal-react):把
auth配置里的authority从你的租户ID换成https://login.microsoftonline.com/commonconst msalConfig = { auth: { clientId: "你的AD应用ID", authority: "https://login.microsoftonline.com/common", // 多租户通用端点 redirectUri: "http://localhost:3000/auth/callback" } }; - 后端(Express + passport-azure-ad):把
identityMetadata改成多租户配置,同时禁用 issuer 验证(或者指定允许的租户列表)const passport = require('passport'); const OIDCStrategy = require('passport-azure-ad').OIDCStrategy; passport.use(new OIDCStrategy({ identityMetadata: 'https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration', clientID: process.env.AZURE_AD_CLIENT_ID, clientSecret: process.env.AZURE_AD_CLIENT_SECRET, redirectUrl: process.env.AZURE_AD_REDIRECT_URI, validateIssuer: false, // 多租户模式下禁用,或者配置allowedIssuers responseType: 'code id_token', responseMode: 'form_post', scope: ['openid', 'profile', 'https://api.partnercenter.microsoft.com/user_impersonation'] }, (iss, sub, profile, accessToken, refreshToken, done) => { // 这里可以把用户的租户ID(profile.tenantId)存入会话 return done(null, { profile, accessToken }); }));
- 前端(msal-react):把
二、集成Partner Center API核心步骤
1. 配置AD应用的Partner Center权限
- 进入Azure AD应用的「API权限」页,点击「添加权限」→ 选择「Microsoft Partner Center」
- 添加所需的委派权限:比如
PartnerCenter.Read.All(读取订阅/许可证)、PartnerCenter.Subscriptions.ReadWrite.All(创建订阅)、PartnerCenter.Licenses.ReadWrite.All(管理许可证) - 点击「授予管理员同意」(必须是合作伙伴账户的全局管理员操作)
- 同时在Partner Center后台,把这个AD应用添加为「应用程序用户」,分配对应角色(比如代理管理员)
2. 后端获取Partner Center访问令牌
因为是客户登录后操作,需要用用户委派的令牌通过「on-behalf-of」流程交换Partner Center的令牌:
const axios = require('axios'); async function getPcAccessToken(userAccessToken) { const tokenUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/token'; const params = new URLSearchParams({ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', client_id: process.env.AZURE_AD_CLIENT_ID, client_secret: process.env.AZURE_AD_CLIENT_SECRET, assertion: userAccessToken, scope: 'https://api.partnercenter.microsoft.com/user_impersonation', requested_token_use: 'on_behalf_of' }); const res = await axios.post(tokenUrl, params); return res.data.access_token; }
3. 调用API实现业务功能
(1)获取客户的订阅详情
async function getCustomerSubscriptions(pcToken, customerTenantId) { const apiUrl = `https://api.partnercenter.microsoft.com/v1/customers/${customerTenantId}/subscriptions`; const res = await axios.get(apiUrl, { headers: { 'Authorization': `Bearer ${pcToken}`, 'Accept': 'application/json' } }); return res.data.items; // 返回订阅列表 }
(2)获取客户的许可证详情
async function getCustomerLicenses(pcToken, customerTenantId) { const apiUrl = `https://api.partnercenter.microsoft.com/v1/customers/${customerTenantId}/licenses`; const res = await axios.get(apiUrl, { headers: { 'Authorization': `Bearer ${pcToken}`, 'Accept': 'application/json' } }); return res.data.items; // 返回许可证列表 }
(3)为客户创建新订阅/添加托管服务
async function createCustomerSubscription(pcToken, customerTenantId, subscriptionPayload) { const apiUrl = `https://api.partnercenter.microsoft.com/v1/customers/${customerTenantId}/subscriptions`; const res = await axios.post(apiUrl, subscriptionPayload, { headers: { 'Authorization': `Bearer ${pcToken}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } }); return res.data; } // 示例payload: // const payload = { // offerId: "你的Partner Center产品Offer ID", // friendlyName: "客户自定义订阅名称", // quantity: 5, // 购买数量 // billingCycle: "Monthly", // 计费周期 // termDuration: "P1M" // };
三、前端React功能实现
- 获取客户租户ID:登录后通过msal-react的
useMsal钩子获取用户的租户ID(account.idTokenClaims.tid) - 调用后端API:把租户ID传给后端,获取对应的订阅/许可证数据,然后渲染成列表(比如用Ant Design的Table组件)
- 添加服务表单:做一个表单让客户选择要添加的服务(可以提前从后端拉取Partner Center的产品列表),填写数量后提交到后端的创建订阅接口
- 权限校验:前端要确保用户只能看到自己租户的资源,后端也要验证用户的租户ID和请求的客户租户ID一致
四、关键注意事项
- 权限隔离:后端必须校验用户的租户ID与请求的客户租户ID匹配,禁止跨租户访问
- API限流:Partner Center API有请求次数限制,要处理429错误,实现指数退避重试
- 错误处理:前端要展示友好错误提示,后端要捕获API异常并返回结构化错误信息
内容的提问来源于stack exchange,提问作者p0stdelay
相关产品推荐
相关产品推荐

