Sync Profile pictures from Azure AD | Community
Skip to main content
Newcomer
November 16, 2021
Question

Sync Profile pictures from Azure AD

  • November 16, 2021
  • 22 replies
  • 1 view

I am trying to Sync Azure AD Profile pictures for all users to Zoom

I am trying to find info on this but cannot  find any valid documentation anywhere.

 

I found articles with people using ADFS to do this but i got rid of ADFS not going back.

 

Does anyone have any information on whether this is possible, I have an ongoing tickect with support but were going in circles

    22 replies

    Newcomer
    May 18, 2023

    I'd also love to see Graph work correctly with SSO to zoom for the profile pics.

    We're using workspace reservation in Zoom now for hot desks, it would be great for the pictures to auto populate on user accounts so they can easily see who is at which desks on which days etc.

    Newcomer
    June 21, 2023

    Just posting to keep this topic alive. I create a new Zoom support case and asked again. I was given a similar answer...

     

    As for your query about syncing profile pictures from Azure AD, you may try to do this via SAML response mapping.
    The basic idea for profile picture mapping is this:
    1. The admin puts the profile pictures onto a web server.
    2. The admin creates a basic SAML mapping for profile pictures. The mapping contains a publicly accessible URL pointing to the web server’s profile picture.
    3. During the SSO process, Zoom pulls the profile picture from the web server and adds it to the user’s profile.
    There is one difference when doing this with Azure AD as the IDP. The image must be base64 encoded before being placed on the server.

    This ins't helpful, so I went back asking for more specifics about what that SAML response might look like (examples from other customers). It is also my understanding that the profile pic isn't available via SAML responses, and instead MS Graph is required. I also understand that MS Graph response is given in binary, so further converting to Base64 will need to be done, which is only possible in the code that made the request (Zoom's portal). If I'm correct (and I could very much be wrong) then this isn't going to work at all, unless Zoom specifically add support for grabbing the photo from MS Graph.

     

     

    Does anyone else have an update?

    Newcomer
    June 21, 2023

    I got a quick response. The answer was

     

    Based on what I have gathered you can map the profile picture by using a direct URL where the picture is located. Unfortunately, there is no specific attribute that would be able to be mapped to bring in the picture. Some of our customers have all the pictures uploaded to a file-sharing site then each picture has its own link.
     
    Here is an image to clarify.

    This isn't a solution, but does provide a glimpse at how using a claim transform, you are able to get unique photos for each user. It doesn't specifically work for Azure because the Graph photo still requires some authentication to get to, and still isn't' in base64 format.

     

    Yes, I could put my photos on a public URL, but if I'm manually doing that, I may as well manually upload the photo to the users' Zoom account instead. 

    Newcomer
    February 22, 2024

    I would like to bump this post. Hosting avatar pictures on a publically accessible server is not an acceptable solution.

     

    +1 to add Microsoft Graph support!

    Newcomer
    February 22, 2024

    We have this working through our provisioning partner we use called Aquera.

     

    We leverage them because ADP is our source of truth for employee data. We hook from Aquera into Azure AD, but also pay for the integration into Zoom because it was such a large organizational ask to get photos in and it is the only way we found to fully automate it.

     

    Not cheap and we would discontinue that integration tomorrow if Zoom got their act together and simply supported MS Graph for this. 

     

    Come on Zoom, Enterprise clients are asking for this and it has been years already! 

    Newcomer
    March 20, 2024

    Bumping post.

    After researching this issue for weeks, it's clear that your customers don't want to erect a web server OUTSIDE OF OUR FIREWALL just to host some profile pictures.  For a company as large as this, it seems absurd to me (and everyone else here) that we simply cannot use a SAML attribute (say 'thumbnailPhoto' - which already exists in AD) and use that as our profile picture.

     

    The reason why is because that attribute is stored as an octet string and it would require you to convert that image to base64 in order for the image to be viewable.  Here's the issue: When you convert that attribute to base64, it's too large to store in AD. It ends up being triple the allotted size for an extensionattribute.

    So, why not convert the image to base64 on the backend?

    I'm pretty sure this won't get a response given the thread, I'm just keeping this post alive.

    Newcomer
    September 6, 2024

    It would be great to see the SAML mapping pull the photo and import automatically into the zoom account.  Giving this a bump 🙂

    Newcomer
    September 17, 2024

    We would like to get this feature as well. 

    Maintaining profile picture for thousands of users in multiple places takes a lot of time.

    Newcomer
    November 8, 2024

    I gave up on this 2 years ago and just run a daily sync job using the same images that are set for Entra. The job uses the zoom Api and the pszoom PowerShell module

    Newcomer
    November 8, 2024

    Wow. You are the first person I believe since this topic was created to have an automated solution. Could you share your sync job script here please?

     

    Newcomer
    November 8, 2024

    Sure - here it is. Zoom doesn't keep the name of the file it's some type of hash or guid I believe so you have to keep a state file. I also have another job for if their photo in the headshot's directory is changed to delete it from the json. This way on the next run it will update in zoom. We also disabled the user's ability to update their own photos as there were some that were doing it daily. This also includes a commented out section to export all the zoom users photos. 

    $Verbose = 2 $LogFileName = [string]::Format("Zoom-{0}.log", (Get-Date -Format yyyy-MM-dd)) $LogFilePath = "C:\Bin\Zoom\$LogFileName"; Function Log { param($message); if ($Verbose -ge 2) { $currenttime = Get-Date -format u; $outputstring = "[" + $currenttime + "] " + $message; $outputstring | Out-File $LogFilepath -Append; } } Function LogAndConsole($message) { if ($Verbose -ge 1) { Write-Host $message -ForegroundColor Green } if ($Verbose -ge 2) { Log $message } } Function LogErrorAndConsole($message) { if ($Verbose -ge 1) { Write-Host $message -ForegroundColor Red } if ($Verbose -ge 2) { Log $message } } import-Module PSZoom #update zoom creds if changed #Get-Credential | Export-Clixml "C:\Bin\Zoom\ZoomAPI.xml" -Force $zoomAPI = Import-Clixml "C:\Bin\Zoom\ZoomAPI.xml" $zoomAPIsplat = @{ AccountID = $zoomAPI.GetNetworkCredential().Domain ClientID = $zoomAPI.GetNetworkCredential().UserName ClientSecret = $zoomAPI.GetNetworkCredential().Password } try { Log 'Connecting to zoom' connect-PSZoom @zoomAPIsplat -ErrorAction Stop } catch { LogErrorAndConsole "[!] Quitting - $($_.Exception.Message)" break } $headshotsPath = "\\(pathhere)\Headshots" ######Export Current Zoom Images###### <# foreach ($user in $zoomUsers){ if ($null -ne $user.pic_url){ $url = $user.pic_url + '?type=large' Invoke-WebRequest -uri $url -OutFile \\$headshotsPath\Headshots\Zoom\Old\$($User.email).jpg } } #> #Get Current Zoom users and dump to json $zoomUsers = Get-ZoomUsers -AllPages | Select-Object email, pic_url $zoomUsers | ConvertTo-Json | Out-File c:\bin\zoom\zoomUsersCurrent.json -Force $zoomLocal = Get-Content c:\bin\zoom\zoomUsersUpdated.json | ConvertFrom-Json $diffs = Compare-Object $zoomUsers $zoomLocal -Property pic_url -PassThru | Where-Object sideindicator -eq '<=' $zoomChangeLog = "ZoomChangeLog-" + (Get-Date -Format yyyy-MM-dd) + '.txt' foreach ($diff in $diffs) { $email = $diff.email $User = Get-ADUser -Filter { UserPrincipalName -eq $email } $picturePath = "\\$headshotsPath\Headshots\$($User.SamAccountName)" + ".jpg" if (Test-Path -Path $picturePath) { $original = [System.Drawing.Image]::FromFile($picturePath) $ratioX = 648 / $original.Width $ratioY = 648 / $original.Height $ratio = $ratioY if ($ratioX -le $ratioY) { $ratio = $ratioX } # Resize the picture [int]$newWidth = $original.Width * $ratio [int]$newHeight = $original.Height * $ratio $newPicture = New-Object System.Drawing.Bitmap($newWidth, $newHeight) $graph = [System.Drawing.Graphics]::FromImage($newPicture) $graph.Clear([System.Drawing.Color]::White) $graph.DrawImage($original, 0, 0, $newWidth, $newHeight) # Set encoder settings for image quality $encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1) $encoder = [System.Drawing.Imaging.Encoder]::Quality $encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($encoder, 100) # Save file $tmpFilePath = "C:\bin\zoom\upload\$($User.SamAccountName)" + ".jpg" $imageCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object { $_.MimeType -eq 'image/jpeg' } $newPicture.Save($tmpFilePath, $imageCodecInfo, $($encoderParams)) $upload = update-ZoomProfilePicture -UserId $email -FileName $tmpFilePath LogandConsole "Updated $($upload.id) at $($upload.added_at)" [System.IO.File]::Delete($tmpFilePath) # Release resources if ($original) { $original.Dispose() } if ($graph) { $graph.Dispose() } if ($newPicture) { $newPicture.Dispose() } } } $zoomUsersUpdated = Get-ZoomUsers -AllPages | Select-Object email, pic_url $zoomUsersUpdated | where pic_url -NE $null | ConvertTo-Json | Out-File c:\bin\zoom\zoomUsersUpdated.json -Force $zoomUsersUpdated.count