问题
net core application. My requirement is to add group based authorization. I am user in Azure AD. I belong to the some group names starts with BR and AR. Users belong to the AR groups only should be able to access my APIs. Currently my client application is Swagger and I am hitting APIS only through swagger.
For example, In startup I can have the below code.
services.AddAuthorization(options => {
options.AddPolicy("AR-BitBucket-User",
policyBuilder => policyBuilder.RequireClaim("groups",
"6be4f534-dcf5-489e-b57d-c7bb46be8d6b"));
});
In controller,
[Authorize("AR-BitBucket-User")]
In the above approach, I am hard coding but I do not want to hard code. First of all I am not getting groups info in JWT token and I am getting
hasGroups:true in my JWT token. Instead of hard coding I want to get it from Graph API. Can someone help me how to do this? I am not able to get any related example in internet. So can someone help me?
回答1:
If you want to config your application to receive group claims, you need to set the "groupMembershipClaims" value as SecurityGroup
in the Manifest file.
In your application settings page on the Application Registration Portal , click on "Manifest" to open the inline manifest editor.
Edit the manifest by locating the "groupMembershipClaims" setting, and setting its value to "SecurityGroup".
Save the manifest.
{
...
"errorUrl": null,
"groupMembershipClaims": "SecurityGroup",
...
}
When the groups claim is enabled for an application, Azure AD includes a claim in the JWT and SAML tokens that contains the object identifiers (objectId) of all the groups to which the user belongs, including transitive group membership.
But please note that to ensure that the token size doesn't exceed HTTP header size limits, Azure AD limits the number of objectIds that it includes in the groups claim. If a user is member of more groups than the overage limit (150 for SAML tokens, 200 for JWT tokens), then Azure AD 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. For more details, please refer to the blog.
So you need to do some process :
Check for the claim _claim_names with one of the values being groups. This indicates overage.
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.
Of course , you can directly call Microsoft Graph API to retire current user's groups without using group claims
Regarding how to authorize based on that groups, you can create a policy. For more details, please refer to the document. For example
Startup.cs
services.AddAuthorization(options =>
{
options.AddPolicy("CheckGroups", policy =>
policy.Requirements.Add(new GroupsCheckRequirement("YourGroupID")));
});
services.AddScoped<IAuthorizationHandler, GroupsCheckHandler>();
GroupsCheckRequirement.cs:
public class GroupsCheckRequirement : IAuthorizationRequirement
{
public string groups;
public GroupsCheckRequirement(string groups)
{
this.groups = groups;
}
}
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);
}
}
}
And then using policy :
[Authorize(Policy = "CheckGroups")]
Besides, you also can implement it by ASP.NET Core middleware libraries. The asp.net middleware supports roles populated from claims by specifying the claim in the RoleClaimType
property of TokenValidationParameters
. Since the groups
claim contains the object ids of the security groups than actual names, you'd use the group ids instead of group names. For more details, please refer to the sample.
Startup.cs
// The following lines code instruct the asp.net core middleware to use the data in the "groups" claim in the Authorize attribute and User.IsInrole()
// See https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.2 for more info.
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
// Use the groups claim for populating roles
options.TokenValidationParameters.RoleClaimType = "groups";
});
Then using it
[Authorize(Roles = “Group-object-id")] // In controllers
// or
User.IsInRole("Group-object-id"); // In methods
来源:https://stackoverflow.com/questions/58534859/how-to-do-authorization-based-on-groups-in-net-core-app