Search code examples
azurenext.jsazure-active-directorynext-authazure-authentication

Fetch profile image from Azure Active Directory with Next-Auth authentication


I am able to fetch below details from Azure AD provider while using Next-Auth, but unable to fetch profile picture.

{
  ver: '2.0',
  iss: 'https://login.microsoftonline.com/xxxxxxxx-0000-xxxx-xxxx-xxxxxxxxxx/v2.0',
  sub: 'xxxxxxxxxxxxxxx',
  aud: 'xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
  exp: 0000000000,
  iat: 0000000000,
  nbf: 0000000000,
  name: 'Dibyendu Saha',
  preferred_username: '[email protected]',
  oid: '00000000-0000-0000-000-0000000000000',
  email: '[email protected]',
  tid: 'xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx',
  aio: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}

I also want to fetch first name and surname also in addition to profile picture.

I have checked the documentation from 'https://next-auth.js.org/providers/azure-ad'. I have checked the note as well:

Azure AD returns the profile picture in an ArrayBuffer, instead of just a URL to the image, so our provider converts it to a base64 encoded image string and returns that instead. See: https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples. The default image size is 48x48 to avoid running out of space in case the session is saved as a JWT.

Next Auth Provider code as below:

   AzureADProvider({
      clientId: process.env.AZURE_AD_CLIENT_ID as string,
      clientSecret: process.env.AZURE_AD_CLIENT_SECRET as string,
      profile: (profile: AzureADProfile) => {
        console.log(profile);
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
          image: profile.picture,
          firstName: profile.name,
          lastName: profile.name
        };
      },
    }),

Solution

  • I created an Azure AD Application and generated tokens via Postman by using below parameters:

    https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
    
    client_id:ClientID
    scope:https://graph.microsoft.com/.default openid offline_access
    code:code
    redirect_uri:https://jwt.ms
    grant_type:authorization_code
    client_secret:ClientSecret
    

    enter image description here

    When I decoded the access token, there is no profile picture details displayed:

    enter image description here

    Note that: To fetch the user's profile picture you need to call Microsoft Graph API. You cannot get user's profile image from Azure AD tokens.

    To fetch the User's profile picture, grant User.Read.All API permission:

    enter image description here

    And generate the access token for Microsoft Graph API like below:

    Pass scope as https://graph.microsoft.com/.default

    enter image description here

    Using the above access token, you can fetch the signed in user's Profile picture by using below query:

    GET https://graph.microsoft.com/v1.0/me/photo/$value
    

    enter image description here

    If you want to pass UserID make use of below query:

    https://graph.microsoft.com/v1.0/users/UserID/photo/$value
    

    enter image description here

    To do the same in nextauth.js use the below sample code:

     providers: [
    
       AzureADProvider({
         clientId: process.env.AZURE_AD_CLIENT_ID,
         clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
         tenantId: process.env.AZURE_AD_TENANT_ID,
         authorization: { params: { scope: "User.Read.All openid offline_access" } },
      }),
     ],
    
    async profile(profile, tokens) {
        const profilePicture = await fetch(
        `https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
        {
          headers: {
            Authorization: `Bearer ${tokens.access_token}`,
          },
        }
      )
    
       if (profilePicture.ok) {
        const pictureBuffer = await profilePicture.arrayBuffer()
        const pictureBase64 = Buffer.from(pictureBuffer).toString("base64")
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
          image: `data:image/jpeg;base64, ${pictureBase64}`,
        }
      } else {
        return {
          id: profile.sub,
          name: profile.name,
          email: profile.email,
        }
      }
    }
    

    References:

    Get profilePhoto - Microsoft Graph v1.0

    Azure AD Provider - Profile image doesn't work · Issue #5376 · nextauthjs/next-auth · GitHub by drewgillen