Send Azure AD Guest User Invitations via Graph API

The built in controls in Azure AD for Guest User invitations are great for most cases. You can lock down guest invitations to specific users or groups and even specific recipient domains. When we look at more highly secure tenancies however, we often see requirements for approval flows or custom workflows to be associated with Guest User invitations.

This isn’t something available in the native GUIs but, as usual, that doesn’t mean it’s not possible! This entire process can be automated and built into a simple Graph API call. We can then expand out what we build into a Logic App/Power Automate flow. Using the different Microsoft technologies, the entire process can be customized to an endless degree. Even non-Microsoft technologies such as Service Management tools can kick off the process and integrate nicely into Azure Automation etc.

To help people (including myself on several projects) to build out their custom processes around guest user invitations, I’ve built the below PowerShell function to provision a guest user invitation via Graph API

In this post, we’ll walk through setting up the environment for the function and how to run it.

Setting up an app registration

The first thing we need for our Graph call is an application registration. This can be set up in Azure AD and assigned the permissions as below:

Configure the new app registration with a name. A redirect URL of http://localhost can be set as we don’t need redirect.

Under API Permissions, add and grant User.Invite.All, User.ReadWrite.All and Directory.ReadWrite.All permissions. Depending on how you are connecting this can be delegated or application permissions but as I need to automate the calls, I’ve selected application permissions. Ensure to grant consent on the permissions after adding them

Finally, create a Client Secret and take note of it for use in the Graph Connection

Parameters Required

Before we can run the function, we need to collect some information. We need to gather the below information about our tenant:

  • The Client ID of the application registration we created above
  • The Tenant ID (Directory ID) from Azure AD
  • The Client Secret we noted when we created the application registration
  • A URL to redirect users to after completion, this isn’t mandatory and the default is https://myapps.microsoft.com

Once we have all this information, we can import the function by running:

import-module <Filepath to PS1 file>\graph-Send-GuestInvitation.ps1

Once imported, we can run our function with the below command:

SendGuestInvitation -UserEmail <Guest user email> -ClientSecret <Your Client Secret> -ClientID <Your Client ID> -TenantID <Your Tenant ID>

When the function is run, it will return an invitation object. This object contains the details of the invitation as well as the “inviteRedeemURL” which can be sent to the guest to redeem their invitation in a more custom, branded email from an offical corporate email address.

This function can be found on GitHub here

Note, this code is for illustration purposes and not fit for running in production. Please ensure you understand any code you are running in a production environment.

function GetGraphToken {
    # Azure AD OAuth Application Token for Graph API
    # Get OAuth token for a AAD Application (returned as $token)
    <#
    .SYNOPSIS
    This function gets and returns a Graph Token using the provided details
    

    .PARAMETER clientSecret
    -is the app registration client secret

    .PARAMETER clientID
    -is the app clientID

    .PARAMETER tenantID
    -is the directory ID of the tenancy
    
    #>
    Param(
        [parameter(Mandatory = $true)]
        [String]
        $ClientSecret,
        [parameter(Mandatory = $true)]
        [String]
        $ClientID,
        [parameter(Mandatory = $true)]
        [String]
        $TenantID

    )

    
    
    # Construct URI
    $uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
     
    # Construct Body
    $body = @{
        client_id     = $clientId
        scope         = "https://graph.microsoft.com/.default"
        client_secret = $clientSecret
        grant_type    = "client_credentials"
    }
     
    # Get OAuth 2.0 Token
    $tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing
     
    # Access Token
    $token = ($tokenRequest.Content | ConvertFrom-Json).access_token
    return $token
}

Function SendGuestInvitation {
    <#
    .SYNOPSIS
    This function gets Graph Token from the GetGraphToken Function and uses it to request a new guest user
    
    .PARAMETER UserEmail
    -UserEmail is the email address of the requested user
    
    .PARAMETER clientSecret
    -is the app registration client secret

    .PARAMETER clientID
    -is the app clientID

    .PARAMETER tenantID
    -is the directory ID of the tenancy
    
    .PARAMETER tenantID
    -A URL to redrect to after the invitation is redeemed
    #>
    Param(
        [parameter(Mandatory = $true)]
        [String]
        $UserEmail,
        [parameter(Mandatory = $true)]
        [String]
        $ClientSecret,
        [parameter(Mandatory = $true)]
        [String]
        $ClientID,
        [parameter(Mandatory = $true)]
        [String]
        $TenantID,
        [parameter(Mandatory = $false)]
        [String]
        $RedirectURL = "https://myapps.microsoft.com"

    )

    $token = GetGraphToken -ClientSecret $ClientSecret -ClientID $ClientID -TenantID $TenantID

    $apiUri = 'https://graph.microsoft.com/beta/invitations/'
    $body = "{'invitedUserEmailAddress': '$UserEmail','inviteRedirectUrl': '$RedirectURL'}"
    
    $invitation = (Invoke-RestMethod -Headers @{Authorization = "Bearer $($token)" } -Uri $apiUri -Method Post -ContentType 'application/json' -Body $body)

    Return $invitation
}

2 thoughts on “Send Azure AD Guest User Invitations via Graph API

  1. Pingback: Script to Quickly Document your Conditional Access Policies – Sean McAvinue

  2. Pingback: Get Teams Notifications for Office 365 Service Health Issues – Sean McAvinue

Leave a comment