Creating a user and assigning it to an Azure AD role using Microsoft.Graph PS Module

Going forward, the Azure AD PowerShell Module will not be updated, and Microsoft has stated that it is the Microsoft.Graph PowerShell Module that will be used. This makes sense, as this is auto-generated based on the Microsoft Graph Odata, not requiring Microsoft to maintain several things. However, right now, some of the PowerShell verbs are not really following best practices. Anyway, here is how to do some simple things πŸ™‚

Ensure the latest version of Microsoft.Graph is installed

The below code can be used in top of a script, in order to ensure Microsoft.Graph is installed and up to date.

    Write-Verbose "Loading Microsoft.Graph module"
    $connectCommand = Get-Command Connect-MgGraph -ErrorAction SilentlyContinue

    if(!$connectCommand) {
        Write-Warning "Could not find Microsoft.Graph module, trying to install..."
        Install-Module Microsoft.Graph -Scope CurrentUser -ErrorAction Stop
    } else {
        $latest = Find-Module Microsoft.Graph 
        if($latest.Version -gt $connectCommand.Module.Version) {
            Write-Warning "Microsoft.Graph module version $($connectCommand.Module.Version) installed, trying to update to version $($latest.Version)"
            Update-Module Microsoft.Graph -ErrorAction Stop

Connecting using interactive signin

The Connect-MgGraph cmdlet can be used to sign in. What is nice about this cmdlet, is that you can limit the scopes, but it also means that you need to define exactly what you want to do:

$connectResult = Connect-MgGraph -Scopes "User.ReadWrite.All","Application.ReadWrite.All","Domain.Read.All","RoleManagement.ReadWrite.Directory" -ErrorAction Stop

When running this, a browser window will appear, with regular Azure AD signin. You need permissions to consent the required scopes, in order to sign in.

If you need to sign into a tenant using a B2B guest account, you need to provide the -Tenant option, in order to tell Azure AD which tenant to sign into.

Connecting using access token

Let’s say you already have an access token, such as using ROPC or other means of signing in, this can be provided to Connect-MgGraph using the -AccessToken option. To demo this, you can use a token from the Microsoft Graph Explorer:

Connect-MgGraph -AccessToken 'eyJ0eXAiOiJKV1QiLCJub25-------t1WM1mKbxHx3UAA'

Create user

In order to create a user, many of the same parameters as New-AzureADUser is needed, such as UserPrincipalName, DisplayName etc. Notice that PasswordProfile is provided as a hashmap:

$PasswordProfile = @{}
$PasswordProfile["Password"]= ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!?.;,._".ToCharArray() | Get-random -Count 50) -join ""
$PasswordProfile["ForceChangePasswordNextSignIn"] = $false
$user = New-MgUser -UserPrincipalName "" -AccountEnabled:$true -DisplayName "Test User" -MailNickname "test.user" -PasswordPolicies DisablePasswordExpiration -PasswordProfile $PasswordProfile

Onboard unused Azure AD roles

In this scenario, we want to use Global reader, Security reader, SharePoint Administrator and Authentication Policy Administrator, so we need to onboard them using New-MgDirectoryRole:

# Global reader, Security reader, SharePoint Administrator and Authentication Policy Administrator
$requiredRoleTemplates = Get-MgDirectoryRoleTemplate | Where-Object Id -in "f2ef992c-3afb-46b9-b7cf-a126ee74c451","5d6b6bb7-de71-4623-b4af-96380a352509","f28a1f50-f6e7-4571-818b-6a12f2af6b6c","0526716b-113d-4c15-b2c8-68e3c22b9f80"

# Get all roles
$aadRoles = Get-MgDirectoryRole

# Onboard any unused role that we need
$requiredRoleTemplates |
    Where-Object {!($aadRoles | Where-Object RoleTemplateId -eq $_.Id)} |
    ForEach-Object {
        Write-Verbose "Role template '$($_.DisplayName)' with template id $($_.Id) has never been used in this tenant. Onboarding the role before use." -Verbose
        New-MgDirectoryRole -RoleTemplateId $_.Id
    } |

Add user to role

The following is an example on how to add a user to a role – which may seem cryptic. And it is… Essentially, we are oroviding the raw body to the New-MgDirectoryRoleMemberByRef cmdlet, as documented here. Hopefully this experience will be improved at some point in the future, as this really is not how an SDK should behave πŸ™‚

# Get all roles again
$aadRoles = Get-MgDirectoryRole

$requiredRoleTemplates |
    ForEach-Object {
        $aadRoles | Where-Object RoleTemplateId -eq $_.Id
    } | ForEach-Object {
        $Members = Get-MgDirectoryRoleMember -DirectoryRoleId $_.Id
        if($User.Id -notin $Members.Id) {
            Write-Verbose "Adding user to Azure AD role '$($_.DisplayName)'" -Verbose
            New-MgDirectoryRoleMemberByRef -DirectoryRoleId $_.Id -BodyParameter @{"" = "$($user.Id)"}

So there you have it – a quick and dirty howto on assigning an Azure AD role to a user. Notice that this does not use the PIM API, and I may write another post about how to do that.

3 thoughts on “Creating a user and assigning it to an Azure AD role using Microsoft.Graph PS Module

    1. It seems you actually need to use Invoke-MgGraphRequest for this currently, as there is no Remove-command apparently. Using Invoke-MgGraphRequest, you can invoke a DELETE towards something like$ref, where the first guid is the ID of youir role and the last guid is the ID of your principal (user or service principal)

      1. This helps a lot! I did not know that command and I think it might just be easier to use that one for so many requests.

Leave a Reply

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

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

Twitter picture

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

Facebook photo

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

Connecting to %s