-1

I have to read a file in a OneDrive sheet using prestashop. I can't use the microsoft/microsoft-graph packet with composer because it need guzzle v6 and prestashop is locked at v5 so i'm rigting the request myself but it seems i'm missing something.

I got the credential figured out, I have my access token (without it or a random string gives me an 401 error).

Now I'm trying to read a file, but even easier than that, I can't list the recent files in my drive. I can do it on the graph explorer (beeing connected) and do whatever I want but whtin the code I always get an "400 error Bad request" with no other detail.

Here is my code, if you can point me to te right direction?

        $url = 'https://graph.microsoft.com/v1.0/me/drive/recent';
        $req = $guzzle->get($url, [
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2',
                'Accept'     => 'application/json, text/plain, */*',
                'Authorization' => 'Bearer ' . $accessToken,
            ],
            'body' => [
            ],
        ]);

EDIT :

The problem seems to be about authorisation, here is the code :

<?php
// 1/ retrieve the access token

        $guzzle = new \GuzzleHttp\Client();
        $url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
        $token = json_decode($guzzle->post($url, [
            'body' => [
                'client_id' => $clientId,
                'client_secret' => $clientSecret,
                'resource' => 'https://graph.microsoft.com/',
                'grant_type' => 'client_credentials',
                //should I use this
                'roles'=>[
                    "Sites.Read.All",
                    "Files.Read.All"
                ],
                //or this?
                'scp' => 'Sites.Read.All Files.Read.All'
            ],
        ])->getBody()->getContents());
        $access_token = $token->access_token;

// 2/ read file content
        $userId = 'email@domain.fr';
        $url = 'https://graph.microsoft.com/v1.0/users/' . $userId . '/drive/items/##FILE_ID##/workbook/worksheets(\'Export\')/range(address=\'a2:d4\')?$select=values';
        //$url = 'https://graph.microsoft.com/v1.0/users/' . $userId . '/drive/list';

        $guzzle = new \GuzzleHttp\Client();
        $req = $guzzle->get($url, [
            'headers' => [
                'Authorization' => 'Bearer ' . $accessToken,
            ]

        ]);
// this return a 403 forbidden
        $ret = json_decode($req->getBody()->getContents());

1 Answers1

0

Most likely you acquire access token (application permission token) via Client credentials grant flow, in that case there is no Me context since it represents signed-in user context (applicable for delegated permission token only).

For application permission token user needs to be explicitly specified, for example:

To call List recent files endpoint at least Files.Read.All and Sites.Read.All permission levels are required.

enter image description here

Once permissions are granted and consented as illustrated below

enter image description here

roles claim should contain the following list of permissions:

"roles": [
    "Sites.Read.All",
    "Files.Read.All"
  ]

enter image description here

$userId = "<username>@<tenant>.onmicrosoft.com";
$url = 'https://graph.microsoft.com/v1.0/users/' . $userId . '/drive/recent';
$guzzle = new Client();
$headers = ['Authorization'=>'Bearer ' . $accessToken];
$response = $guzzle->get($url,['headers' => $headers]);
$json = json_decode($response->getBody()->getContents(),true);

To determine whether access token is delegated or application permission, jwt.io service, for instance, could be utilized:

for application permission token, the permissions are provided in the roles claim:

enter image description here

For delegated permission token, the permissions are specified via scp claim instead

enter image description here

How to get access token

function getAccessToken($tenantId, $clientId, $clientSecret){
    $guzzle = new Client();
    $url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
    $token = json_decode($guzzle->post($url, [
        'form_params' => [
            'client_id' => $clientId,
            'client_secret' => $clientSecret,
            'resource' => 'https://graph.microsoft.com/',
            'grant_type' => 'client_credentials'
        ],
    ])->getBody()->getContents());
    return $token->access_token;
}
Vadim Gremyachev
  • 57,952
  • 20
  • 129
  • 193
  • 1
    Ok thank you, i'll try that (I need and admin to grant access). – Romain Le Mercier Sep 09 '19 at 14:50
  • I got aprooval from the admin but I can't get access, I have a 403 forbiden now, I call it progress! – Romain Le Mercier Sep 10 '19 at 15:17
  • I don't understand the access configuration. First, I get the token using grant_type = client_credentials. Then I call https://graph.microsoft.com/v1.0/users/user@email.com/drive/items/###DOC_ID###/workbook/worksheets and I get 403 forbidden. If I understand @vadim correctly I need to change the credential request? Or first I get the acesstoken and then call a request to grant me access for this token? – Romain Le Mercier Sep 10 '19 at 15:34
  • @RomainLeMercier, the answer has been updated (demonstrates what permissions are required and how to validate access token) – Vadim Gremyachev Sep 10 '19 at 17:14
  • Sorry to ping you but you seems to know your stuff and I really don't, the more I google or read the doc, the more I'm lost... – Romain Le Mercier Sep 13 '19 at 08:58
  • @RomainLeMercier, just spotted in your example `body` parameter is utilized to perform post request , in GuzzleHttp (v 5.0 or above) `form_params` request option needs to be utilized instead(the updated answer contains an example on how to acquire access token) – Vadim Gremyachev Sep 14 '19 at 20:42
  • Yes I use Guzzle V5 and in the version the param needs to be "body", form_params came with V6 (and I can't update due to prestashop dependencies). In your exemple to get the access token I don't see any roles ou scp param to get permition. Is it not in this request I have to ask for it? Or is it an other request? Right now I have only two : 1/ get accen token 2/ get file content (where I have a 403 error). – Romain Le Mercier Sep 16 '19 at 07:08
  • @RomainLeMercier what file content? In your question, there is a mention about `me/drive/recent` endpoint only Can you be more specific and provide all the relevant details in your question, the way how you communicate at the moment make it difficult to assist you IMHO – Vadim Gremyachev Sep 16 '19 at 11:58