Razvan Zamfir
Razvan Zamfir

Reputation: 4686

How can I get the current user's picture from Microsoft Graph in this Laravel app?

I am working on a Laravel 8 app that uses Microsoft Azure for user management (login included).

I began by following this tutorial on their website.

I got stuck trying to display the current user's picture.

In the view I have:

<img src="{{ isset($user_avatar) ? $user_avatar : asset('img/default-avatar.png') }}" class="rounded-circle avatar-top">

In the AuthController controller I get the current user with the data:

$user = $graph->createRequest('GET', '/me? 
$select=displayName,mail,mailboxSettings,userPrincipalName,givenName,surname,photo')
      ->setReturnType(Model\User::class)
      ->execute();

In the app\Http\Controllers\Controller.php I have:

class Controller extends BaseController {
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
        
    public function loadViewData() {

        $viewData = [];

        // Check for flash errors
        if (session('error')) {
            $viewData['error'] = session('error');
            $viewData['errorDetail'] = session('errorDetail');
        }

        // Check for logged on user
        if (session('userName'))
        {
            $viewData['userName'] = session('userName');
            $viewData['firstName'] = session('firstName');
            $viewData['lastName'] = session('lastName');
            $viewData['user_avatar'] = session('userAvatar');
            $viewData['userEmail'] = session('userEmail');
            $viewData['userTimeZone'] = session('userTimeZone');
        }

        return $viewData;
    }
}

In the DashboardContoller, I pass $viewData to the view:

class DashboardContoller extends Controller
{
    public function index(){
        $viewData = $this->loadViewData();
        return view('dashboard', $viewData);
    }
}

In app\TokenStore\TokenCache.php I have:

public function storeTokens($accessToken, $user) {
 session([
  'accessToken' => $accessToken->getToken(),
  'refreshToken' => $accessToken->getRefreshToken(),
  'tokenExpires' => $accessToken->getExpires(),
  'userName' => $user->getDisplayName(),
  'firstName' => $user->getGivenName(),
  'lastName' => $user->getSurname(),
  // Set AVATAR
  'userAvatar' => $user->getPhoto(),
  'userEmail' => null !== $user->getMail() ? $user->getMail() : $user->getUserPrincipalName(),
  'userTimeZone' => $user->getMailboxSettings()->getTimeZone()
 ]);
}

As can be seen above, I use the getPhoto() method present in the User model (vendor\microsoft\microsoft-graph\src\Model\User.php).

I successfully displayed the user's full name this way.

The problem:

For a reason I have been unable to figure out, the user_avatar returns null.

What is my mistake?

Upvotes: 1

Views: 1681

Answers (1)

user2250152
user2250152

Reputation: 20723

It's known issue that Photo property on User resource type is always null. Graph API doesn't support using Select with the Photo property at the moment.

To get the content of photo you have to call another endpoint

GET /me/photo/$value
GET /users/{id | userPrincipalName}/photo/$value

Add to AuthController

$photo = $graph->createRequest("GET", "/me/photo/\$value")
       ->execute();
$photoMeta = $graph->createRequest("GET", "/me/photo")
       ->execute();

Update storeTokens function for userAvatar

public function storeTokens($accessToken, $user, $photo, $photoMeta) {
 $body = $photo->getRawBody();
 $base64 = base64_encode($body);
 $meta = $photoMeta->getBody();
 $mime = $meta["@odata.mediaContentType"]
 $img = ('data:' . $mime . ';base64,' . $base64);
 session([
  'accessToken' => $accessToken->getToken(),
  'refreshToken' => $accessToken->getRefreshToken(),
  'tokenExpires' => $accessToken->getExpires(),
  'userName' => $user->getDisplayName(),
  'firstName' => $user->getGivenName(),
  'lastName' => $user->getSurname(),
  // Set AVATAR
  'userAvatar' => $img,
  'userEmail' => null !== $user->getMail() ? $user->getMail() : $user->getUserPrincipalName(),
  'userTimeZone' => $user->getMailboxSettings()->getTimeZone()
 ]);
}

Resources:

Get profilePhoto

How to include photo

Graph API support for Photos property in select

Upvotes: 2

Related Questions