How To Add Azure AD Roles Using PowerShell With PIM

If you recall a while back we published an article to Get PIM Role Assignment Status For Azure AD Using Powershell, and today we’re going to build on top of that to add Azure AD Roles Using PowerShell

The goal here is to eliminate adding people using the Azure portal and use a method that’s more scalable and automatable. Because who doesn’t love automation right? The script I’m going to share with you today leverages the concept of just in time access using Azure AD Privilege Identity Management (PIM).

Note: PIM requires an Azure AD P2 License in your Tenant which is required for this to work.


In order for the script to run successfully you will need to have the following in place.

  • Azure AD P2 License for PIM Use
  • Privileged Role Administrator -or Global Administrator to grant permissions
  • AzureADPreview Powershell Module

Powershell 5+ would be preferred and I want to emphasize the AzureAdPreview Module (not AzureAD) as this has the commands we’re looking for.


Script Parameters


Specify the UserPrincipalName for the user you want to add roles for.


Specify the RoleName you want to add. Tab-Completion is enabled to ensure roles are accurate.


By default it will use the TenantId from your current session. If you’re connected to a multi-tenant, you can specify the tenant here.


Set how long you would like to add the role for. Default is 48 months (4 years)


Add a ticket number if needed for auditing purposes. “Justification” can also be used in lieu of “TicketNumber”


Add Azure AD Roles Using PowerShell With PIM Eligible Assignment

Now that we know what’s needed, let’s move on to the actual script.

Function Add-PIMRoleAssignment {
    This add a user to a PIM Role in Azure AD.
    For updated help and examples refer to -Online version.

    Name: Add-PIMRoleAssignment
    Author: theSysadminChannel
    Version: 1.0
    DateCreated: 2021-Sep-13

            Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            Position  = 0
        [string[]]  $UserPrincipalName,

            Mandatory = $true,
            Position  = 1
            'Application Administrator',
            'Application Developer',
            'Attack Simulation Administrator',
            'Authentication Administrator',
            'Azure Information Protection Administrator',
            'Billing Administrator',
            'Cloud Device Administrator',
            'Compliance Administrator',
            'Conditional Access Administrator',
            'Device Managers',
            'Directory Readers',
            'Directory Writers',
            'Exchange Administrator',
            'Exchange Recipient Administrator',
            'Global Administrator',
            'Global Reader',
            'Helpdesk Administrator',
            'Intune Administrator',
            'License Administrator',
            'Message Center Privacy Reader',
            'Message Center Reader',
            'Power BI Administrator',
            'Power Platform Administrator',
            'Privileged Authentication Administrator',
            'Privileged Role Administrator',
            'Reports Reader',
            'Search Administrator',
            'Security Administrator',
            'Security Reader',
            'Service Support Administrator',
            'SharePoint Administrator',
            'Skype for Business Administrator',
            'Teams Administrator',
            'Teams Communications Administrator',
            'Teams Communications Support Engineer',
            'Teams Communications Support Specialist',
            'User Administrator'
        [string]    $RoleName,

            Mandatory = $false,
            Position  = 2
        [string]    $TenantId,

            Mandatory = $false,
            Position  = 3
        [int]   $DurationInMonths = 48,

            Mandatory = $false,
            Position  = 4
        [string]   $TicketNumber


    BEGIN {
        $SessionInfo = Get-AzureADCurrentSessionInfo -ErrorAction Stop
        if (-not ($PSBoundParameters.ContainsKey('TenantId'))) {
            $TenantId = $SessionInfo.TenantId

        $AdminRoles = Get-AzureADMSPrivilegedRoleDefinition -ProviderId aadRoles -ResourceId $TenantId -ErrorAction Stop | select Id, DisplayName
        $RoleId = @{}
        $AdminRoles | ForEach-Object {$RoleId.Add($_.DisplayName, $_.Id)}

        $Schedule = New-Object Microsoft.Open.MSGraph.Model.AzureADMSPrivilegedSchedule
        $Schedule.Type = "Once"
        $Schedule.StartDateTime = (Get-Date)
        $Schedule.EndDateTime = (Get-Date).AddMonths($DurationInMonths)

        foreach ($User in $UserPrincipalName) {
            try {
                $AzureADUser = Get-AzureADUser -ObjectId $User -ErrorAction Stop | select-object UserPrincipalName, ObjectId
                Open-AzureADMSPrivilegedRoleAssignmentRequest -ProviderId Aadroles -Schedule $Schedule -ResourceId $TenantId -RoleDefinitionId $RoleId[$RoleName] `
                    -SubjectId $AzureADUser.ObjectId -AssignmentState Eligible -Type AdminAdd -Reason $TicketNumber -ErrorAction Stop | Out-Null

                    UserPrincipalName = $AzureADUser.UserPrincipalName
                    RoleName          = $RoleName
                    DurationInMonths  = $DurationInMonths
                    Justification     = $TicketNumber

            } catch {
                Write-Error $_.Exception.Message

    END {}


Add Azure AD Roles Using PowerShell and PIM-Update

Now when I look at the Azure AD Roles for the role name I just granted, we can see that Buzz now has an eligible role for Reports Reader. This confirms that everything worked as expected.
Reports Reader Pim Role


So there you have it, we’re able to add Azure AD Roles Using PowerShell to ensure Just in time access with Privilege Identity Manegment (PIM). Hopefully this was informative and you’re able to use it in your environment.

If you’re interested in more Powershell scripts, be sure to check out our personal Powershell Gallery full of real world, useful scripts just like this one.

5/5 - (19 votes)

Paul Contreras

Hi, my name is Paul and I am a Sysadmin who enjoys working on various technologies from Microsoft, VMWare, Cisco and many others. Join me as I document my trials and tribulations of the daily grind of System Administration.


  1. To permanently assign a role, leave off the duration when calling the Function:
    Add-PIMRoleAssignment -UserPrincipalName ‘[email protected]’ -RoleName ‘SharePoint Administrator’ -Justification ‘TicketNumber’

    and amend the end date to be:
    $Schedule.EndDateTime = $null

    This worked for me.

  2. This script is very useful for me, many thanks for sharing.

    I’ve tried to adapt for my usage but wasn’t quite successfully. how we can set the duration to be permanently eligible ?

Leave a Reply

Your email address will not be published.