如何通过Graph API获取B2C中的自定义用户属性(Claims)
我已成功创建了使用新B2C租户做身份验证的应用,可正常登录并调用API。
我为用户新增了包含Roles属性在内的自定义属性,在「用户流(User Flows)」中配置了1个登录流,已勾选登录时返回Roles声明,同时也配置了用户信息编辑流。可查看已添加的扩展用户属性、声明返回勾选配置,以及用户流编辑后返回的解码令牌,令牌中确实包含扩展声明及对应值。
但我调用Graph API查询用户及扩展属性时,这些在B2C中创建的扩展属性无法返回。
我可通过Graph API正常访问用户,也能通过代码调用Graph API为用户添加扩展属性,支持增删改查操作,通过Graph API创建的扩展后续可正常获取,但通过B2C用户流创建的扩展无法获取。下方是添加扩展的代码,两种场景添加的扩展都和返回声明中对应的B2C用户属性无关联:
// Add extension without the guid from b2c_extensions_app var extension = new OpenTypeExtension() { ExtensionName = $"extension_Roles", AdditionalData = new Dictionary<string, object>() { { "Roles", value} } }; await _graphServiceUsers[userId].Extensions.Request().AddAsync(extension); // Add extension with the guid from b2c_extensions_app var extension2= new OpenTypeExtension() { ExtensionName = $"extension_00000000-e062-0000-8ec8-800000000003_Roles", AdditionalData = new Dictionary<string, object>() { { "Roles", value} } }; await _graphServiceUsers[userId].Extensions.Request().AddAsync(extension2);
我使用下方代码查询带扩展的用户,仅能获取到Graph API创建的扩展,无法获取到令牌声明中展示的B2C自定义扩展:
_graphServiceUsers[userId].Request().Select(UserSelectExpression).Expand("extensions").GetAsync();
所有自定义属性看起来是互相割裂的,我需要通过Graph API修改作为声明返回的属性值。实测仅能获取到Graph API创建的扩展属性,不包含我在B2C中添加的属性,令牌中映射的声明值与我通过Graph API添加并查询到的值不一致。
附加信息
我使用Graph API应用调用接口,已经添加了所有建议的权限。
在Graph Explorer中测试结果与C#代码结果一致,使用的请求地址为:
https://graph.microsoft.com/v1.0/users/600001c5-0000-49b9-89c5-0000c80000fc?$select=displayName,identities,extension_39b4801c-5782-48d4-be6a-1cae6a8a881a_Roles
调用后返回异常。
解决方案更新
如果有朋友遇到相同问题,这里补充说明实际问题原因:Graph API的入门使用确实有一定门槛,截至当前,稳定版v1.0 Graph API不支持获取B2C自定义扩展属性,需要使用Beta版Nuget包,或者调用Beta版Graph API(graph.microsoft.com/beta)才能正常获取所有扩展属性:
- 测试可用的Nuget包是Microsoft.Graph.Beta 4.21.0-preview
- 2021年11月25日发布的Microsoft.Graph稳定版4.11.0无法获取扩展属性
注意:非常重要的一点是,extension_xxx_Roles这类扩展名中的guid需要去掉所有横杠:
- 正确格式:
extension_39b0000c570000d4be6a1cae7a9a000a_Roles - 错误格式:
extension_39b0000-c570-000d-4be6a1-cae7a9a000a_Roles(需要移除guid中所有横杠)
另外如果只想查询指定扩展属性,可在请求中指定对应带无横杠guid的扩展字段,示例代码如下,第一种写法加载用户的所有属性,第二种写法仅加载指定的自定义扩展属性:
var user = await _graphServiceClient.Users[userId].Request().GetAsync(); var user2 = await _graphServiceClient.Users[userId].Request().Select("id,extension_39b0000c570000d4be6a1cae7a9a000a_Roles").GetAsync();
内容的提问来源于stack exchange,提问作者Roberto

