How can I retrieve a Microsoft account profile photo using MicrosoftAccountOptions in ASP.NET Core?

80 Views Asked by At

I am trying to claim a Microsoft account profile photo using MicrosoftAccountOptions in an ASP.NET Core application.

I have built an example app following the guide on "Facebook, Google, and external provider authentication in ASP.NET Core".

The registration process with a Microsoft account is working, and here is the snapshot of my AspNetUsers table after registering with the app:

sqlite> SELECT * FROM AspNetUsers;
                  Id = ...
   AccessFailedCount = 0
    ConcurrencyStamp = ...
               Email = ...
      EmailConfirmed = 1
      LockoutEnabled = 1
          LockoutEnd = 
     NormalizedEmail = ...
  NormalizedUserName = ...
        PasswordHash = 
         PhoneNumber = 
PhoneNumberConfirmed = 0
       SecurityStamp = ...
    TwoFactorEnabled = 0
            UserName = ...

I am also attempting to claim the profile photo. I tried microsoftOptions.ClaimActions.MapJsonKey("photo", "picture", "url");, but it didn't add a new url column to the table.

I found the "photo" keyword in the "JSON representation", but I am struggling to understand how to handle its type.

Here's the relevant part of my Program.cs:

Program.cs
// ...

services
.AddAuthentication()
.AddMicrosoftAccount(microsoftOptions =>
{
  microsoftOptions.ClientId = configuration["Authentication:Microsoft:ClientId"];
  microsoftOptions.ClientSecret = configuration["Authentication:Microsoft:ClientSecret"];

  //microsoftOptions.ClaimActions.MapJsonKey("photo", "picture", "url");

// ...
});

Can anyone provide guidance on how to correctly claim the Microsoft account profile photo using MicrosoftAccountOptions?

1

There are 1 best solutions below

0
Md Farid Uddin Kiron On

How can I retrieve a Microsoft account profile photo using MicrosoftAccountOptions in ASP.NET Core?

Well, Retrieving a Microsoft account profile photo using MicrosoftAccountOptions in ASP.NET Core doesn't involve directly mapping it to the AspNetUsers table. Instead, you need to leverage the Microsoft Graph API.

Using graph API you could to that. In order to get profile picture, you should have "User.Read" permission.

So you should inject the permission with your microsoftOptions.Scopes. You should do as following:

services.AddAuthentication()
.AddMicrosoftAccount(microsoftOptions =>
{
    microsoftOptions.ClientId = configuration["Authentication:Microsoft:ClientId"];
    microsoftOptions.ClientSecret = configuration["Authentication:Microsoft:ClientSecret"];
    microsoftOptions.Scopes = new[] { "User.Read" }; 
});

Controller:

In your controller or wherever you need to access the user's profile photo, obtain the access token from the authenticated user claims. Then Use the acquired access token to call the Microsoft Graph API endpoint https://graph.microsoft.com/v1.0/me/photo/$value.

So, you could try as following:

private async Task<Image> GetPhotoUsingAccessToken(string accessToken)
{
   

    var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(
        async requestMessage =>
        {
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        }));

    using (var photoStream = await graphClient.Me.Photo.Content.RequestAsync())
    {
        
        var image = Image.FromStream(photoStream);
        return image;
    }
}

Note: Above implementation will return the user's profile photo as a binary stream. This example would need graph SDK to isntall, . If you want need more information, please refer to this official document.