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.