如何使用Microsoft Graph API在.net核心应用程序中获取所有授权组?

问题描述:

我正在从事.net核心项目.我正在尝试使用AD组实施授权.我的要求是,天蓝色广告中有很多组.如果当前用户属于azure广告中的任何可用组,那么我想授权这些用户访问.net核心应用程序中编写的api.我尝试如下.我在下面两个类中添加了

I am working on .net core project. I am trying to implement authorize using AD groups. My requirement is, I have many groups in the azure ad. If the current user belongs to any of the available groups in azure ad then I want to authorize those users to access apis written in .net core application. I tried as below. I have added below two classes

 public class IsMemberOfGroupHandler : AuthorizationHandler<IsMemberOfGroupRequirement>
    {
        protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context, IsMemberOfGroupRequirement requirement)
        {
            var groupClaim = context.User.Claims
                 .FirstOrDefault(claim => claim.Type == "groups" &&
                     claim.Value.Equals(requirement.GroupId, StringComparison.InvariantCultureIgnoreCase));

            if (groupClaim != null)
                context.Succeed(requirement);

            return Task.CompletedTask;
        }
    }

 public class IsMemberOfGroupRequirement : IAuthorizationRequirement
    {
        public readonly string GroupId;
        public readonly string GroupName;

        public IsMemberOfGroupRequirement(string groupName, string groupId)
        {
            GroupName = groupName;
            GroupId = groupId;
        }
    }

下面是我的启动班.

 services.AddAuthorization(options =>
            {
                var adGroupConfig = new List<AdGroupConfig>();
                _configuration.Bind("AdGroups", adGroupConfig);

                foreach (var adGroup in adGroupConfig)
                    options.AddPolicy(
                        adGroup.GroupName,
                        policy =>
                            policy.AddRequirements(new IsMemberOfGroupRequirement(adGroup.GroupName, adGroup.GroupId)));
            });

以上代码检查配置文件中可用的组.现在,我的要求是使用Microsoft图形API来获取所有可用的组.我找不到任何方法来处理此要求.有人可以帮我弄这个吗?任何帮助,将不胜感激.谢谢

Above code checks groups available in configuration file. Now my requirement is use microsoft graph api to get all the available groups. I could not find any way to handle this requirement. Can someone help me with this? Any help would be appreciated. Thanks

请首先检查

Please firstly check this code sample , which use OpenID Connect to sign in users and use MSAL to get the Microsoft Graph API token to retire groups .

如果将您的应用程序配置为通过编辑清单来接收团体声明:

If config the your application to receive group claims by editing the manifest :

{
  ...
  "errorUrl": null,
  "groupMembershipClaims": "SecurityGroup",
  ...
}

已登录用户所属的安全组的对象ID在令牌的组声明中返回.

The object id of the security groups the signed in user is member of is returned in the groups claim of the token.

如果用户属于超过超出限制的组的更多成员(SAML令牌为150,JWT令牌为200),则Microsoft身份平台不会在令牌中发出组声明.相反,它在令牌中包含超额声明,该声明指示应用程序查询Graph API以检索用户的组成员身份.

If a user is member of more groups than the overage limit (150 for SAML tokens, 200 for JWT tokens), then the Microsoft Identity Platform does not emit the groups claim in the token. Instead, it includes an overage claim in the token that indicates to the application to query the Graph API to retrieve the user’s group membership.

{
  ...
  "_claim_names": {
    "groups": "src1"
    },
    {
   "_claim_sources": {
    "src1": {
        "endpoint":"[Graph Url to get this user's group membership from]"
        }
    }
  ...
}

因此您可以按照以下过程进行操作:

So you can follow the process :

  1. 检查其中一个值为组的索赔_claim_names.这表明超量了.

  1. Check for the claim _claim_names with one of the values being groups. This indicates overage.

如果找到,请调用_claim_sources中指定的端点以获取用户组.

If found, make a call to the endpoint specified in _claim_sources to fetch user’s groups.

如果未找到,请查看用户所属组的组声明.

If none found, look into the groups claim for user’s groups.

当然,您可以使用group claims直接调用Microsoft Graph API来退出当前用户的组而无需:

Of course , you can directly call Microsoft Graph API to retire current user's groups without using group claims :

然后您可以基于该组进行授权.例如,如果使用策略:

You can then authorize based on that groups . For example , if using policy :

services.AddAuthorization(options =>
{
    options.AddPolicy("GroupsCheck", policy =>
        policy.Requirements.Add(new GroupsCheckRequirement("YourGroupID")));
});
services.AddScoped<IAuthorizationHandler, GroupsCheckHandler>();

GroupsCheckRequirement.cs:

GroupsCheckRequirement.cs:

public class GroupsCheckRequirement : IAuthorizationRequirement
{
    public string groups;

    public GroupsCheckRequirement(string groups)
    {
        this.groups = groups;
    }
}

GroupsCheckHandler.cs:

GroupsCheckHandler.cs :

public class GroupsCheckHandler : AuthorizationHandler<GroupsCheckRequirement>
{
    private readonly ITokenAcquisition tokenAcquisition;
    private readonly IMSGraphService graphService;

    public GroupsCheckHandler(ITokenAcquisition tokenAcquisition, IMSGraphService MSGraphService)
    {
        this.tokenAcquisition = tokenAcquisition;
        this.graphService = MSGraphService;
    }
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                              GroupsCheckRequirement requirement)
    {
        string accessToken = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] { Constants.ScopeUserRead, Constants.ScopeDirectoryReadAll });

        User me = await graphService.GetMeAsync(accessToken);

        IList<Group> groups = await graphService.GetMyMemberOfGroupsAsync(accessToken);

        var result = false;
        foreach (var group in groups)
        {
            if (requirement.groups.Equals(group.Id))
            {
                result = true;
            }
        }

        if (result)
        {
            context.Succeed(requirement);
        }

    }


}

然后使用策略:

[Authorize(Policy = "GroupsCheck")]