[SalesForce] Show user profile image – third party site

I am using Salesforce REST API to pull in the user profile salesforce object into my external site. I wanted to be able to display things like about me, title, and image on my site. I get all of this information from the following endpoint.

/services/data/v41.0/sobjects/User/{USERID}

The information I then pull from this is

Name
Email
FullPhotoUrl

I tried putting the FullPhotoUrl into an img html tag but it shows as broken link

Key thing to note is I am using the JWT bearer token authentication oauth flow for server to server communication. The user of my site does not have their own salesforce login and the data gathering happens all server side. The image does show if I login to my environment myself in another tab. I am guessing there is some sort of cookie that is allowing the image to be shown

TLDR: How do I get the user profile image url link I get in the rest api to show in an external site img tag?

Documentation of JWT flow: https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&type=5

Best Answer

You might be able to add something to the headers or the page to be able to access the actual photo url, but I'd avoid the whole thing & provide the photo in another form, either in base64, or as a publicly linked (you can set up "private" links as well) ContentVersion.

Base64

  1. Get PhotoUrl
  2. Get PageReference Content
  3. Save into field/return with other data
  4. Use on page with img tag

Downsides: Spotty support (never had a problem unless its an email), large amount of text, may need to return per request depending on how you set your page up (best used as a saved database entry instead of getting a value with each request)

ContentVersion

  1. Get the photo url
  2. Create new content version
  3. Upload Blob of User photo to the version
  4. Share using built in link feature
  5. Save link back to user (needs own context)
  6. Return Link Url with user record
  7. Display link on page

Downsides: Link is likely public to anyone with a copy of it, Setting this up to happen automatically is a pain, since you cant update a setup object & a non-setup object in the same context, Lots of extra objects involved to get the data to be shareable (ContentDocument, ContentVersion, User, etc)


Base64 Sample Code (Should run in dev console):

public static String GetBase64Content(String url) {
    String Base64Content = 'data:image/png;base64, '; 

    if (url != null) {
        PageReference imageSource = new PageReference(url); 

        Blob b = imageSource.getContent();

        Base64Content += EncodingUtil.base64Encode(b); 
    }

    return Base64Content; 
}

User u = [
    SELECT Id, FullPhotoUrl 
    FROM User 
    WHERE Id = :UserInfo.getUserId()
    LIMIT 1
];

String content = GetBase64Content(u.FullPhotoUrl);

// use like: 
// <img src="{!content}" />

You may need to store the base64 result either in a long/rich text field or in a json object, depending on how your server handles the data.


ContentVersion Demo

Creates a contentVersion using the blob from the users FullPhotoUrl, set to "publicly available", which creates a ContentDistribution, which you can query & get the ContentDownloadUrl from, which you can use in an img tag or store somewhere. Could be useful to create base64 or binary files on a target server.

private static ContentVersion CreateVersion(User u, Blob body) {
    return new ContentVersion(
        // https://salesforce.stackexchange.com/questions/117113/migrating-chatter-files-attached-to-feed-comments
        OwnerId = UserInfo.getUserId(), // Has to be running user - won't be able to create otherwise.. 
        VersionData = body,
        Title = 'Profile Photo of ' + u.Name,
        PathOnClient = 'profilePhoto.png',
        Origin = 'H',
        Profile_Image_Owner__c = u.Id, 
        Externally_Available__c = true,
        FirstPublishLocationId = LibraryId  // Used Custom setting w/ specific id, should replace with target dir 
    );
}

User u = [
    SELECT Id, FullPhotoUrl 
    FROM User 
    WHERE Id = :UserInfo.getUserId()
    LIMIT 1
];

ContentVersion version = CreateVersion(u, new PageReference(u.FullPhotoUrl).getContent());

insert version;

ContentDistribution dist = [
    SELECT Id, DistributionPublicUrl, ContentDownloadUrl
    FROM ContentDistribution
    WHERE ContentVersionId = :version.Id
];

// Use like so:
// <img src="{!dist.ContentDownloadUrl}" />

// Need to update user to attach content url/id in a seperate context 
// Could also save user id to document & query, or return id in response from server