多租户OAuth下自动获取Microsoft Dynamics客户资源ID
我来帮你搞定这个自动获取Dynamics资源ID的问题——不用让用户手动输入任何URL,完全可以在授权流程里自动完成,下面是具体的实现思路和步骤:
用户登录后,我们可以通过他们的身份凭证,调用专门的微软服务来查询其租户下的Dynamics实例信息,从而自动拿到https://{orgid}.crm.dynamics.com这种资源ID,无需用户手动输入。
第一步:完成初始OAuth2授权,获取用户身份凭证
首先引导用户走常规的多租户Azure AD授权流程,获取两个关键凭证:
- ID Token:包含用户的租户ID(
tid字段)、用户主体名称(upn字段)等基础身份信息 - Access Token(针对Microsoft Graph/Discovery Service):用来后续查询Dynamics实例
授权URL示例(替换你的应用ID和回调地址):
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=YOUR_APP_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope=User.Read Organization.Read.All https://disco.crm.dynamics.com/user_impersonation offline_access&response_mode=query
这里的scope要包含:
User.Read:获取用户基本信息Organization.Read.All:读取租户的组织信息(用来定位Dynamics实例)https://disco.crm.dynamics.com/user_impersonation:访问Dynamics Discovery服务的权限offline_access:获取刷新令牌,支持后续静默刷新
第二步:自动查询用户的Dynamics实例URL
拿到第一步的Access Token后,有两种可靠的方式获取用户的Dynamics实例:
方式1:调用Microsoft Graph API
用Graph的Access Token发起请求:
GET https://graph.microsoft.com/v1.0/organization
在响应的value数组中,找到包含resourceProvisioningOptions且值包含DynamicsOnline的对象,提取id字段(租户域名),然后拼接成Dynamics实例URL:https://{租户域名}.crm.dynamics.com。
方式2:调用Dynamics Discovery Service API
用针对disco.crm.dynamics.com的Access Token发起请求:
GET https://disco.crm.dynamics.com/api/discovery/v2.0/Instances
这个API会直接返回用户有权访问的所有Dynamics实例列表,每个实例对象里的InstanceUrl就是你需要的资源ID(比如https://contoso.crm.dynamics.com)。如果用户有多个实例,你可以默认选第一个,或者弹出选择框让用户确认。
第三步:用自动获取的资源ID发起最终授权
拿到InstanceUrl后,构造针对该Dynamics实例的授权URL,引导用户完成最终的权限授权:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=YOUR_APP_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope={InstanceUrl}/user_impersonation offline_access&resource={InstanceUrl}
这里的resource参数就是自动获取的Dynamics实例URL,用户全程不需要手动输入任何地址,流程会自动完成授权。
- 权限配置:在你的Azure AD应用的“API权限”页面,必须添加上述提到的Graph和Discovery Service的委托权限,并且确保权限已获得管理员同意(或者允许用户自行同意,根据你的需求设置)。
- 多实例处理:如果用户租户下有多个Dynamics实例,建议增加一个选择环节,让用户确认要授权的实例,提升体验。
- 错误处理:要考虑用户没有Dynamics权限的情况,此时查询API会返回空列表,需要提示用户联系管理员开通权限。
这样整个流程就完全自动化了,用户只需要完成登录操作,剩下的资源ID获取和授权都由你的应用后台自动处理,完全不用手动输入URL~
内容的提问来源于stack exchange,提问作者iCode

