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...

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.

  1. Get the AppId of the tenant-specific b2c-extensions-app.
  2. Construct the custom attribute name like this:
    • extension_$((Get-MgApplication | Where-Object { $_.DisplayName.StartsWith("b2c-extensions-app") }).AppId.Replace('-', ''))_attribute.
  3. Create a hashtable with the attribute name and value.
  4. Create user with New-MgUser and 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.

Custom GameMaster attribute

There are two main ways to assign this attribute to a user:

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:

b2c-extensions-app in AD portal

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

Graph Explorer results view

References

Found something inaccurate or plain wrong? Was this content helpful to you? Let me know!

šŸ“§ codez@deedx.cz