Creating B2C users through the Microsoft Graph

The Microsoft Graph finally should have all functionality that previously only the Azure AD Graph had, such as the ability to create and manage B2C user accounts. Earlier you had to create them through the Azure AD Graph, in order to do certain things such as setting the account type as local and managing username.

The blog post assumes that you have already created an Azure AD B2C tenant and have created yourself a local global administrator account in the tenant (not B2B, just to make things easier when it comes to tokens).

So, let’s start with our usual “capture the Graph Explorer access token” method. Go to https://developer.microsoft.com/en-us/graph/graph-explorer and sign in with your B2C tenant’s global administrator account. Make sure you add the “User.ReadWrite.All” permisison. Run the following PowerShell and then copy the graph explorer URL to the clipboard:

function Get-AccessTokenFromGraphExplorerUrlOnClipboard
{
    [CmdletBinding()]
    [Alias()]
    Param
    ([String[]] $RequiredScopes = @())
  
    Process
    {
        $token = $null
        $first = $true
        do {
            if(!$first) {
                Sleep -Seconds 1   
            }
            $first = $false
  
            Write-Verbose "Trying to get Graph Explorer URL from clipboard"
            $url = Get-Clipboard
            if($url -ne $null -and $url.StartsWith("https://developer.microsoft.com/en-us/graph/graph-explorer#access_token=")) {
                $token = $url -split "[=&]" | Select -Index 1
            }
        } while($token -eq $null -or !$token.StartsWith("ey"))
  
        $token1 = $token.Split(".")[1]
        if(($token1.Length % 4) -gt 0) {
            $token1 = $token1.PadRight($token1.Length + (4 - ($token1.Length % 4)), "=")
        }
        $tokenAsObject = $token1 |ConvertFrom-Base64 | ConvertFrom-Json
        $RequiredScopes | Where{$_ -notin ($tokenAsObject.scp -split " ")} | Foreach {
            Write-Warning "Missing scope: $($_)"
        }

        $token
    }
}
 
Write-Host -ForegroundColor Green "Sign into graph explorer and copy the url with the access token - https://developer.microsoft.com/en-us/graph/graph-explorer"
$token = Get-AccessTokenFromGraphExplorerUrlOnClipboard -Verbose -RequiredScopes @("User.ReadWrite.All")
$restparams = @{headers = @{Authorization = "Bearer $token"}}

Now that we have our token ready, we can create a local B2C with email address as username the following way:

$body = @{
    identities = @(
        @{
            signInType = "emailAddress"
            issuer = "gwb2c.onmicrosoft.com"
            issuerAssignedId = "marius@test.com"
        }
    )
    displayName = "Marius Solbakken"
    passwordProfile = @{
        password = "TestPass!1"
    }
} | ConvertTo-Json
Invoke-RestMethod -Body $body -Uri "https://graph.microsoft.com/v1.0/users" -Method Post @restparams -ContentType "application/json"

Or we can create one with username instead of email address:

$body = @{
    identities = @(
        @{
            signInType = "userName"
            issuer = "gwb2c.onmicrosoft.com"
            issuerAssignedId = "marius"
        }
    )
    displayName = "Marius Solbakken"
    passwordProfile = @{
        password = "TestPass!1"
    }
} | ConvertTo-Json
Invoke-RestMethod -Body $body -Uri "https://graph.microsoft.com/v1.0/users" -Method Post @restparams -ContentType "application/json"

Or even a user with a username and two email addresses as signin names:

$body = @{
    identities = @(
        @{
            signInType = "userName"
            issuer = "gwb2c.onmicrosoft.com"
            issuerAssignedId = "testuser"
        }
        @{
            signInType = "emailAddress1"
            issuer = "gwb2c.onmicrosoft.com"
            issuerAssignedId = "testuser1@test.com"
        }
        @{
            signInType = "emailAddress2"
            issuer = "gwb2c.onmicrosoft.com"
            issuerAssignedId = "other@someone.com"
        }
    )
    displayName = "Marius Solbakken"
    passwordProfile = @{
        password = "TestPass!1"
    }
} | ConvertTo-Json
Invoke-RestMethod -Body $body -Uri "https://graph.microsoft.com/v1.0/users" -Method Post @restparams -ContentType "application/json"

Of course, if you have a migration scenario in which you are enabling federation to an old platform as a temporary solution, you can use the object identity type to enable signInType “federated”, issuer “issuer id of your temporary IDP” and issuerAssignedId as the identifier claim form your IDP.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s