Script Repository


Associate Office 365 account with Active Directory user

October 18, 2018
1942

Adaxes allows managing Office 365 properties of a user only if the Immutable ID property of an Office 365 account matches the Object GUID property of the AD user account. When an Office 365 account is created in Adaxes or if your AD is synchronized with Office 365 via DirSync or AAD Sync, an immutable ID is assigned automatically. However, if an Office 365 account was created outside of Adaxes, and your AD environment is not synchronized, the ID will not be assigned. This means that you won't be able to manage properties of such an Office 365 account in Adaxes.

You can use the below script in order to associate an Office 365 account with an AD user by specifying an appropriate immutable ID. The script associates an Office 365 account with a user if the Office 365 username corresponds to one of the following:

  • The User Principal Name (UPN) of the user in Active Directory (displayed in Adaxes as Windows Logon Name).
  • The UPN prefix of the AD user combined with the default domain of their Office 365 Tenant. For example, if the UPN of the user is john.doe@example.com, and the tenant name is Fabrikam, the script will search for an Office 365 account with the following username: john.doe@fabrikam.onmicrosoft.com.
  • The email address of the user stored in the Email property and all SMTP addresses stored in the Email Proxy Addresses property.

Using the script, you can create a Custom Command for User objects and run it against users whose Office 365 accounts you want to associate. To add the script to a Custom Command, use the Run a program or PowerShell script action.

For the script to work, you need to install Microsoft Azure Active Directory Module for Windows PowerShell on each computer where Adaxes service is running.

Edit Remove
PowerShell
# Check whether the user's Office 365 account is already linked
try
{
    $immutableId = $Context.TargetObject.Get("adm-O365ObjectId")
    return # already associated
}
catch
{
}

$office365Cred = $Context.GetOffice365Credential()
if ($office365Cred -eq $NULL)
{
    return # user is not associated with an Office 365 Tenant
}

# Get Email Proxy Addresses
try
{
    $proxyAddresses = $Context.TargetObject.Get("proxyAddresses")
}
catch
{
    $proxyAddresses = @()
}

# Create an immutable ID
$guid = $Context.TargetObject.Get("objectGuid")
$immutableId = [System.Convert]::ToBase64String($guid)

$scriptBlock = {
    param($office365Cred, $proxyAddresses, $immutableId)
    Import-Module MsOnline
    
    function SearchUser ($searchString)
    {
        return Get-MsolUser -SearchString $searchString
    }
    
    function SetImmutableId ($objectId, $immutableId)
    {
        Set-MsolUser -ObjectId $objectId -ImmutableId $immutableId
    }
    
    Connect-MsolService -Credential $office365Cred
    
    # Get domains registered in the Office 365 Tenant
    $domains = (Get-MsolDomain) -as [System.Array]
    
    # Find a corresponding account in Office 365
    $userPrincipalName = "%userPrincipalName%"
    $searchParameters = @()

    if (-not ([System.String]::IsNullOrEmpty($userPrincipalName)))
    {
        # Check whether the user's UPN belongs to one of the registered domains
        $domainPart = $userPrincipalName.Substring($userPrincipalName.IndexOf("@") + 1)
        foreach ($domain in $domains)
        {
            if ($domain.Name -ne $domainPart)
            {
                continue
            }
            
            # Add complete UPN to the search parameters
            $searchParameters += $userPrincipalName
            break
        }
        
        # Build a username in the default domain (@something.onmicrosoft.com)
        $defaultDomain = $domains | where {$_.IsDefault}
        $username = $userPrincipalName.Substring(0, $userPrincipalName.IndexOf("@"))
        
        # Add the username to search parameters
        $searchParameters += "$username@" + $defaultDomain.Name
    }

    # Add email proxy addresses to search parameters
    foreach ($addressWithType in $proxyAddresses)
    {
        if (-not ($addressWithType.StartsWith("smtp", [System.StringComparison]"CurrentCultureIgnoreCase")))
        {
            continue
        }
        
        $address = $addressWithType.SubString(5)
        $searchParameters += $address
    }
    
    # Add Email property to search parameters
    if (-not ([System.String]::IsNullOrEmpty("%mail%")))
    {
        $searchParameters += "%mail%"
    }

    # Find user in Office 365
    foreach ($string in $searchParameters)
    {
        $msolUser = SearchUser $string
        if ($msolUser -eq $NULL)
        {
            continue
        }
        
        # Assign an immutable ID
        SetImmutableId $msolUser.ObjectId $immutableId
        return # exit script
    }
    
    Write-Error "User account not found in Office 365."
}

# Start Windows PowerShell as a separate process and run the script block in that process
$waitTimeSeconds = 9 * 60
$job = Start-Job -ScriptBlock $scriptBlock -ArgumentList $office365Cred, $proxyAddresses, $immutableId
Wait-Job -Job $job -Timeout $waitTimeSeconds

if ($job.State -ne "Completed")
{
    return
}

# Get output from the process
Receive-Job -Job $job


Comments ( 2 )
avatar
Tim
March 05, 2019

I get the following error on a few of my users. Any idea?

Uniqueness violation. Property: SourceAnchor. Stack trace: at SetImmutableId, <No file>: line 12 at <ScriptBlock>, <No file>: line 41

avatar
Support
March 05, 2019

Hello Tim,

The error can appear when the immutableID the script attempts to set to the object is already set to an object in Office 365. It is also related to the objects in Office 365 Recycle Bin.
For details about Office 365 Recycle Bin, have a look at the following article: https://www.pei.com/2013/01/emptying-the-office-365-recycle-bin/.
For additional information about the error, have a look at the following article: http://masterandcmdr.com/uniqueness-violation-property-sourceanchor/.

Leave a comment