SPFx – SharePoint Online User Profile Photo Sync

Introduction

Hi, friends a few days ago I had posted an article on ‘SharePoint Online User Photo Sync.‘ It explains how the user photos displayed in the SharePoint site from the exchange online and also covered on the option for syncing the photos from AAD to SharePoint using PnP Profile Uploader.

In this post, let me introduce you to the SPFx web part that would facilitate the administrator to sync the profile photos from AAD or the FileShares to SharePoint User Profile store.

Features

  • User selection will help you to update only specific user based on the selection. It will also allow the users to fetch the photos from Azure AD before starting the synchronization.
  • Bulk Sync will allow the admin to upload the photos from their file shares. The filename should be in the format ‘UserID.jpg‘.
  • Access control based on SharePoint Group, not all the users can access the application.
  • Separate section to check the status of the photo update.
  • Azure Function to handle the photo update. PnPPowershell is used in Azure Function.
  • The application supports SPA.

Note: All the supporting lists were created when the web part is loaded for the first time. Whenever the web part is loaded, the supported lists were checked whether it exists or not.

Properties

  • Select a library to store the thumbnails: A document library to store the thumbnail photos.
  • Delete thumbnail stored: This flag will decide whether you want to keep the thumbnails generated or to clean it after the sync completed.
  • Azure Function URL: Azure function URL to run the photo update.
  • Use Certificate for Azure Function authentication: The video mentioned below to setup Azure Function has different options. This setting will decide whether to use the certificate or stored credentials to communicate with SharePoint.
  • Date format: Date format to be used across the entire application. Used momentJS.
  • SharePoint Groups: Only the users from the configured SharePoint Groups and Site Administrator shall be allowed access.
  • Use page full width: This is used when the web part is added to a site page where it has to use full width.

Preview

Source Code

The above web-part is shared with the community and is of free to use. Please click the below link to download the code and have fun.

React-Photo-Sync

Happy Coding…

41 thoughts on “SPFx – SharePoint Online User Profile Photo Sync

  1. Pingback: SharePoint PnP Dev SPFx JS SIG Call – October 22nd, 2020 – Screenshot Summary - Warner Digital

  2. I wanted to use your trick to get the full width, so I tested:
    jQuery(“.SPCanvas-canvas”).prop(“style”, “max-width: none”);
    jQuery(“.CanvasZone”).prop(“style”, “max-width: none”);
    But without jQuery
    document.getElementsByClassName(‘SPCanvas-canvas’)
    document.getElementsByClassName(‘CanvasZone’)
    But sometimes it works because there is 1 item in the array but other times the HTMLCollection is empty.
    Does it always work for you? Any web part?
    Thank you

    Liked by 1 person

  3. Hello Sudharsan, I repeatedly tried and failed to configure the azure function.
    I created a http trigger and and pasted the script ftom assets folder SPUPS_Photo_Sync.ps1 to the run.sp1 in az function. Saved it and then used the azure default-key fucntion URL in the webpart. Saved the webpart and search the user and hit sync. Nothing happens No logs created in the azure functions as well.
    How to debug? Am I missing something?
    I am new to this SPFX world. forgive my ignorance.
    –Aman

    Like

    • Hi Aman, thanks for trying out the solution. Let me know what is the issue when you are trying to execute the Azure Function. You can check the issue in the Monitor section of the particular function. There are few configuration params that have to be created for the Function App.
      1. Tenant – Which is the tenant name
      2. ClientID – Client secret
      3. ServiceAccount – SharePoint Administrator account name
      4. ServiceAccountPwd – SharePoint Administrator account pwd
      5. Thumbprint – Certificate thumbprint if you are using cert authentication.

      Please go through the below video for Azure Function

      Like

  4. Hello Sudharsan. Thank you for the video link..I had configured as mentioned. but i think something is not right. If you could take some time out and create a short video or upload a step by step instructions for a beginner like me. I would highly appreciate it.
    This project will help me understand a lot. Thanks in advance.
    I am in a support industry and getting this executed will help lots of admins across the world. I have frustrated admins break down with no solutions. Most of them with hybrid config. no exo license.
    This wil definitely give an edge.
    God bless you for the wonderful work you are doing.

    Like

  5. Thanks for sharing this tool.
    I am new to this but am having trouble building the solution. Where have I gone wrong?

    [tsc] typescript version: 3.3.4000
    [12:59:31] Finished subtask ‘tslint’ after 9.49 s
    [12:59:32] Error – [tsc] src/webparts/photoSync/PhotoSyncWebPart.ts(81,19): error TS2416: Property ‘dataVersion’ in type ‘PhotoSyncWebPart’ is not assignable to the same property in base type ‘BaseClientSideWebPart’.
    [12:59:32] [tsc] Property ‘_major’ is missing in type ‘Version’ but required in type ‘Version’.
    [12:59:32] Error – ‘tsc’ sub task errored after 8.81 s

    Like

      • Hi Sudharsan,

        All deployed but only a spinning icon when retrieving photo from Azure.
        What should my run.ps1 look like as opposed to the video above? Everything else I followed in that video to the letter.
        Thank you!

        Like

  6. Pasted the script from assets folder SPUPS_Photo_Sync.ps1 to the run.sp1 in az function.
    Just did that and same outcome…..spinning icon. Pulls pic from SP but when I hit ‘get from Azure’…it just spins???
    Please forgive my ignorance with SPFX and Powershell Online.

    Like

    • Hi, have you updated the function url with the keys in the web part properties. If possible open the dev tools in the browser and send me the error when you click the button to get the photo from azure.

      Like

  7. Uncaught (in promise) InteractionRequiredAuthError: AADSTS65001: The user or administrator has not consented to use the application with ID ‘17557252-78a8-46a6-8d23-522a35ab2af6’ named ‘SharePoint Online Client Extensibility Web Application Principal’. Send an interactive authorization request for this user and resource.
    Trace ID: 301698e0-c8d4-4aaf-b0a7-029f01df1701
    Correlation ID: b532e5cb-b99d-49c8-a0f7-04d34f1a4112
    Timestamp: 2021-07-01 08:01:48Z
    at t [as constructor] (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at t [as constructor] (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at new t (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at e.saveTokenFromHash (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at e.processCallBack (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at e.handleAuthenticationResponse (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at e. (chunk.vendors~msalImplicit_none_2a19e0d86b4f1c2475a1.js:1)
    at sp-pages-assembly_en-us_936a12a5ccfae2244c3a4528c462bea8.js:1
    at Object.next (sp-pages-assembly_en-us_936a12a5ccfae2244c3a4528c462bea8.js:1)
    at c (sp-pages-assembly_en-us_936a12a5ccfae2244c3a4528c462bea8.js:1)

    Like

  8. Where do I set that in particular?
    I’ve already set this before the Azure App was made:
    “Allow user consent for apps”
    “All users can consent for any app to access the organization’s data.”

    Like

  9. Yay! Finally got it working.
    Seems I had to give the SharePoint Online Client Extensibility Web Application Principal Admin permissions for AAD Graph UserRead.ALL

    Thank you so much for persisting with me! Awesome!

    Like

  10. Spoke too soon.
    It isn’t pulling the photo from AzureAD – Just says Photo not found. I can see the pics in Azure AD for these users.
    Any ideas?

    Like

  11. Yeah, unfortunately no successful runs registered in the Function and the requests submitted in the WebPart stay at Submitted.
    I am totally lost….

    Like

  12. Hello Sudharsan,
    I am facing a problem regarding SPFX react-photo-sync. I hope you will help me.

    Problem: The react photo sync is not passing any payload in the request parameter. So my Azure function (SPUPS_Photo_Sync.ps1) getting an error for null strings in $jsoninput

    Detailed view:
    $adminurl ,$mysiteurl ,$targetsiteurl ,$picfolder ,$usecert ,$itemid ,$clearPhotos etc. are getting null that causes erros in these functions like.function connectSPOnline, uploadToUserProfilePictures etc.

    Actions did already:
    1) Placed SPUPS photo sync web part in SharePoint (without changing script) [ Everything is working correctly in SharePoint but, photos are not updating in the backend (from Azure function) ].
    2) Copied the same SPUPS_Photo_Sync.ps1 script into Azure function (without changing script).
    3) Changed FUNCTION_EXTENSION_VERSION = ~1

    What I am doing wrong? if you can help me, That will be great..!
    Thank You.

    Like

    • Hi, sorry to hear that you are facing some issues. Can you please check the ‘UPS Photo Sync Jobs’ list and check whether the json payload is available in the ‘SyncData’ field? Let me know whether the issues occurs on both ‘User Selection Photo Sync’ and ‘Bulk Sync’? If you haven’t tried the ‘Bulk Sync’, can you please try the ‘Bulk Sync’ and let me know whether it works or not.

      Like

      • Hi, based on the error on the Azure Function, there are some null values passed and also there is an error ‘command not found’ which is due to the missing dll’s. If you can pass me the json generated by removing your tenant name and also if any username mentioned in the photo with the sample data, it will help the troubleshooting process.

        For manual, are you able to get the photos from Azure? Have you approved the API access in the SharePoint Admin center for the web part to access the Graph API?

        Like

  13. Hello Sudharsan,

    You have built a very great solution here. I have already been able to adapt a few small things so that this also works via Function V3 etc. Very happy with it.
    But i have a small problem with the Bulk Sync.
    When I try to upload pictures in Bulk Sync, I always get the message:

    User not found! – https://i.imgur.com/kwrwx2n.png

    UserId seems to be correct: https://i.imgur.com/cHRfpsW.png

    Can also resolve the user via User Selection Photo Sync: https://i.imgur.com/HPN2OaK.png

    Do you have any idea what this could be?

    Like

  14. Hi Sudharsan,

    The idea of the whole solution is fantastic but the big problem is the instructions to get this to work. Especially the set up of the Azure function, i be having a hard time to get this working likewise many people here. Can you please provide any support ?

    Like

      • Hi,
        I would love too.

        -I’ve uploaded the spkg file to the app catalog and granted it the correct api permissions.
        – Created a azure function and pasted the script SPUPS_Photo_Sync in the Http trigger
        -Copied the function url into the Azure Function Url field in SP.

        My problem is that nothing happens when i’m trying to update photo, it just keep loading. And the Azure Profile Photo picture is not displaying.

        This is how it looks in the webrowser console:
        Uncaught (in promise) Error: Error making HttpClient request in queryable [400] ::> {“odata.error”:{“code”:”-2147024809, System.ArgumentException”,”message”:{“lang”:”en-US”,”value”:”Server relative urls must start with SPWeb.ServerRelativeUrl”}}}

        Like

  15. A concise set of install instructions would be great. I know you know how to do it, but I have no idea where to start with O365 Workbench

    Thanks

    Like

  16. failing to build package in Docker:

    npm notice New major version of npm available! 8.19.4 -> 9.6.7
    npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.6.7
    npm notice Run npm install -g npm@9.6.7 to update!
    npm notice
    npm ERR! code 1
    npm ERR! path /workspaces/project/node_modules/deasync
    npm ERR! command failed
    npm ERR! command sh -c — node ./build.js
    npm ERR! gyp info it worked if it ends with ok
    npm ERR! gyp info using node-gyp@3.8.0
    npm ERR! gyp info using node@16.20.0 | linux | x64
    npm ERR! gyp ERR! configure error
    npm ERR! gyp ERR! stack Error: Command failed: /usr/local/python/current/bin/python -c import sys; print “%s.%s.%s” % sys.version_info[:3];
    npm ERR! gyp ERR! stack File “”, line 1
    npm ERR! gyp ERR! stack import sys; print “%s.%s.%s” % sys.version_info[:3];
    npm ERR! gyp ERR! stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    npm ERR! gyp ERR! stack SyntaxError: Missing parentheses in call to ‘print’. Did you mean print(…)?
    npm ERR! gyp ERR! stack
    npm ERR! gyp ERR! stack at ChildProcess.exithandler (node:child_process:402:12)
    npm ERR! gyp ERR! stack at ChildProcess.emit (node:events:513:28)
    npm ERR! gyp ERR! stack at maybeClose (node:internal/child_process:1100:16)
    npm ERR! gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:304:5)
    npm ERR! gyp ERR! System Linux 5.10.16.3-microsoft-standard-WSL2
    npm ERR! gyp ERR! command “/usr/local/bin/node” “/workspaces/project/node_modules/.bin/node-gyp” “rebuild”
    npm ERR! gyp ERR! cwd /workspaces/project/node_modules/deasync
    npm ERR! gyp ERR! node -v v16.20.0
    npm ERR! gyp ERR! node-gyp -v v3.8.0
    npm ERR! gyp ERR! not ok
    npm ERR! Build failed

    Like

  17. This webpart is brilliant. Thanks so much for adding this to the community. Actually I have to the same problem as @sebus. Do you have any running setup for this webpart? I’ve tried with Node v18.x, Node v16.x and Node v14.x and I still get errors.

    On Node v16 I’m able to add deasync via npm install deasync and then install the necessary packages via npm install. But it’s

    Like

Leave a comment