User synchronization with Azure AD/Active Directory

This article is available in video format as well as a written article containing more details.
Note: due to changes in the PowerShell module, parts of the video are outdated. The video can still be used for reference. The code in this article is up to date.

The Azure AD / Active Directory synchronization is capable of automatically creating, updating, and disabling users from Azure AD or Active Directory.

We have created the ‘BrightBookingUserAdminTools’ PowerShell module, which handles this logic. By creating a (planned) task with the right PowerShell commands, you can push this information regularly to GoBright from your server.

Note: GoBright only receives data through this BrightBookingUserAdminTools. GoBright does not have permissions to send data back to your Azure AD / Active Directory.

GoBright as an Enterprise Application in Azure AD

Before continuing the section below we’d like to address that you can setup GoBright as an enterprise application within Azure AD. This will allow you to create/update users to the platform automatically and enable SSO easily. We highly recommend following the steps in the article below before continuing: GoBright as an Enterprise Application (Azure AD)

Introduction

The integration-logic is available as a PowerShell module, via PowerShellGallery, as ‘BrightBookingUserAdminTools‘.

The ‘BrightBookingUserAdminTools’ PowerShell module should be installed on a machine (server) in your domain.

When configured it follows the following steps, each time it runs:

  1. Get the users from Azure AD or Active Directory, filtered by your preferences, for example, filtered by group membership
  2. These users are sent to GoBright and immediately created or updated
  3. If the user is deactivated in Azure AD or Active Directory, it will also be deactivated in GoBright
  4. Users that are not read from the Azure AD or Active Directory are also no updated in GoBright

Follow the steps below to install and configure the integration!

Step 1

Install prerequisites

The BrightBookingUserAdminTools module has the following dependencies:

  • PowerShell version 5 or higher
  • The following PowerShell modules:
    • PowerShellGallery
    • ActiveDirectory
    • Azure AD
  • The machine (server) should be linked in your Windows domain

Please follow the next steps to install the dependencies:

  1. Log in to the machine (server) where you want to install the task. (this machine should be linked in the Windows domain).
  2. Start PowerShell on that machine, as ‘administator’:
    clip0001-279x300.jpg
  3. Check if PowerShell 5 is installed:
    • Execute the following command:
      $PSVersionTable.PSVersion
    • In the result you get, the ‘Major‘ should be ‘5‘ or higher.
    • If the ‘Major‘ is lower than ‘5‘, follow these steps:
      • Install Windows Management Framework 5 (this includes PowerShell 5):
        Download Windows Management Framework 5
      • Note 1: if you get the error ‘The update is not applicable to your computer’ you probably selected the wrong download, please refer to this article.
      • Note 2: Windows Management Framework 5 depends on .NET Framework 4.5.
      • Note 3: Reboot is probably required.
      • After installation please check if the ‘Major‘ is ‘5‘ or higher:
        $PSVersionTable.PSVersion
  4. PowerShell ExecutionPolicy(optional)
    • Set PowerShell ExecutionPolicy to Unrestricted
      • Set-ExecutionPolicy -ExecutionPolicy Unrestricted
  5. Install the PowerShellGallery PowerShell module:
    • Execute the following commands in PowerShell (running as administrator)
    • Install the NuGet PackageProvider:
      Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
    • Configure PowerShellGallery as a trusted source:
      Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
    • Install the PowerShellGet module:
      Import-Module -Name PowerShellGet
  6. If you want to synchronize with Active Directory: Install the ActiveDirectory PowerShell module:
  7. If you want to synchronize with Azure AD: Install the Microsoft.Graph PowerShell module:
    • Execute the following commands in PowerShell (running as administrator)
    • Note: .Net Framework 4.7.2 or higher is required, for more documentation see: https://learn.microsoft.com/en-us/powershell/microsoftgraph/installation?view=graph-powershell-1.0
    • Install the applicable Microsoft.Graph modules:
      Install-Module Microsoft.Graph.Applications -Force Install-Module Microsoft.Graph.Users -Force Install-Module Microsoft.Graph.Groups -Force Install-Module Microsoft.Graph.Identity.DirectoryManagement -Force

Step 2

Installation/Update of the synchronization module

Install or update the BrightBookingUserAdminTools PowerShell module:

Install-Module -Name BrightBookingUserAdminTools -Force

The ‘-Force‘ command makes sure that the latest version of the module is installed even when a previous installation exists. When the module was already installed, the PowerShell session will need to be restarted.

Step 3

Configuration: get the API URL and API key

To be able to synchronize the users, you need to get the following information in the GoBright Portal:

  • The API URL and API key
  • The name of the integration which should be linked to the users

Follow these steps to find the API URL and API key:

  • Log in with a manager account in the GoBright portal
  • Go to Admin center > Integrations > API access
  • Generate an API key via the ‘Add’-button. Choose as type ‘manager’ and enter a description for later reference
    • Note: please make sure you save the API key, as there is no way to recover it
  • The ‘API URL’ is your GoBright environment URL which can be found in the URL bar of your browser and under Admin center > Integrations > API access: API url https://[tenant-id].gobright.cloud/

Follow these steps to find the name of the integration:

  • Log in with a manager account in the GoBright portal
  • Go to Admin center > Integrations
  • Copy the name of the integration (Exchange/Office 365) which should be used to link the users to

The name of the integration, the API URL and API key are needed in the next steps.

Step 4

Configure the synchronization PowerShell script

In the last step you will build the actual script to tell the GoBright PowerShell module which users you want to get and push to your GoBright environment. This can be done with Azure AD or Active Directory.

The GoBright platform enforces communication using TLS 1.2. Depending on the system you use this might nog happen automatically. See the code below and implement this in every PowerShell script that communicates with GoBright.

Also add the $ErrorActionPreference to make sure it stops the script whenever an error occurs. Please don’t forget to add the lines below in each of your scripts.

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
$ErrorActionPreference = "Stop"

Choose one of the explanations for the script which applies to your situation below.

Script for Azure AD synchronization using the Microsoft.Graph module

Step 4.1: Connect to your Azure AD

Start PowerShell, and connect to your Azure AD via the command:

Connect-MgGraph -Scopes 'User.Read.All','Group.Read.All','GroupMember.Read.All'

Step 4.2: Test the selection of users

Below you can find several example commands, you can adjust them to fit your situation.

These commands will not yet actually update users in GoBright, because they include the ‘-WhatIf’ parameter.

Example synchronization commands:

Process users and add the user roles within GoBright based on their group membership in Azure AD:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $ErrorActionPreference = "Stop" Connect-MgGraph -Scopes 'User.Read.All','Group.Read.All','GroupMember.Read.All' $includedGroups = @()
$includedGroups += '[your AzureAD groupname_1 here]' $includedGroups += '[your AzureAD groupname_2 here]'

# get the list of userid's in the group $groups = Get-MgGroup -All | Where-Object { $includedGroups -contains $_.DisplayName } $users_in_groups_userids = @(); Foreach ($group in $groups) { $groupMembers = Get-MgGroupMember -All -GroupID $group.id Foreach ($groupMember in $groupMembers) { $users_in_groups_userids += $groupMember.Id } } # get the required details of those users $users_full_list = Get-MgUser -All -Select Id,DisplayName,Mail,UserPrincipalName,AccountEnabled,MobilePhone,AssignedLicenses $users = $users_full_list | Where-Object { $users_in_groups_userids -contains $_.Id } Write-Output "Loaded from AzureAD: $(($users | Measure-Object).Count) users" # define the mapping of groups to roles $groupToRoleMapping = @()
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for View

$groupToRoleMapping += @ # **special case** this line matches for every user, because of the 'MatchType', and is needed when you want to have a generic role for every user

$roleNameDefaultIfNoGroupMatched = "Regular user"


$users | Push-AzureADUsersToBB -DeactivateExistingUsersInSameIntegrationThatAreNotLoaded -UserDefaultRoleName $roleNameDefaultIfNoGroupMatched -GroupUserRoleMapping $groupToRoleMapping -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Available parameters for Push-AzureADUsersToBB

You can use the following parameters in the ‘Push-AzureADUsersToBB’ command:

ADUserSpecificUsername UserPrincipalName
(optional)

By default the user will authenticate with the primary e-mailaddress of the user to the Microsoft Exchange Server or Office365.

Provide this value to use a different way of authenticating of the user to the Microsoft Exchange Server or Office365:
UserPrincipalName to use the UPN

-ADUserPincodePropertyName
(optional)

Specify an fieldname of a field in Active Directory which you want to use as a ‘pincode’ (has to be numeric, minimum of 4 digits, and has to be unique).

-ADUserMobilePropertyName
(optional)

Specify an fieldname of a field in Active Directory which you want to use to get the mobile phonenumber of the users (e.g. for notification of the digital reception)
Will use the standard ‘Mobile’ field by default.

-ADUserNFCIdPropertyName
(optional)

Specify a fieldname of a field in Active Directory which you want to use to get the NFC Identifier for that user.
Please note that it should be in HEX format, eg: XX:XX:XX:XX:XX:XX .

-ADUserDefaultCostCenterId OrNamePropertyName
(optional)

Specify a fieldname of a field in Active Directory which you want to use to set the default cost center for that user. You can specify the name or id (‘guid’) of the costcenter, where the name is most commonly used.

-GroupUserRoleMapping

This parameter gives you the possibility to assign a role to a user in the platform, based on a group membership in the Azure AD.
You need to supply a hashtable (a key+value list), where the key is the full FQN of the group and the value is the rolename in the platform.

See the example below.

-UserRoleNameForNewUsers
(optional)

Optional name of an existing role in the portal to use when new users are created through this synchronization.

-DeactivateExistingUsersIn
SameIntegrationThatAreNotLoaded
(optional)

Optional switch to automatically deactivate users that are not in the selected users from ActiveDirectory anymore, but still existing in the portal.
Use this switch to automatically disable them.
Only users in the same integration are taken into account (see parameter: BrightBookingIntegrationName)

-IncludeUsersWithoutAzureAD
AssignedLicensesOrAssignedPlans

Include users that do not have Azure AD licenses assigned (would otherwise be included as inactive) or Azure AD plans assigned (would otherwise be fully excluded). Note that including these users might result in having unintended ‘users’ like serviceacounts, roommailbox users, etc. That can be mitigated by filtering the users before feeding them into this command.

-BrightBookingApiUrl
(required)
The API url, as found in step 3
-BrightBookingApiKey
(required)
The API url, as found in step 3
-BrightBookingIntegrationName
(required)
The API url, as found in step 3
-WhatIf
(optional)
Use the ‘-WhatIf’ parameter to only test and see, but not actually send data to your GoBright environment

Step 4.2: Run the actual synchronization

Once the list of users is correctly filtered, you can execute the real synchronization by removing the ‘-WhatIf’ parameter.

So now execute the same command, but without ‘-WhatIf’ and it will process the users to your GoBright environment.

Step 4.3: Schedule the integration to run periodically via Windows task scheduler

To be able to run the script unattended you should somehow login automatically.
The advised way to do use unattended login, this can be done via certificates, via app registration in Azure AD:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $ErrorActionPreference = "Stop"



#This script will create een enterprise app with a local certificate for unattended authorisation.
#Set the enterprise app name $AppName = "GoBright_UserSync_UnattendedLogin" $ErrorActionPreference = "Stop" #Connect with the graph to be able to create or update the application Connect-MgGraph -Scopes "Application.Read.All","Application.ReadWrite.All" #Get the tenantid $organization = Get-MgOrganization $APPTenantID = $organization.Id #Create or update the enterprise app $foundApps = Get-MgApplication | Where-Object {$_.DisplayName -eq $AppName} $foundAppsCount = $foundApps | Measure-Object if ($foundAppsCount.Count -eq 0) { # create the app $App = New-MgApplication -DisplayName $AppName $APPObjectID = $App.Id $APPClientID = $App.AppId } Else { $APPObjectID = $foundApps.Id $APPClientID = $foundApps.AppId } #Create a local self-signed certificate to use it as credential for the enterprise app $foundCerts = Get-ChildItem -Path cert:CurrentUsermy | Where-Object { $_.Subject -eq "CN=$($AppName)" } $foundCertsCount = $foundCerts | Measure-Object If ($foundCertsCount.Count -eq 0) { # create self-signed cert $thumb = (New-SelfSignedCertificate -CertStoreLocation Cert:CurrentUserMy -subject $AppName -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(20) -Type CodeSigningCert -KeySpec Signature).Thumbprint $foundCerts = Get-ChildItem -Path cert:CurrentUsermy$thumb $cert = $foundCerts[0] } Else { $cert = $foundCerts[0] } #Create a keyCredential from the certificate for the enterprise app $keyCreds = @{ Type = "AsymmetricX509Cert"; Usage = "Verify"; key = $cert.RawData } try { #Set credentials Update-MgApplication -ApplicationId $APPObjectID -KeyCredentials $keyCreds #Set permission scopes, needs to go via id, see: https://learn.microsoft.com/en-us/graph/permissions-reference #'User.Read.All' = df021288-bdef-4463-88db-98f22de89214 #'Group.Read.All' = 5b567255-7703-4780-807c-7be8301ae99b #'GroupMember.Read.All' = 98830695-27a2-44f7-8c18-0c3ebc9698f6 $params = @{ RequiredResourceAccess = @( @{ ResourceAppId = "00000003-0000-0000-c000-000000000000" ResourceAccess = @( @{ Id = "df021288-bdef-4463-88db-98f22de89214" Type = "Role" }, @{ Id = "5b567255-7703-4780-807c-7be8301ae99b" Type = "Role" }, @{ Id = "98830695-27a2-44f7-8c18-0c3ebc9698f6" Type = "Role" } ) } )} Update-MgApplication -ApplicationId $APPObjectID -BodyParameter $params } catch { Write-Error $Error[0] } #Output details and request the admin to check the consent
Write-Output "App registration '$($AppName)' is now available, please use following details in the user sync script:"
Write-Output " - ClientId: $($APPClientID)"
Write-Output " - TenantId: $($APPTenantID)"
Write-Output " - CertificateThumbprint: $($cert.Thumbprint)"
Write-Output "NOTE: Please give admin consent in the AzureAD portal to this app!"

Admin Consent in AzureAD

Please go to Azure portal and open the created enterprise application for unattendedlogin and select API permission > Grant admin consent for “Your Domain”

Now you can use the following way to automatically login to your Azure AD with the unattended login method and test your script via ‘-WhatIf’ before running the actual user sync script:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$ErrorActionPreference = "Stop"

$clientid = "[fill in your client from the output of the first script]" $tenantid = "[fill in your tenant id from the output of the first script]" $thumb = "[fill in your thumb id from the output of the first script]" Connect-MgGraph -ClientId $clientid -TenantId $tenantid -CertificateThumbprint $thumb
$includedGroups = @()
$includedGroups += '[your AzureAD groupname_1 here]' $includedGroups += '[your AzureAD groupname_2 here]'

# get the list of userid's in the group $groups = Get-MgGroup -All | Where-Object { $includedGroups -contains $_.DisplayName } $users_in_groups_userids = @(); Foreach ($group in $groups) { $groupMembers = Get-MgGroupMember -All -GroupID $group.id Foreach ($groupMember in $groupMembers) { $users_in_groups_userids += $groupMember.Id } } # get the required details of those users $users_full_list = Get-MgUser -All -Select Id,DisplayName,Mail,UserPrincipalName,AccountEnabled,MobilePhone,AssignedLicenses $users = $users_full_list | Where-Object { $users_in_groups_userids -contains $_.Id } Write-Output "Loaded from AzureAD: $(($users | Measure-Object).Count) users" # define the mapping of groups to roles $groupToRoleMapping = @()
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for View

$groupToRoleMapping += @ # **special case** this line matches for every user, because of the 'MatchType', and is needed when you want to have a generic role for every user

$roleNameDefaultIfNoGroupMatched = "Regular user"


$users | Push-AzureADUsersToBB -DeactivateExistingUsersInSameIntegrationThatAreNotLoaded -UserDefaultRoleName $roleNameDefaultIfNoGroupMatched -GroupUserRoleMapping $groupToRoleMapping -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Next, follow these steps to synchronize the users from Active Directory on a schedule:

  • Take the command you’ve composed (see previous steps), and save it in a .ps1 file:
    • Create a .ps1 file (e.g. UsersToBrightBooking.ps1) in a folder you prefer
    • Open the file with an editor, for example ‘notepad’
    • Paste the login script to automatically login to your Azure AD
    • Paste the full command into the file
    • Save the file
  • Execute the file to see if it is successful
  • Create a task in the Windows task scheduler:
    • Open Windows task scheduler
    • Create a task
    • Set a schedule, for example once a day, or every 4 hours
    • Add an action ‘Start a program’:
      • Program/script:
        Powershell.exe
      • Parameters:
        -windowstyle minimized -c “powershell -c .[Name of the created .ps1 file] -verbose >> ExportToGoBright_Output.txt 2>&1″
      • Start in:
        Fill the ‘start in’ with the location of the script, e.g.: C:scripts

Script

“]

Step 4.1: Connect to your Azure AD

Start PowerShell, and connect to your Azure AD via the standard ‘Connect-AzureAD’ command.

AzureAD powershell module is deprecated

Please note that the AzureAD powershell module is deprecated, please migrate to the Microsoft.Graph powershell module (see above in this article)

Step 4.2: Test the selection of users

The command to get the information from Active Directory and process it in BrightBooking is:

Get-AzureADUser -All $true [optional: filter] | Push-AzureADUsersToBB [optional: specific username/pincode field] -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]'

You can use the following parameters in the ‘Push-AzureADUsersToBB’ command:

ADUserSpecificUsername UserPrincipalName
(optional)

By default the user will authenticate with the primary e-mailaddress of the user to the Microsoft Exchange Server or Office365.

Provide this value to use a different way of authenticating of the user to the Microsoft Exchange Server or Office365:
UserPrincipalName to use the UPN

-ADUserPincodePropertyName
(optional)

Specify an fieldname of a field in Active Directory which you want to use as a ‘pincode’ (has to be numeric, minimum of 4 digits, and has to be unique).

-ADUserMobilePropertyName
(optional)

Specify an fieldname of a field in Active Directory which you want to use to get the mobile phonenumber of the users (e.g. for notification of the digital reception)
Will use the standard ‘Mobile’ field by default.

-ADUserNFCIdPropertyName
(optional)

Specify a fieldname of a field in Active Directory which you want to use to get the NFC Identifier for that user.
Please note that it should be in HEX format, eg: XX:XX:XX:XX:XX:XX .

-ADUserDefaultCostCenterId OrNamePropertyName
(optional)

Specify a fieldname of a field in Active Directory which you want to use to set the default cost center for that user. You can specify the name or id (‘guid’) of the costcenter, where the name is most commonly used.

-GroupUserRoleMapping

This parameter gives you the possibility to assign a role to a user in the platform, based on a group membership in the Azure AD.
You need to supply a hashtable (a key+value list), where the key is the full FQN of the group and the value is the rolename in the platform.

See the example below.

-UserRoleNameForNewUsers
(optional)

Optional name of an existing role in the portal to use when new users are created through this synchronization.

-DeactivateExistingUsersIn
SameIntegrationThatAreNotLoaded
(optional)

Optional switch to automatically deactivate users that are not in the selected users from ActiveDirectory anymore, but still existing in the portal.
Use this switch to automatically disable them.
Only users in the same integration are taken into account (see parameter: BrightBookingIntegrationName)

-IncludeUsersWithoutAzureAD
AssignedLicensesOrAssignedPlans

Include users that do not have Azure AD licenses assigned (would otherwise be included as inactive) or Azure AD plans assigned (would otherwise be fully excluded). Note that including these users might result in having unintended ‘users’ like serviceacounts, roommailbox users, etc. That can be mitigated by filtering the users before feeding them into this command.

-BrightBookingApiUrl
(required)
The API url, as found in step 3
-BrightBookingApiKey
(required)
The API url, as found in step 3
-BrightBookingIntegrationName
(required)
The API url, as found in step 3
-WhatIf
(optional)
Use the ‘-WhatIf’ parameter to only test and see, but not actually send data to your GoBright environment

Below you can find several example commands, you can adjust them the way you need to fit your situation.

These commands will not yet actually update users in the system, so these are test commands, because they include the ‘-WhatIf’ parameter.

Example test commands:

Process all users in the Azure AD to GoBright:

Get-AzureADUser -All $true | Push-AzureADUsersToBB -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users with UPN’s ending with ‘yourdomain.com’ to GoBright:

Get-AzureADUser -All $true | where {$_.userprincipalname -like "*yourdomain.com"} | Push-AzureADUsersToBB -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users with an NFC ID and Pincode in a custom attribute, note that the extension attribute name must be identical to the one in Azure AD:

$users_all_import = Get-AzureADUser -All $true [optional: filter]
$users_all = @()


$pincodeField = '[Extension attribute here]'


$NFCField = '[Extension attribute here]'


Foreach ($user in $users_all_import) {

$getExtensionProperty = $user | Select-Object -ExpandProperty ExtensionProperty

If ($getExtensionProperty.$pincodeField) {

$pin = (Get-AzureADUserExtension -ObjectId $user.ObjectId).get_item($pincodeField)

} Else {

$pin = ''

}


If ($getExtensionProperty.$NFCField) {

$nfc = (Get-AzureADUserExtension -ObjectId $user.ObjectId).get_item($NFCField)

} Else {

$nfc = ''

}


$user | Add-Member UserPincode $pin -Force

$user | Add-Member UserNFC $nfc -Force

$users_all += $user

}


$users_all | Push-AzureADUsersToBB -ADUserPincodePropertyName UserPincode -ADUserNFCIdPropertyName UserNFC -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users and add the user roles within GoBright based on their group membership in Azure AD:

$groupToRoleMapping = @()
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for Meet-Work-Visit
$groupToRoleMapping += @ # match specific users that belong to a group for View

$groupToRoleMapping += @ # **special case** this line matches for every user, because of the 'MatchType', and is needed when you want to have a generic role for every user

$roleNameDefaultIfNoGroupMatched = "Regular user"


$users_all = Get-AzureADUser -All $true
$users_all | Push-AzureADUsersToBB -UserDefaultRoleName $roleNameDefaultIfNoGroupMatched -GroupUserRoleMapping $groupToRoleMapping -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process all users except those who are a member of a specific group in Azure AD:

$excludedGroups = @()
$excludedGroups += '[GroupName1]'
$excludedGroups += '[GroupName2]'
$excludedGroups += '[GroupName3]'
$ADGroups = Get-AzureADGroup -All $true | Where-Object { $excludedGroups -notcontains $_.DisplayName }
$users_all = $ADGroups | Get-AzureADGroupMember -All $true
$users_all | Push-AzureADUsersToBB -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Step 4.2: Run the actual synchronization

Once the list of users is correctly filtered, you can execute the real synchronization by removing the ‘-WhatIf’ parameter.

So now execute the same command, but without ‘-WhatIf’ and it will process the users to your GoBright environment.

Step 4.3: Schedule the integration to run periodically via Windows task scheduler

To be able to run the script unattended you should somehow login automatically.

Advised unattended login method:
The advised way to do unattended login, is by creating an registered app in Azure AD, and connect to that app:

#script for creating user, cert, and get tenantid #getting data for daily script
Connect-AzureAD $pwd = "Password to encrypt the cert" $subject = "GoBright_unattendedlogin" # may not be longer than 15 characters = the name certificate and app $tmppath = "C:tmp" $certname= "unattendedlogin_azuread.pfx" $fullcertpath = "C:tmpunattendedlogin.pfx" $IdentifierUris = "https://www.fillInYourOwnDomain.com" # Here you need to fill in your own domain name
$thumb = (New-SelfSignedCertificate -CertStoreLocation Cert:CurrentUserMy -subject $subject -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(10) -Type CodeSigningCert -KeySpec Signature).Thumbprint $pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText if ($tmppath -eq $false) Export-PfxCertificate -cert "cert:CurrentUsermy$thumb" -FilePath $fullcertpath -Password $pwd
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate($fullcertpath, $pwd) $keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
$application = New-AzureADApplication -DisplayName $subject -IdentifierUris $IdentifierUris New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier $subject -Type AsymmetricX509Cert -Usage Verify -Value $keyValue $sp=New-AzureADServicePrincipal -AppId $application.AppId Add-AzureADDirectoryRoleMember -ObjectId (Get-AzureADDirectoryRole | where-object {$_.DisplayName -eq "Directory Readers"}).Objectid -RefObjectId $sp.ObjectId
$tenantid = Get-AzureADTenantDetail | Select ObjectId -ExpandProperty ObjectId $appid = $application.AppId $thumb $tenantid $appid
#copy data from thumb, tenantid, appid to daily user sync script

For more information please click on this link.

For testing purposes you could use the following way to automatically login to your Azure AD with the unattended login method and test your script before running the actual user sync script:

$tenantid = "[fill in your tenant id from the output of the first script]" $thumb = "[fill in your thumb id from the output of the first script]" $appid = "[fill in your appid from the output of the first script]"
Connect-AzureAD -TenantId $tenantid -ApplicationId $appid -CertificateThumbprint $thumb
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $ErrorActionPreference = "Stop"
$users_all = Get-AzureADUser -All $true | Where-Object {$_.userprincipalname -like "*someDomainname.com"} $users_all | Push-AzureADUsersToBB -UserDefaultRoleName $roleNameDefaultIfNoGroupMatched -GroupUserRoleMapping $groupToRoleMapping -DeactivateExistingUsersInSameIntegrationThatAreNotLoaded -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Note: when you get an error within PowerShell that there are insufficient rights to run the script, then you need to check the rights to add to the app. For more information please read the following Microsoft article ‘Step 5: Assign Azure AD roles to the application’: https://docs.microsoft.com/en-us/powershell/exchange/app-only-auth-powershell-v2?view=exchange-ps

Next, follow these steps to synchronize the users from Active Directory on a schedule:

  • Take the command you’ve composed (see previous steps), and save it in a .ps1 file:
    • Create a .ps1 file (e.g. UsersToBrightBooking.ps1) in a folder you prefer
    • Open the file with an editor, for example ‘notepad’
    • Paste the login script to automatically login to your Azure AD
    • Paste the full command into the file
    • Save the file
  • Execute the file to see if it is successful
  • Create a task in the Windows task scheduler:
    • Open Windows task scheduler
    • Create a task
    • Set a schedule, for example once a day, or every 4 hours
    • Add an action ‘Start a program’:
      • Program/script:
        Powershell.exe
      • Parameters:
        -windowstyle minimized -c “powershell -c .[Name of the created .ps1 file] -verbose >> ExportToGoBright_Output.txt 2>&1″
      • Start in:
        Fill the ‘start in’ with the location of the script, e.g.: C:scripts

Script for Active Directory synchronization

Step 4.1: Test the selection of users

The command to get the information from Active Directory and process it in GoBright is:

Push-ADUsersToBB [filter] [optional: specific username/pincode field] -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]'

You can use the following parameters in the ‘Push-ADUsersToBB’ command:

-Filter
(required)
The filter condition to filter the users you want to synchronize (more documentation available)
-SearchBase
(optional)
Specifies the Active Directory path the search under (more documentation available)

-ADSpecificUsername
(optional)

By default, the user will authenticate with the primary e-mail address of the user to the Microsoft Exchange Server or Office365.

Provide these values to use a different way of authenticating the user to the Microsoft Exchange Server or Office365:
DomainPlusUsername to use DOMAINusername
UserPrincipalName to use the UPN

-ADUserPincodePropertyName
(optional)

Specify a field name of a field in Active Directory which you want to use as a ‘pincode’ (has to be numeric, minimum of 4 digits, and has to be unique)

-ADUserMobilePropertyName
(optional)

Specify a field name of a field in Active Directory which you want to use to get the mobile phone number of the users (e.g. for notification of the digital reception)
Will use the standard ‘Mobile’ field by default.

-ADUserNFCIdPropertyName
(optional)

Specify a field name of a field in Active Directory which you want to use to get the NFC Identifier for that user.

Please note that it should be in HEX format, eg: XX:XX:XX:XX:XX:XX.

-ADUserDefaultCostCenterId OrNamePropertyName
(optional)

Specify a fieldname of a field in Active Directory which you want to use to set the default cost center for that user. You can specify the name or id (‘guid’) of the costcenter, where the name is most commonly used.

-UserRoleNameForNewUsers
(optional)

Optional name of an existing role in the platform to use when new users are created through this synchronization.

-UserDefaultRoleName
(optional)

Set the default rolename for all users that don’t have a match in the ‘GroupUserRoleMapping’ (see below)

-GroupUserRoleMapping
(optional)

This parameter gives you the possibility to assign a role to a user in the platform, based on a group membership in the ActiveDirectory.
You need to supply a hashtable (a key+value list), where the key is the full FQN of the group and the value is the rolename in the platform.

See the example below.

-DeactivateExistingUsersIn
SameIntegrationThatAreNotLoaded
(optional)

Optional switch to automatically deactivate users that are not in the selected users from ActiveDirectory anymore, but still existing in the portal.
Use this switch to automatically disable them.
Only users in the same integration are taken into account (see parameter: BrightBookingIntegrationName)

-BrightBookingApiUrl
(required)
The API url, as found in step 3
-BrightBookingApiKey
(required)
The API url, as found in step 3
-BrightBookingIntegrationName
(required)
The API url, as found in step 3
-WhatIf
(optional)
Use the ‘-WhatIf’ parameter to only test and see, but not actually send data to your GoBright environment

Below you can find several example commands, you can adjust them the way you need to fit your situation.

There commands will not yet actually update users in the system, so these are test commands, because the include the ‘-WhatIf’ parameter.

Example test commands:

Process users with UPN’s ending with ‘yourdomain.com’:

Push-ADUsersToBB -Filter 'UserPrincipalName -like "*yourdomain.com"' -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users with UPN’s ending with ‘yourdomain.com’, and using the ‘PersonnelNumber’ field in ActiveDirectory as pincode for the users:

Push-ADUsersToBB -Filter 'UserPrincipalName -like "*yourdomain.com"' -ADUserPincodePropertyName PersonnelNumber -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users which are members of a specific group in an OU (Organizational Unit):

Push-ADUsersToBB -Filter { memberOf -RecursiveMatch "CN=Administrators,DC=Company,DC=com" } -SearchBase "OU=Office,DC=Company,DC=com" -ADUserPincodePropertyName PersonnelNumber -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users which are members of a specific group in an OU (Organizational Unit) and set a specific role based on their group membership:

$groupToRoleMapping = @()

$groupToRoleMapping += @ # match specific users that belong to a group
$groupToRoleMapping += @ # match specific users that belong to a group
$groupToRoleMapping += @ # match specific users that belong to a group to a role of View
$groupToRoleMapping += @ # **special case** this line matches for every user, because of the 'MatchType', and is needed when you want to have a generic role for every user
$roleNameDefaultIfNoGroupMatched = "Regular user"
Push-ADUsersToBB -Filter { memberOf -RecursiveMatch "CN=OfficeUsers,DC=Company,DC=com" } -SearchBase "OU=Office,DC=Company,DC=com" -ADUserPincodePropertyName PersonnelNumber -UserDefaultRoleName $roleNameDefaultIfNoGroupMatched -GroupUserRoleMapping $groupToRoleMapping -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Process users which are members of a specific group in an OU (Organizational Unit), with [domain][username] as authentication username:

Push-ADUsersToBB -Filter { memberOf -RecursiveMatch "CN=Administrators,DC=Company,DC=com" } -SearchBase "OU=Office,DC=Company,DC=com" -ADSpecificUsername DomainPlusUsername -BrightBookingApiUrl '[API url]' -BrightBookingApiKey '[API key]' -BrightBookingIntegrationName '[name of integration as created in Admin center > Integrations]' -WhatIf

Step 4.2: Run the actual synchronization

Once the list of users is correctly filtered, you can execute the real synchronization by removing the ‘-WhatIf’ parameter.

So now execute the same command, but without ‘-WhatIf’ and it will process the users to your GoBright environment.

Step 4.3: Schedule the integration to run periodically via Windows task scheduler

Follow these steps to synchronize the users from Active Directory on a schedule:

  • Take the command you’ve composed (see previous steps), and save it in a .ps1 file:
    • Create a .ps1 file (e.g. UsersToBrightBooking.ps1) in a folder you prefer
    • Open the file with an editor, for example ‘notepad’
    • Paste the full command into the file
    • Save the file
  • Execute the file to see if it is successfull
  • Create a task in the Windows task scheduler:
    • Open Windows task scheduler
    • Create a task
    • Set a schedule, for example once a day, or every 4 hours
    • Add an action ‘Start a program’:
      • Program/script:
        Powershell.exe
      • Parameters:
        -windowstyle minimized -c “powershell -c .[Name of the created .ps1 file] -verbose >> ExportToGoBright_Output.txt 2>&1″
      • Start in:
        Fill the ‘start in’ with the location of the script, e.g.: C:scripts

Sync interval for testing

The advice for the sync interval is a scope of the following amounts below:

  • 0 to 2000 users: the sync can be run 4 times a day
  • Over 2000 users: the sync can be run 2 times a day

For testing approximately 3-4 times in an hour we strongly advise to run the script with small batches of 10 users per run.

This article comes from the Help Center of GoBright.

View original article

FAQ

Ask us anything! Find the answers to the most frequently asked questions here.

Browse the FAQs

Help Center

A goldmine for all IT and Facility Managers. Dive into the technical stuff concerning our products and solutions.

Visit the Help Center

Newsletter

Wanna stay informed of all developments within the smart office and our new features? Subscribe now.

Subscribe now