Azure B2C custom user attributes with PowerShell Core
azure b2c powershell
How to create an Azure AD B2C user with custom attribute using PowerShell Core.
September 29, 2021
This post is a beginning of my Azure AD B2C scripting journey...
- Azure B2C custom user attributes with PowerShell Core
- Automating Azure B2C creation with PowerShell Core
- Update Redirect URIs from Azure DevOps
- Automating Azure AD B2C creation with Terraform
There's also a GitHub repository with full scripts.
For a recent project I was writing a provisioning script for test users in Azure AD B2C. As straightforward as it may look, there are some difficulties when it comes to custom attributes (extension properties, custom claims - these all refer to the same thing in this context) and creating users that have them.
The B2C documentation mentions that it's possible to create and update users with extension attributes, but unfortunately doesn't specify how to do that. Let's figure it out in this post.
tl;dr
Use the Microsoft.Graph PowerShell module with User.ReadWrite.All and Application.Read.All scopes.
- Get the
AppIdof the tenant-specificb2c-extensions-app. - Construct the custom attribute name like this:
extension_$((Get-MgApplication | Where-Object { $_.DisplayName.StartsWith("b2c-extensions-app") }).AppId.Replace('-', ''))_attribute.
- Create a hashtable with the attribute name and value.
- Create user with
New-MgUserand add the attribute in-AdditionalProperties.
Custom B2C attributes
Azure AD B2C supports custom attributes on user accounts and ASP.NET Core is then able to process them directly from authorization claims. The complication is that there's no UI in the B2C portal which would allow editing these attributes.
Let's imagine that we have a custom attribute called "GameMaster" which was created using the Azure portal.

There are two main ways to assign this attribute to a user:
- Using the
AzureADPowerShell module (Windows only, doesn't support Core).(Get-AzureADExtensionProperty | Where-Object { $_.Name.Contains("GameMaster") }).Name$extension = [System.Collections.Generic.Dictionary[string, string]]::new()$extension.Add($gameMasterExtensionProp, $userGameMaster)New-AzureADUser ... -ExtensionProperty $extension
- Using Microsoft Graph.
- Directly through REST API.
- With .NET SDK, sample here: https://github.com/Azure-Samples/ms-identity-dotnetcore-b2c-account-management
- With
Microsoft.GraphPowerShell module.
I used all of them, but to bypass the need of using the Windows-only AzureAD module in a scripted environment, I ended up with the Microsoft.Graph module method.
This post is about a PowerShell script which will create an user and assign them the GameMaster attribute.
The b2c-extensions-app application
Every Azure AD B2C tenant stores custom attributes in a dedicated application registration just for this tenant. Its name is kind of strange, but self-explanatory:

When assigning custom attributes to users, we can't simply use the attribute name (GameMaster), but it's necessary to also include this b2c-extensions-app's ID like this:
extension_<extensionsAppID>_GameMaster
Thankfully, for the actual access token that our application will get from Azure AD this gets shortened to:
"extension_GameMaster": false
Creating a user with PowerShell Core
Equipped with the knowledge from previous sections, we can start creating users with PowerShell Core.
First, make sure that you have the Microsoft.Graph module installed.
Get-InstalledModule Microsoft.Graph
And if not, install it:
Install-Module Microsoft.Graph
Authenticating to MS Graph can be done interactively, using the Connect-MgGraph commandlet.
Yes, it's indeed MgGraph and not MsGraph, which caught me by suprise :)
Connect-MgGraph -TenantId $tenantId -Scopes "User.ReadWrite.All Application.Read.All"
Where $tenantId can be either the GUID or tenant name (like mytenant.onmicrosoft.com).
And then the tricky part is creating the accurate custom property name for this tenant. I'm using this contraption:
$gameMasterExtensionProp = "extension_$((Get-MgApplication | Where-Object { $_.DisplayName.StartsWith("b2c-extensions-app") }).AppId.Replace('-', ''))_GameMaster";
It's basically looking for an app with the well-known b2c-extensions-app name and removing all - from its ID.
Following is the creation of user's password and login identity (using just e-mail and registering as local account):
$passwordProfile = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphPasswordProfile
$passwordProfile.Password = $userPassword
$passwordProfile.ForceChangePasswordNextSignIn = $false
$identity = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphObjectIdentity
$identity.SignInType = "emailAddress"
$identity.Issuer = $tenantId
$identity.IssuerAssignedId = $userEmail
And our extension:
$extension = @{
$gameMasterExtensionProp = $userGameMaster # 'true' or 'false'
}
Finally, the New-MgUser commandlet creates this user:
New-MgUser -DisplayName $user.displayName `
-AccountEnabled `
-Identities $identity `
-PasswordProfile $PasswordProfile `
-CreationType LocalAccount `
-AdditionalProperties $extension
To test that this worked, Microsoft Graph Explorer can be used.
Hint: To sign into a specific tenant, use:
https://developer.microsoft.com/en-us/graph/graph-explorer?tenant=<tenant>.onmicrosoft.com.This is useful, because the B2C tenant is separate from its "parent" Azure tenant.
Sign in with your admin account and use the /users endpoint to list all users. In order to display the custom attribute, you have to explicitly ask for it:
https://graph.microsoft.com/v1.0/users?$select=id,displayName,extension_<extensionAppId>_GameMaster

References
Feedback
Found something inaccurate or plain wrong? Was this content helpful to you? Let me know!
š§ codez@deedx.cz