Azure Active Directory, the advanced logo

Iterating Group memberships using Claims in .NET Core

Reading Time: 5 minutes.

Another case, where there’s plenty of documentation, but it just doesn’t seem to be comprehensive enough or just doesn’t apply for any of the cases that I have – for whatever reason. Maybe my cases are wrong, or I’m just bad at googling, but I’ve struggled to find a good page documenting this.

Perfect case for another blog post about the topic, then – perhaps someone else will find it useful!

This post answers the question: How to get Claims for a user in .NET Core? Additionally, it answers how to configure your app in Azure AD to request Claims to be returned with the user principal. It also shows how to iterate these Claims in your C# code, using a group membership check as an example.

Introduction

I posted earlier about how to get the current user in .NET Core. That post leaves out some of the basis work you need to do before you even get to that point – a shortcoming, that was made painfully obvious by a couple of comments on that article.

This ties into the broader topic of gathering information about the current – or any other, for that matter – user in your system. I’ve posted something about this before, on how to handle the user object you get back, but I didn’t go into the details of configuring your application to actually request and use those Claims.

In this article, we’ll go through how to configure your application registration with Azure Active Directory to return the Claims detailing group memberships!

By default, you only have access to a few Claims. The screenshot below details this in action:

Solution

The solution consists of 2 different steps. First of all, you need to force AAD to return the group membership info, and after that, you need to have a meaningful way of checking the claims in your code.

All clear at this point? Great, let’s jump into it!

How to request group claims from AAD?

You need to modify your application manifest file to explicitly, specifically request group membership claims to be returned. This happens by specifying either of the two options below:

Locate the “groupMembershipClaims” setting. Set its value to either “SecurityGroup” or “All”. The way these 2 work is as follows:

  • SecurityGroup
    • Groups claim will contain the identifiers of all security groups of which the user is a member.
  • All
    • Groups claim will contain the identifiers of all security groups and all distribution lists of which the user is a member

The latter can easily contain hundreds of entries – so be aware of the (hopefully obvious) performance considerations! Only request the Security Groups if possible.

Additionally, according to Microsoft’s documentation, you can also specify these values in the groupMembershipClaims – section (although I have never needed to specify them):

  • DistributionList
  • DirectoryRole

In your application manifest JSON, it looks something like this:

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

I’ve also included a whole example JSON below for your reference.

Example of an app manifest requesting group membership claims in Azure AD

{
	"id": "22af0087-1337-1337-1337-363738a49ea9",
	"acceptMappedClaims": null,
	"accessTokenAcceptedVersion": null,
	"addIns": [],
	"allowPublicClient": null,
	"appId": "9bbe55d1-1337-1337-1337-e69344bf7f2c",
	"appRoles": [],
	"oauth2AllowUrlPathMatching": false,
	"createdDateTime": "2019-09-03T20:11:34Z",
	"groupMembershipClaims": "All",
	"identifierUris": [],
	"informationalUrls": {
		"termsOfService": null,
		"support": null,
		"privacy": null,
		"marketing": null
	},
	"keyCredentials": [],
	"knownClientApplications": [],
	"logoUrl": null,
	"logoutUrl": null,
	"name": "appname",
	"oauth2AllowIdTokenImplicitFlow": true,
	"oauth2AllowImplicitFlow": true,
	"oauth2Permissions": [],
	"oauth2RequirePostResponse": false,
	"optionalClaims": null,
	"orgRestrictions": [],
	"parentalControlSettings": {
		"countriesBlockedForMinors": [],
		"legalAgeGroupRule": "Allow"
	}
	],
	"preAuthorizedApplications": [],
	"publisherDomain": "yourdomain.onmicrosoft.com",
	"replyUrlsWithType": [
		{
			"url": "https://localhost:44307/signin-oidc",
			"type": "Web"
		},
		{
			"url": "https://localhost:44307/",
			"type": "Web"
		}
	],
	"requiredResourceAccess": [
		{
			"resourceAppId": "00000003-0000-0000-c000-000000000000",
			"resourceAccess": [
				{
					"id": "64a6cdd6-aab1-4aaf-94b8-3cc8405e90d0",
					"type": "Scope"
				}
			]
		}
	],
	"samlMetadataUrl": null,
	"signInUrl": null,
	"signInAudience": "AzureADMyOrg",
	"tags": [],
	"tokenEncryptionKeyId": null
}

An interesting additional point can be made about the optionalClaims. You can use this part of the manifest to request additional claims from AAD. Basically, depending on how you’re configuring your application, you might need to request additional claims such as extended user profile properties through saml2Token by specifying additional claims. Same applies to varying degree and use cases to idToken, saml2Token and accessToken.

The example below requests an extension attribute from Azure AD, like a property coming from on-prem Active Directory synchronization:

        ...
        "optionalClaims": {
		"idToken": [],
                "accessToken": [],
                "saml2Token": [ 
                { 
                    "name": "extension_ab603c56068041afb2f6832e2a17e237_skypeId",
                    "source": "user", 
                    "essential": true
                }
                ]
	},
        ...

Note, that in order to also retrieve the ID tokens or Access tokens directly to your application from Azure AD, you need to also enable the corresponding options under app registration > Authentication.

How to enable Azure Active Directory to return tokens for your app? This form can be found under "Authentication" section of your Azure app registration.
How to enable Azure Active Directory to return tokens for your app? This form can be found under “Authentication” section of your Azure app registration.

See more on the optional claims in the References section!

Now, on with the actual topic:

Add the API permissions to request the Groups memberships

Basically, you’ll need either one of the two following permissions:

  • Groups.Read.All (recommended)
  • Directory.Read.All (higher permissions – also works)

Both of these permissions require admin consent.

Iterating the Claims in your code

Next, you need to find a nice way to use the claims in your code.

After the configuration above has been done, it’ll yield output like this to your user objects.

The way you can use this, for example, would be to check group membership of a user, like shown below – grab all Claims of type “groups” and compare their value to the ID (Guid) of your group.

How to iterate Claims (group memberships) in your C# .NET Core code?
How to iterate Claims (group memberships) in your C# .NET Core code?

And you should be good!

As a fairly large caveat, though, it’s useful to notice, that writing helper methods and calling them everywhere in your application is not a good way to check for permissions in ASP.NET Core. Instead, for anything larger than a few views and/or APIs, you should use authorization attributes and limit visibility of your components using AuthorizeViews or build custom components on top of these. See References for more info.

References

Antti K. Koskela

Antti Koskela is a proud digital native nomadic millennial full stack developer (is that enough funny buzzwords? That's definitely enough funny buzzwords!), who works as a Solutions Architect for Valo Intranet, the product that will make you fall in love with your intranet. Working with the global partner network, he's responsible for the success of Valo deployments happening all around the world.

He's been a developer from 2004 (starting with PHP and Java), and he's been bending and twisting SharePoint into different shapes since MOSS. Nowadays he's not only working on SharePoint, but also on .NET projects, Azure, Office 365 and a lot of other stuff.

This is his personal professional (e.g. professional, but definitely personal) blog.
mm

Leave a Reply

avatar
5000
  Subscribe  
Notify of