Using Azure AD groups authorization in ASP.NET Core for an Azure Blob Storage

This post show how Azure AD groups could be used to implement authorization for an Azure Blob storage and used in an ASP.NET Core Razor page application to authorize the identities. The groups are assigned the roles in the Azure Storage. Azure AD users are added to the Azure AD groups and inherit the group roles. The group ID is added to the claims of the tokens which can be used for authorization in the client application.

Code: https://github.com/damienbod/AspNetCoreAzureAdAzureStorage

Blogs in this series

Setup the groups in Azure AD

To implement this, two new user groups are created inside the Azure AD directory.

The required Azure AD users are added to the groups.

Add the role assignment for the groups to Azure Storage

The Azure Storage which was created in the previous post is opened and the new Azure AD groups can be assigned roles. The Storage Blob Contributor group and the Storage Blob reader group are add to the Azure Storage Role assignments.

You can see that the Storage Contributors Azure AD group is assigned the Storage Blob Data Contributor role and the Storage Reader Azure AD group is assigned the Storage Blob Data Reader role.

Add the group IDs to the tokens in Azure App registrations

Now the groups can be added to the id_token and the access token in the Azure App registrations. If you use a lot of groups in your organisation, you might not want to do this due to token size, but instead use Microsoft Graph in the applications to get the groups for the authenticated Identity. In the Token Configuration blade of the Azure App registration, the groups can be added as an optional claim.

To use the groups in the ASP.NET Core web application, only the security groups are required.

Implement the ASP.NET Core authorization handlers

The StorageBlobDataContributorRoleHandler implements the ASP.NET Core handler to authorize the identities. The handler implements the AuthorizationHandler with the required requirement. The handler retrieves the group claim from the claims with the group value of the group we set in the role assignments in the Azure Storage. The claims are extracted from the id_token or the user info endpoint. Only the group is validated in the ASP.NET Core application, not the actual role which is required for the Azure Storage access. There is no direct authorization with the Azure Storage Blob container. The authorization is done through the Azure AD groups.

By using the group claims, no extra API call is required to authorize the identity using the application. This is great, as long as the tokens don’t get to large in size.

public class StorageBlobDataContributorRoleHandler 
	: AuthorizationHandler<StorageBlobDataContributorRoleRequirement>
{
	protected override Task HandleRequirementAsync(
		AuthorizationHandlerContext context,
		StorageBlobDataContributorRoleRequirement requirement
	)
	{
		if (context == null)
			throw new ArgumentNullException(nameof(context));
		if (requirement == null)
			throw new ArgumentNullException(nameof(requirement));

		// StorageContributorsAzureADfiles
		var groupId = "6705345e-c37e-4f7a-b2d9-e2f43e029524";

		var spIdUserGroup = context.User.Claims
			.FirstOrDefault(t => t.Type == "groups" && 
				t.Value == groupId);

		if(spIdUserGroup != null)
		{
			context.Succeed(requirement);
		}

		return Task.CompletedTask;
	}
}

The handlers with the requirements are registered in the application in the Startup class. Policies are created for the requirement which can be then used in the application. Microsoft.Identity.Web is used to authenticate the user and the application.

services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
	.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
	.AddInMemoryTokenCaches();

services.AddAuthorization(options =>
{
	options.AddPolicy("StorageBlobDataContributorPolicy", 
		policyIsAdminRequirement =>
	{
		policyIsAdminRequirement
			.Requirements
			.Add(new StorageBlobDataContributorRoleRequirement());
	});
	options.AddPolicy("StorageBlobDataReaderPolicy", 
		policyIsAdminRequirement =>
	{
		policyIsAdminRequirement
			.Requirements
			.Add(new StorageBlobDataReaderRoleRequirement());
	});
});

services.AddRazorPages().AddMvcOptions(options =>
{
	var policy = new AuthorizationPolicyBuilder()
		.RequireAuthenticatedUser()
		.Build();
	options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();

The authorization policies can be applied as attributes on the class of ASP.NET Core Razor pages.

[Authorize(Policy = "StorageBlobDataContributorPolicy")]
[AuthorizeForScopes(Scopes = new string[] { 
   "https://storage.azure.com/user_impersonation" })]
public class AzStorageFilesModel : PageModel
{
    // code ...

When the application is started from Visual Studio, the group claims can be viewed and the handler will succeed if the Azure groups, users and role assignments are configured correctly.

Azure AD Groups can be used in this way to manage access to Azure AD storage in an ASP.NET Core. This works great but is a very dependent on Azure adminstration. For this to work good, you need access and control over the Azure AD tenant which is not always the case in companys. If the Azure Storage was extended with Tables or Queues, the roles can be applied to new groups or the existing ones. A lot depends on how the users, groups and applications are managed.

Links

https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles

Using Azure Management Libraries for .NET to manage Azure AD users, groups, and RBAC Role Assignments

https://management.azure.com/subscriptions/subscriptionId/providers/Microsoft.Authorization/roleAssignments?api-version=2015-07-01

https://docs.microsoft.com/en-us/rest/api/apimanagement/apimanagementrest/azure-api-management-rest-api-authentication

https://docs.microsoft.com/en-us/rest/api/authorization/role-assignment-rest-sample

https://github.com/mderriey/azure-identity-livestream

https://blog.soft-cor.com/empowering-developer-teams-to-manage-their-own-azure-rbac-permissions-in-highly-regulated-industries/

2 comments

  1. […] Using Azure AD groups authorization in ASP.NET Core for an Azure Blob Storage (Damien Bowden) […]

  2. […] Using Azure AD groups authorization in ASP.NET Core for an Azure Blob Storage – Damien Bowden […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.