Using Azure Automation to Invite Entra ID B2B Users

In a previous article about using Entra ID B2B users, I needed to set up some user extensions. In that article, I also mentioned that many customers needed to access the environment, which meant that multiple users needed to be changed.
As this is an ongoing business and we like to automate these kinds of tasks, I looked for an automation option. Creating a script wasn’t the problem, but using it to connect to Entra ID by entering credentials every time or putting them into the script was the hard part of the search.

After some time, I stumbled upon Azure Automation, where you can create runbooks (scripts) and add them to a scheduled task.

What’s Azure automation

Azure Automation is a cloud-based service provided by Microsoft Azure that enables users to automate various manual, time-consuming, and repetitive tasks across Azure and on-premises environments. It offers tools for process automation, configuration management, and update management. Using PowerShell or Python to automate complex tasks, users can create, schedule, and manage runbooks (workflow scripts). Azure Automation also provides Desired State Configuration (DSC) to define and enforce system configurations. Additionally, it integrates with other Azure services, allowing users to orchestrate end-to-end workflows for efficient and consistent management of resources in the Azure cloud.

Creating an Azure Automation account

We must create an Azure Automation account before using Azure Automation and deploying our script. Sign in to the Azure portal and search for Azure Automation. Click on “Create” and follow the wizard, here, you will see the output of “Review + Create.”

Powershell Modules

When using Azure Automation, verifying the availability of the intended PowerShell modules is crucial. For this situation, the following modules are essential:

  • Microsoft.Graph.Authentication:
    Responsible for establishing connections (Connect-MgGraph) and severing connections (Disconnect-MgGraph) to MgGraph.
  • Microsoft.Graph.Groups:
    Required for retrieving group members (Get-MgGroupMember) and obtaining information based on a group ID (Get-MgGroup).
  • Microsoft.Graph.Identity.SignIns:
    Necessary for initiating invitations (New-MgInvitation) through identity sign-ins.
  • Microsoft.Graph.Users:
    Utilized for fetching user information (Get-MgUser) and facilitating user updates (Update-MgUser).

To add the modules to the Azure Automation account, open the account and go to “Modules,” then follow the below steps to add the module. Repeat these steps until all required modules are added:

  1. Click on “Add a Module”
  2. Select “Browse from gallery”
  3. Click on “Click here to browse from gallery”
    • Search the module and select
    • click on “Select” at the bottom of the page.
  4. Now set the “Runtime Version”. In our case, it’s 5.1.
  5. Click “Import”

To verify if all of the required Powershell modules are available or still being imported, click on “Modules” within the Azure Automation account.

After adding the appropriate Powershell modules, we need to add the required permissions.


To get our script working with the appropriate permissions, we need the following permissions:

  • User.ReadWrite.All
  • User.Invite.All
  • Directory.Read.All

As we use a Managed Identity, we need to add the permissions using Graph Explorer. First, we must connect to the Graph Explorer: and sign in using an account in the correct tenant. You can’t switch tenant/directory when using Graph Explorer.

Step 1: Finding the Service Principal

We first need to find the service principal for our managed identity (automation account). To do so, we need to perform the following query, where displayname equals our Managed Identity name, in our case, “CTX-DaaS”:


Write down the ID. We need this in step 4.

Step 2: Finding the Microsoft Graph Service principal ID

As the Microsoft Graph API always has the following AppId “00000003-0000-0000-c000-000000000000”, we can create a filter and only look for this AppId. We can use the following query to get the ID:

GET$filter=appId eq '00000003-0000-0000-c000-000000000000'

Write down the ID. We need this in steps 3 and 4.

Step 3: Finding the Application Roles (Permissions) id

Now, we need to get the App Role IDs, as these are always the same and well-documented by Microsoft. We can search for them on the following site:

  • User.ReadWrite.All: “741f803b-c850-494e-b5df-cde7c675a1ca”
  • User.Invite.All: “09850681-111b-4a89-9bed-3f2cae46d706”
  • Directory.Read.All”: “7ab1d382-f21e-4acd-a863-ba3e13f7da61”

When you would like to use Graph Explorer, this is also possible, and you follow the below step: As we can’t add a filter to the query, we need to use the old-fashioned way and use CTRL+F to search for the appropriate IDs. First, we need to run the below query, replacing the {ServicePrincipalID} with the ID we found in step 2.


After running the query, we get a list of all the Application Roles. Luckily, the output only shows 100 results. Now, use CTRL+F to search for the permissions mentioned above and write down the IDs.

Step 4: Assigning the Application Roles to the Managed Identity

To assign the Application Roles, we need the following IDs:

  1. PrincipalId (step 1)
  2. ResourceId (step 2)
  3. AppRoleIId (step 3)

To add the Application Roles to the Managed Identity, we need to use a POST query in combination with a Content-Type application/json in the header and the following request body:


Content-Type: application/json

"principalId": "{your-managed-identity-service-principal-id}",
"resourceId": "{your-graph-serviceprincipal-id}",
"appRoleId": "{your-app-role-id}"

Repeat step 4 until you assigned all the Application Roles.

Step 5: Verifying the permissions in Entra ID

Now that we have set the Application Roles (Permissions), we can verify this within the Entra ID portal. To do so, we go to Entra ID, Enterprise Applications, then set the Application Type to “Managed Identities”.

Now, we select the Managed Identity we create to perform the Azure Automation tasks and go to Permissions. Here, we will see the permissions we just assigned.

Creating the runbook

Now that we have set all the appropriate permissions, we can start creating the runbook. For this case, we will look for users who are members of a certain security group called “CTX-DaaS-B2B” and verify if the Extension (Created in the previous blog) and CreationType are equal to Invitation. We will check this for each user who’s a member of the security group and check each setting, and if needed, we will apply changes.

Below, you can see the script we are using to automate the process of invitations and setting the extensions so the user can sign in to the Citrix Environment, which is mentioned in the previous blog.

Connect-MgGraph -Identity -NoWelcome
$Group = "CTX-DaaS-B2B"
$group = Get-MgGroup -Filter "DisplayName eq '$Group'"
$members = Get-MgGroupMember -GroupId $group.Id
$ExtensionUPN = "extension_c8ef4d2cb6694d76974c5a05be13affa_guestShadowUPN"
$ExtensionSID = "extension_c8ef4d2cb6694d76974c5a05be13affa_guestUserOnPremSID"
$CreationType = "Invitation" 
$RedirectURL = ""
$UserMessage = "You have been invited to the Citrix New Yard environment. `
                Redeem this invitation to get started and you’ll be redirected to the Citrix New Yard"

foreach ($member in $members) {
    $user = Get-MgUser -UserId $member.Id -Property ID, DisplayName, Mail, UserPrincipalName, UserType, CreationType, ExternalUserState, OnPremisesSecurityIdentifier

    if ($user.UserType -ne "Guest"){
        Write-output "User $($user.displayname) is Member, changing to Guest!"
        Update-MgUser -UserId $user.Id -UserType "Guest"

    $UserExtensions = (Get-mguser -UserID $user.Id -Property $ExtensionUPN).AdditionalProperties
    if ($UserExtensions.keys -NotContains $ExtensionUPN) {
        Write-Output "User $($user.displayname) has nu Extension, updating UPN and SID Extensions"
        Update-mguser -UserId $ -AdditionalProperties @{$ExtensionUPN = $user.UserPrincipalName}
        Update-mguser -UserId $ -AdditionalProperties @{$ExtensionSID = $user.OnPremisesSecurityIdentifier}

    Write-output "$($user.displayname) has CreationType $($user.creationType)"
    if ($user.CreationType -ne $CreationType) {
        Write-output "User $($user.displayname) isn't invited, inviting user!"
        New-MgInvitation -InvitedUser $user -InvitedUserEmailAddress $user.Mail -InviteRedirectUrl $RedirectURL -SendInvitationMessage:$true -InvitedUserMessageInfo:@{CustomizedMessageBody=$UserMessage}



We published the runbook to production once we tested it (using the test pane in the PowerShell runbook) and verified everything was correct. This can be done using the Publish button inside the PowerShell runbook.

Create a Schedule

Now that we have the runbook published, we can start with scheduling the runbook. As we start migrating users to the new environment, we have set the schedule to run every hour. When the migration is done, we can change the schedule to once a day, as we normally don’t make that many changes or create multiple users a day.

Let’s start with creating the schedule. We go to the Schedules from the Automation account and add a schedule.

Once the schedule is created, we need to assign the runbook to the schedule. Therefore, we go to the runbook, click on the “Link to schedule” button, click on the link to a schedule in your runbook, select the correct schedule, and click OK. To verify if the runbook is successfully linked to the schedule, click “Schedules” within the runbook and verify that the correct schedule is linked.

Verify the Azure Automation Task

Now that we successfully have followed all the steps:

  1. Creating Azure Automation Account
  2. Add PowerShell Modules
  3. Set permissions
  4. Create the runbook
  5. Create and linked a Schedule

We can now see in the overview of the Azure Automation account if the runs are completed successfully. As you can see in the screenshot below, the job has run once and was successful. The users will receive an invite every hour unless they already received one.


We can conclude that Azure Automation is a powerful tool for automating repetitive tasks, such as sending invites to new guests. I couldn’t achieve this without the guidance of GoToGuy’s blog, where the Graph Explorer is explained to configure all the necessary permissions. I will undoubtedly utilize Azure Automation more frequently now that I know its capabilities.

Using Entra ID B2B with Citrix Cloud

In a recent project, I designed an environment for a client who offers a published application to a substantial customer base. They expressed their desire to incorporate the use of Entra ID. I recommended the adoption of Entra ID B2B accounts for this purpose. Entra ID B2B accounts enable access to external partners for applications and resources within the organizational environment.

About Entra ID B2B

Entra ID B2B, short for Business-to-Business, is a Microsoft cloud service that facilitates secure collaboration among organizations. It permits organizations to extend invitations to external entities, such as partners, suppliers, or customers, granting them access to resources hosted within their Entra ID environment (formerly Azure AD). This approach eliminates the necessity for external users to establish new accounts, streamlining the collaborative process. Entra ID B2B bolsters security by implementing conditional access policies and multi-factor authentication for guest users, ensuring that only authorized individuals can access shared resources. Read here for more about Entra ID B2B.

Issues during implementation

While implementing this solution within the Citrix Cloud using the default Entra ID connect option, I encountered issues during the sign-in process with B2B accounts. After asking around, Julian Jakob directed me to an article highlighting an issue related to the default Entra ID connection in conjunction with Citrix FAS (Federated Authentication Service).

Upon reaching out to Citrix for support, it was revealed that there had been a modification to their SAML 2.0 configuration. This change now offers the option to utilize UPN (User Principal Name) or SID (Security Identifier) for authentication, whereas both were previously required. Please refer to the screenshot below for visual reference to this configuration option.

Based on the information provided, we successfully implemented Entra ID B2B accounts. However, this implementation necessitated certain modifications to our On-Premises Active Directory. Specifically, to grant B2B access to individual users, updating their User Principal Name (UPN) to align with their respective email addresses was imperative. While this approach was effective, it may not be ideal, especially considering the potential complexities of managing multiple DNS suffixes within the environment. As such, I dedicated some time to exploring alternative solutions that would obviate the need for such changes within the Active Directory.

Earlier in the project, I had come across an article from Citrix that introduced the concept of a ClaimsMappingPolicy. This approach leverages Azure AD Preview modules and a SAML Tech preview. It is worth noting that I refrained from testing this solution previously due to its preview status. Please refer to the provided article link for detailed information on this alternative approach.

Configuring the Entra ID as IdP

To initiate the configuration of Entra ID as the Identity Provider (IdP), the following key steps must be taken:

  1. Enterprise Application Setup: The first step involves the configuration of the Enterprise Application within the designated environment.
  2. Microsoft Graph Integration: Integrating with Microsoft Graph services is essential to facilitate the required functionalities.
  3. Claims Policy Mapping: Mapping of claims policies is necessary to define and manage the assertion of identity attributes.
  4. SAML 2.0 Connection in Citrix Cloud: Establishing a SAML 2.0 connection within the Citrix Cloud infrastructure enables secure authentication and authorization processes.

Enterprise Application Setup

To initiate the setup and configuration of a custom Entra ID Enterprise SAML application, please follow the provided steps. I have followed the guide created by Citrix, which can be accessed.

  1. Azure Portal Sign-In:
    • Sign in to the Azure portal.
  2. Navigate to Entra ID:
    • In the portal menu, select “Entra ID.
  3. Access Enterprise Applications:
    • From the left pane, under “Manage,” select “Enterprise Applications.”
  4. Create New Application:
    • In the working pane’s command bar, select “New Application.”
  5. Choose Custom Application:
    • Select “Create your own application” from the command bar. Avoid using the Citrix Cloud SAML SSO enterprise application template, as it restricts modifications to the list of claims and SAML attributes.
  6. Application Name and Integration:
    • Enter a name for the application.
    • Select “Integrate any other application you don’t find in the gallery (Non-gallery).”
    • Click “Create.” This action will lead you to the application overview page.
  7. Configure Single Sign-On (SSO):
    • From the left pane, select “Single sign-on.”
    • In the working pane, choose “SAML.”
  8. Basic SAML Configuration:
  9. User and Group Assignment:
    • From the left pane, select “Users and Groups.”
      • In the top bar, select “Add user/group.”
      • Under “Users,” select “None Selected.”
      • Choose the user you wish to test with, and click “Select.”
    • Click “Assign.” This action allows the designated user to be used for testing purposes.

These steps will enable creating and configuring a custom Entra ID Enterprise SAML application for your specific requirements.

Microsoft Graph Integration

The Citrix article I came across relies on Azure AD PowerShell modules, which have been planned for deprecation. To conduct effective testing, I needed to use something that was officially supported to ensure reliable functionality. Consequently, I embarked on a transition journey, migrating all the Azure AD commands to Microsoft Graph. Fortunately, I stumbled upon an informative article outlining the Microsoft Graph commands, which are direct replacements for the deprecated Azure AD Commands. This migration strategy aligns with industry best practices and guarantees continued operational effectiveness by leveraging the Microsoft Graph framework while circumventing the challenges posed by deprecated Azure AD PowerShell modules.


After migrating all Azure AD commands to Microsoft Graph, I comprehensively understood the requisite modules. Below, you’ll find an enumeration of all the essential commands, complete with their corresponding modules and the associated permissions indispensable for their execution:


To initiate work with Microsoft Graph, the first step involved the installation of the necessary modules. To achieve this, an Elevated PowerShell session needs to be opened, and the following commands need to be executed:

Install-Module Microsoft.Graph.Users
Install-Module Microsoft.Graph.Identity.SignIns
Install-Module Microsoft.Graph.Applications

You can append- force to each command if you prefer to streamline the installation process without individual prompts.


When establishing a connection to Microsoft Graph, it is essential to define the scope, which dictates the permissions granted for that session. As illustrated in the table above, a comprehensive set of permissions is required, which can be summarized as follows:

  • Policy.Read.All
  • Application.ReadWrite.All
  • Policy.ReadWrite.ApplicationConfiguration
  • User.ReadWrite.All

With these permissions delineated, we can proceed to connect to Microsoft Graph. To initiate this process, follow these steps:

  1. Open an Elevated PowerShell window.
  2. Connect to Microsoft Graph using the following command:
Connect-MgGraph -Scopes Policy.Read.All, Application.ReadWrite.All,Policy.ReadWrite.ApplicationConfiguration, User.ReadWrite.All
  1. A popup window will appear upon executing the command, prompting you to authenticate and grant Microsoft Graph the specified permissions, as detailed in the command above.
Microsoft Graph Permissions

This authentication step ensures the session has the necessary privileges to interact with Microsoft Graph effectively.

Configuring Claims Policy Mapping

Now that we are ready to configure the necessary settings for the Claims Mapping Policy, we continue from the PowerShell window we previously used to connect to Microsoft Graph.

Claims Mapping Policies are used in identity management to map and transform attributes (claims) exchanged between identity providers and service providers during authentication. They enable customization of how user attributes are processed, ensuring proper handling and alignment of user data between systems for secure access control.

Preparing the Application

To utilize the Claims Mapping Policy for Entra ID B2B users, where the User Principal Name (UPN) and Security Identifier (SID) do not align with the On-Premises Active Directory, we need to edit Entra ID with specific Extensions and bind them to the application. In this context, we will require the name of the previously created application, which, for this demonstration, is referred to as “CTX-DaaS-B2B.”

  1. Retrieve the application using the following command:
$MGApp = Get-MgApplication -Filter "displayname eq 'CTX-DaaS-B2B' "
  1. Next, we need to add the Extensions, both of which are set to target User objects:
    • guestUserOnPremSID
    • guestShadowUPN
New-MgApplicationExtensionProperty -ApplicationId $ -Name "guestUserOnPremSID" -TargetObjects User
New-MgApplicationExtensionProperty -ApplicationId $ -Name "guestShadowUPN" -TargetObjects User
  1. Note down the names of these Extensions by executing the following command:
Get-MgApplicationExtensionProperty -ApplicationId $mgapp.Id | fl *
Get the extension IDs for the use with the JSON code
  1. Add the Claims Mapping Policy by providing the policy in JSON format. Before doing so, replace the ExtensionIDs with the Extension names obtained in step 3. Take note of the following names:
    • Variable = $params
    • displayName = “CitrixCustomClaims
$params = @{
	definition = @(
            "ClaimsSchema": [
                "name": "displayName",
                "name": "givenName",
                "name": "cip_upn",
                "AppliesToUserType": "members"
                "name": "cip_upn",
                "SamlClaimType": "cip_upn",
                "AppliesToUserType": "allGuests"
                "name": "cip_oid",
                "name": "cip_email",
                "name": "cip_sid",
                "AppliesToUserType": "members"
                "name": "cip_sid",
                "SamlClaimType": "cip_sid",
                "AppliesToUserType": "allGuests"
	displayName = "CitrixCustomClaims"

This process ensures the application has the necessary Extensions and Claims Mapping Policy to handle Entra ID B2B user scenarios where UPNs and SIDs do not correspond to the On-Premises Active Directory.

  1. Obtain the Service Principal
    Proceed by retrieving the Service Principal with the following command, where Displayname is the name of the app, in this case CTX-DaaS-B2B:
$ServicePrincipal = Get-MgServicePrincipal -Filter "Displayname eq 'CTX-DaaS-B2B' "
  1. Create the Claims Mapping Policy
    Now, create the Claims Mapping Policy, utilizing the $Params variable, which represents the variable name assigned to the Policy when pasting the JSON code. Execute the following command to establish the policy:
New-MgPolicyClaimMappingPolicy -BodyParameter $params
  1. Map the Claims Policy to the Service Principal
    A Graph body parameter must be created using the OData protocol to map the Claims policy to the Service Principal. Follow these steps:
    • Execute the command below, replacing “CitrixCustomClaims” with the name you assigned to your Claims Policy (found in the JSON command. In this case, it’s “CitrixCustomClaims“):
Get-MgPolicyClaimMappingPolicy -Filter "Displayname eq 'CitrixCustomClaims'"| select DisplayName,Description, Id
  • Retrieve the ID and modify the following URL, replacing the ID at the end with the one obtained in the previous step:
    •<ID from previous step>
  • Create a variable in PowerShell with the modified URL, like so:
$odata = @{
	"" = ""
  • Finally, link the Odata to the Service Principal using the following command:
New-MgServicePrincipalClaimMappingPolicyByRef -ServicePrincipalId $ -BodyParameter $odata

These steps facilitate the establishment of the Claims Mapping Policy and its connection to the Service Principal, ensuring proper configuration for your desired scenario.

Configuring the User

To configure the test user, follow the steps outlined below:

  1. Retrieve Current UPN and SID:
    Execute the following command to obtain the current User Principal Name (UPN) and Security Identifier (SID). Replace “[email protected]” with the Entra ID UPN you are configuring (for this test, it’s “[email protected]“):
User Entra ID overview to get the User Principal Name (UPN).
$user = get-mguser -UserId -Property Id,DisplayName,UserPrincipalName, OnPremisesSecurityIdentifier
  1. Update User Extensions:
    Now, proceed to update the user’s Extension with the appropriate values. Replace the Extension name with the one you acquired earlier and execute the following commands:
  • Update User’s On-Premises Security Identifier (SID):
Update-mguser -UserId $ -AdditionalProperties @{'extension_dcf32e98a0de4910ba50bd486eef0335_guestUserOnPremSID' = $user.OnPremisesSecurityIdentifier}
  • Update User’s Shadow User Principal Name (UPN):
Update-mguser -UserId $ -AdditionalProperties @{'extension_dcf32e98a0de4910ba50bd486eef0335_guestShadowUPN' = $user.UserPrincipalName}

These steps ensure the test user’s proper configuration, including updating relevant Extensions with the required values, effectively facilitating the Entra ID B2B user scenario.

Configuring the SAML 2.0 Connection in Citrix Cloud

With Entra ID prepared, let’s proceed to configure Citrix Cloud. To initiate this process, follow these steps:

  1. Sign in to the Citrix Cloud administration console and navigate to the Single Sign-On settings of the previously created Enterprise App.
Create SAML 2.0 connection
  1. Access the Citrix Cloud Console, and under “Identity and Access Management,” click on “Connect” within the SAML 2.0 option.
  2. Create a Custom Administrator URL.
Citrix Cloud Custom Administrator URL
  1. In the SAML configuration, populate the following settings using the Single Sign-On URLs obtained from Entra ID within the Enterprise App:
    • Identity Provider Entity ID = Microsoft Entra ID Identifier.
    • SSO Service URL = Login URL.
    • Logout URL (optional) = Logout URL.
    • Refer to the screenshot below for reference. On the “Set up single sign-on with SAML” page, in the SAML Signing Certificate section, locate “Certificate (PEM)” and select “Download” to save the certificate to your computer. Upload this certificate to the X.509 section of the SAML configuration within Citrix Cloud.
    • Proceed by clicking “Test and Finish.”
  1. Now that SAML 2.0 has been configured, it is necessary to update the Workspace Configuration to employ the newly created authentication method:
    • Within the Citrix Cloud Administration Console, navigate to “Workspace Configuration.”
    • Proceed to the “Authentication” tab.
    • Select “SAML 2.0” and confirm your selection by clicking “OK” in the pop-up dialog.
      Allow a brief moment (approximately 1 minute) before proceeding, as immediate functionality may not always be observed.
Citrix Cloud SAML 2.0 config to Entra ID.

By following these steps, you configure the SAML 2.0 connection in Citrix Cloud, enabling seamless integration with Entra ID for authentication and access management.


Now that we have configured all required settings, we can start with the test.

  1. Visit the Workspace URL and sign in using the test user employed previously:
    1. After launching the desktop, open a command prompt or PowerShell and run the “whoami” command. You will observe that the sign-in is performed using the local Active Directory (AD) account.
Show the ouput of Whoami to see which user is signed in.


After an extensive search and engagement with Citrix support, a functional Entra ID B2B scenario has been successfully resolved. While the initial solution relied on outdated information, it has been updated with current PowerShell commands, resulting in a functional setup. Consequently, organizations can seamlessly integrate Entra ID B2B and regular Entra ID users into their Citrix Cloud deployments, enhancing their access and identity management capabilities.

Please feel free to comment or ask questions regarding this solution. I am working on another article to guide you on using Azure Automation to update all B2B users with the new extension. So, stay tuned.
UPDATE: As mentioned earlier, I would create a blog post about using Azure Automation to automate this. You can read it here.