Microsoft-graph-docs: Photo upload don't work as an application

Created on 10 Jan 2019  Â·  22Comments  Â·  Source: microsoftgraph/microsoft-graph-docs

The permissions to update a photo are incorrect. Can it please be updated? `It doesn't work with application permissions currently.


Document Details

⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

azurAAD profilePhoto

Most helpful comment

Hi,
It is not currently supported - so a feature request would be required. I'm filing one for consideration on the team which owns the service (my team)

All 22 comments

@dkershaw10 is there any reason this doesn't follow the same permissions table as other operations? I know it is a special API and has its complexities...

The beta description does follow the proper format. However that topic is equally incorrect. Both of them need fixing. Will figure out who needs to fix the docs...

Hi! So is it a feature or a bug that uploading a photo for a group with application permissions does not work?

Hi,
It is not currently supported - so a feature request would be required. I'm filing one for consideration on the team which owns the service (my team)

@kevinbellinger Okay cool! Thanks for letting us know!

Me too on the feature request... I am able to create a Group, but I would also like the ability to upload the photo for the group so that it would sync to the SharePoint site for the site logo.

Is there any update on this item? ETA on the fix?

Also updating a photo of a user is not working with application permissions. Any ETA?

Hello team, I am updating groups pic with delegated permission and it seems like it is being updated but I can not see on the display right way ? Does it takes time to display on the teams app(desktop and web). When I go to the change the profile pic of a team manually, I see the image that updated but I do not see on the display on the teams.

Hi, I am seeing the same as @ashoksubedi1. I can GET the photo re the API once it's uploaded, but it is not appearing in the Office 365 or Azure Portal records.

Still getting error:
The specified object was not found in the store., No photo with class 'IPM.UserPhoto.Preview' exists.

Guys, it's been more than a year since this issue was reported. I still get the error

The specified object was not found in the store., No photo with class 'IPM.UserPhoto.Preview' exists.

when I try to update a user photo with code like the following:

Dim s = New System.IO.MemoryStream
PictureBox1.Image.Save(s, Imaging.ImageFormat.Jpeg)
Await graphServiceClient.Users("[email protected]").Photo.Content.Request().PutAsync(s)

I don't think this is supported to be honest. (I'll check - as the error is referencing an IPM type I don't think exists too)

It's more likely this is a doc bug, than a real bug. We're working on a new version of the API which will allow this.

Edit: I actually answered my own question back in February last year. The answer remains the same - we are working on a new API which will allow this. No current ETA.

A doc bug? That's not a doc bug... I don't know how you guys work internally, but this sounds more like a feature that's documented but was never implemented correctly. And this "doc bug" issue was opened over a year ago, and still is not fixed?

Do you guys realize how many developers have spent many hours trying to figure this out? My boss asked me if it's possible to update our user's photos automatically every now and then... I quicky found out about this SDK, so answered "yes, should not be too difficult". I then spent many hours trying to figure out the Graph SDK (because let's face it, Microsoft sucks at writing documentation: examples are either too simple and incomplete, or they are overly complicated so that you can't figure them out). And now I can go explain to my boss that this is not possible, because the documentation was wrong.

I wish there was a way to stop using MS-software at all, because it happens daily that I stumble accross these kinds of incomprehensible behaviour (mostly in Windows, Group policies, Office, the way Teams gets installed in user profile dirs, ...).

Please tell me there's another way to upload these photo's from within a vb or c# app?

Thank you for your constructive and measured feedback.

As I communicated - this is likely one of the scenarios you outline, we are looking at which it is and will address where it makes sense to address (either by fixing a bug or by updating the content). It was tagged a couple of days ago so that someone could actually sit down and figure out which it is.

As I have also communicated, we have a new API which will replace this one which will fix this if we choose not to add/fix the support in the legacy endpoint. Exact timlng of that is TBD.

If you are looking can you also look into this issue?
https://docs.microsoft.com/en-us/graph/api/team-update-photo?view=graph-rest-beta

Look at the end of the documentation. People still getting error of Internal Server Error while updating the teams' profile pic. I need a really PUT request on this endpoint to work for my APP. "/beta/teams/{id}/photo ". I am mentioning this thread because it is related to the profile pic of users and teams.

I'll ask someone to take a look at that too. That one looks a little strange as the update should go through the Groups path. I'm not sure what they've done here.

As I have also communicated, we have a new API which will replace this one which will fix this if we choose not to add/fix the support in the legacy endpoint. Exact timlng of that is TBD.

As a workaround: can I use the API instead of the SDK? I tried a couple of different ways to include an image in the content using the API, but I get results going from 404 (not found), 500 (internal server error), 400 (bad request). If this should work, can you point me to a working example of how to do this?

I managed to test this earlier between connections. Using the Postman collection referenced at https://docs.microsoft.com/en-us/archive/blogs/aaddevsup/using-postman-to-call-the-microsoft-graph-api-using-client-credentials

and creating my own application, with the permissions granted in a test tenant I was able to GET and PUT an image successfully via Postman using just the basic documentation.

Steps I used:

  1. Configure app and grant correct perms (and consent in AAD portal)
  2. Configure Postman environment with my application details.
  3. Generate App-only token via the examples in collection
  4. GET image for a given user in the tenant via /users/id/photo/$value
  5. Test /me path didn't work (rules out user context in token)
  6. PUT new image for same user.
  7. Test that it works on GET.

I suspect you have an environmental or configuration issue somewhere with your application if you don't manage to get the above to work.

Sorry about another rant, but you just gave a perfect example of what I mean when I say that MS sucks at writing usable documentation.

  • I ask how I can use this feature with the SDK or API-calls. You reply with instructions for using Postman. I'm not trying to do this with Postman, but from within C#/VB.Net. Postman and friends are good for testing but not for using in a desktop app.
  • "PUT new image for same user" are not really helpful instructions. Some api calls need a string-value in the request contents, that's pretty easy. Uploading an image is way more complicated.
  • The errors I get are not related to some problem with getting the token, or setting the wrong permissions.

For what it's worth, I found out what my issue was. I was getting the image from a picturebox, which apparently isn't the same as loading an image from disk. Here's the code I used to successfully update a profilephoto for a user:

Private Async Function GetAccessToken(ByVal tenantId As String, ByVal clientId As String, ByVal clientSecret As String) As Task(Of String)
    Dim builder = ConfidentialClientApplicationBuilder.Create(clientId).WithClientSecret(clientSecret).WithTenantId(tenantId).WithRedirectUri("http://localhost/").Build()
    Dim acquiredTokenResult = builder.AcquireTokenForClient(New List(Of String) From {
        "https://graph.microsoft.com/.default"
    })
    Dim tokenResult = Await acquiredTokenResult.ExecuteAsync()
    Return tokenResult.AccessToken
End Function

Public Async Function uploadphoto() As Task
    Dim Authority As String = "https://graph.microsoft.com"
    Dim Directory As String = "<tenant id>" 
    Dim Application As String = "<client id>" 
    Dim ClientSecret As String = "<client secret>"

    Dim accessToken = Await GetAccessToken(Directory, Application, ClientSecret)
    Dim graphApiVersion = "v1.0" 
    Dim endpoint = $"https://graph.microsoft.com/{graphApiVersion}"
    Dim action = "/users/<email>/photo/$value"

    Using client = New HttpClient()

        Using request = New HttpRequestMessage(HttpMethod.Put, endpoint & action)
            request.Headers.Authorization = New AuthenticationHeaderValue("Bearer", accessToken)

            Dim img As System.Drawing.Image = System.Drawing.Image.FromFile("<full path to jpg>")
            Dim arr As Byte()
            Using MS As New MemoryStream()
                img.Save(MS, System.Drawing.Imaging.ImageFormat.Jpeg)
                arr = MS.ToArray()
            End Using

            request.Content = New ByteArrayContent(arr)
            request.Content.Headers.ContentType = New MediaTypeHeaderValue("image/jpeg")

            response = Await client.SendAsync(request)

        End Using
    End Using
End Function

I do apologize for trying to unblock you quickly by taking your ask for an API example literally and going with the developers choice for testing so you could figure out where you're going wrong while connecting between flights and having a few minutes spare to try and clear out some of these issues in the content.

Reviewing the documentation for the underlying API, I see nothing wrong with it. Perhaps you're expecting a higher level of documentation around the SDK itself and perhaps that is fair, but throwing shade when someone tries to help you is generally not going to produce the desired results. As for my rapid fire example - see above.

Additionally, I recommend using StackOverflow in future to post issues related to things not working the way you expect - the community there is much larger than that which watches people making comments on documents.

Glad you got it working in the end regardless.

@bmaster001 , I also struggled with this problem almost a year ago. I want to use photos that are stored in our database to synchronize it with office 365. I saw that your approach by using the API directly instead of the SDK (.NET API Wrapper by Microsoft) is successful for uploading photo’s with application permission and was for me a trigger to try again.

You mentioned that it was only successful by using images that are stored as file? In my case I have binary blobs that are sourced from the database. Your code put me on the right track.

I was now also able to succesfully write the photo using the API. The key was to uses the byteArrayContent for the API. Thanks!

My code example:

```
Dim pic = New MemoryStream
PictureBox1.Image.Save(pic, Imaging.ImageFormat.Jpeg)

Dim Client As HttpClient = New HttpClient
Client.DefaultRequestHeaders.Add("Authorization", "Bearer " + Result.AccessToken)
Dim userPhotoEnpoint As Uri = New Uri("https://graph.microsoft.com/v1.0/Users/" + TxtEmail.Text + "/Photo/$value")

Dim content As HttpContent = New ByteArrayContent(pic.ToArray)
content.Headers.Add("Content-Type", "image/jpeg")

Dim Httpresult As HttpResponseMessage = Await Client.PutAsync(userPhotoEnpoint, content)
```

Was this page helpful?
0 / 5 - 0 ratings

Related issues

r3dh0t picture r3dh0t  Â·  4Comments

GregSpyra picture GregSpyra  Â·  4Comments

andrewfabrizi picture andrewfabrizi  Â·  3Comments

findyoucef picture findyoucef  Â·  4Comments

joostvdlinden picture joostvdlinden  Â·  4Comments