Introduction:
Azure AD B2C is a powerful customer identity solution, but it comes with some limitations compared to Microsoft Entra ID (formerly Azure Active Directory). One major limitation is the lack of native support for app roles and group claims. While Microsoft Entra ID supports these features out of the box, Azure AD B2C does not expose group membership or app role assignments in the ID token.
However, since Azure AD B2C is built on top of the Microsoft Entra ID framework, we can bridge this gap by leveraging the Microsoft Graph API. In this blog, I’ll Walk through how I built a custom solution using:
- A backend Azure Function that queries the Microsoft Graph API,
- A set of custom policies that call the function during sign-in, and
- The inclusion of app role and group claims in the B2C-issued token.
The Problem: No Native Support for Groups or Roles in AD B2C
Azure AD B2C doesn’t natively issue claims for:
- Group memberships
- App role assignments
This is because B2C is optimized for consumer identity scenarios and does not expose the same directory APIs as standard Microsoft Entra tenants. As a result, applications that depend on RBAC (role-based access control) or group-based authorization need a workaround.
The Solution: Use Microsoft Graph to Build a Custom Solution to Manage App Roles and Group Membership
To address this limitation, I built a complete end-to-end solution that includes:
1. Web Application for Admins
The B2C App Roles Management Web App enables administrators to:
- Assign app roles to B2C users.
- Manage group memberships for users in the B2C directory.
- View assigned roles and group information for each user.
This portal is built using .NET and integrates with the Microsoft Graph API using client credentials to perform directory updates. It provides a clean UI and API endpoints to manage these assignments programmatically.
Azure Function to retrieve App Roles and Group Details of the Authenticated User
I created a custom Azure Function that:
- Authenticates using client credentials against Microsoft Graph.
- Fetches assigned app roles for the user.
- Retrieves the user’s group memberships.
- Returns both values as JSON.
- Is called inside a custom policy using B2C’s REST API integration.
Click here to get the Azure Function source How the Function Works
How the Function Works?
The Azure Function uses Microsoft Graph SDK to query both:
- App role assignments via /appRoleAssignedTo
- Group memberships via /memberOf
Here’s a simplified view of the logic:
var appRoles = await graphClient
.ServicePrincipals[servicePrincipalId]
.AppRoleAssignedTo
.Request()
.Filter($"principalId eq {userObjectId}")
.GetAsync();
var groups = await graphClient
.Users[userObjectId]
.MemberOf
.Request()
.GetAsync();
It returns a response like:
{
"roles": ["Admin", "Editor"],
"groups": ["Marketing", "Developers"]
}
Integrating with Azure AD B2C Custom Policies
Define the REST API in TrustFrameworkExtensions.xml
<TechnicalProfiles>
<TechnicalProfile Id="GetUserAppRoleAssignment">
<DisplayName>Retrieves security groups assigned to the user</DisplayName>
<Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Metadata>
<!-- TODO: change this -->
<Item Key="ServiceUrl">https://<your function name>.azurewebsites.net/api/ManageB2CAppRoles</Item>
<Item Key="AuthenticationType">None</Item>
<Item Key="SendClaimsIn">Body</Item>
<Item Key="AllowInsecureAuthInProduction">true</Item>
<Item Key="IncludeClaimResolvingInClaimsHandling">true</Item>
</Metadata>
<InputClaims>
<InputClaim Required="true" ClaimTypeReferenceId="objectId" />
<!-- this B2C tenant id -->
<InputClaim ClaimTypeReferenceId="tenantId" DefaultValue="{Policy:TenantObjectId}" />
<!-- The App we're signing in to -->
<InputClaim ClaimTypeReferenceId="client_id" PartnerClaimType="clientId" DefaultValue="{OIDC:ClientId}" />
<!-- specify that we want both roles and groups back -->
<InputClaim ClaimTypeReferenceId="scope" DefaultValue="roles groups" AlwaysUseDefaultValue="true" />
</InputClaims>
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="roles" />
<OutputClaim ClaimTypeReferenceId="groups" />
<OutputClaim ClaimTypeReferenceId="tenantId" DefaultValue="{Policy:TenantObjectId}" AlwaysUseDefaultValue="true" />
</OutputClaims>
<UseTechnicalProfileForSessionManagement ReferenceId="SM-Noop" />
</TechnicalProfile>
Call the REST API During Orchestration
In your B2C_1A_SIGNUPORSIGNIN_APPROLE.xml file:
<OrchestrationStep Order="7" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="GetUserAppRoleAssignment" TechnicalProfileReferenceId="GetUserAppRoleAssignment" />
</ClaimsExchanges>
</OrchestrationStep>
Return the Claims in the Token
Add the output claims to the final JWT token issuer:
<OutputClaims>
<OutputClaim ClaimTypeReferenceId="groups" />
<OutputClaim ClaimTypeReferenceId="roles" />
</OutputClaims>
When you test the user flow from the portal, you will get a role, and group claims as shown in the figure below.

Secure the Azure Function
You should:
- Use Azure App Settings or Key Vault to store client secrets.
- Add API key or JWT validation to restrict who can call the function.
- Use Managed Identity for better security (optional enhancement).
This solution brings the enterprise-grade directory capabilities of Microsoft Entra ID into Azure AD B2C by tapping into Graph API during authentication.
This approach allows you to implement RBAC (role-based access control) and group-based personalization in your B2C-secured apps, something not possible with default B2C behavior.
If you’re building enterprise apps with Azure AD B2C and need advanced claims, I highly recommend adopting this pattern.
Summary:
Azure AD B2C does not natively support app roles and group claims like Microsoft Entra ID, but since it’s built on the same underlying framework, these features can be extended using the Microsoft Graph API and custom policies. To overcome this limitation, I developed a custom solution consisting of a web application to manage app roles and group memberships, an Azure Function to retrieve this data at runtime, and custom B2C policies to enrich the token with role and group claims. This approach enables fine-grained access control and enterprise-level authorization for applications using Azure AD B2C, bringing it closer to Microsoft Entra ID’s capabilities. The full implementation is available on GitHub for customization and reuse.
📁 Useful Resources
App Roles & Group Management UI