Microsoft-graph-docs: Creating a subscription for a SharePoint List fails with 403 Forbidden when using application-only permissions

Created on 16 Apr 2020  Â·  34Comments  Â·  Source: microsoftgraph/microsoft-graph-docs

Under the application column, the permission Sites.ReadWrite.All is specified. But attempting to create a subscription with application-only permissions returns a 403 Forbidden error. Creating the subscription with the same request, but using Graph Explorer (delegated permissions) works correctly.


Document Details

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

sharepoint webhooks product

Most helpful comment

Certificates vs secret isn't related to multi tenant vs single tenant.

All graph operations support tokens generated using a certificate but some sharepoint operations don't support app tokens generated using a secret.

You should try to switch to using a certificate but I don't know how complex that is in PHP.

All 34 comments

Any updates on that? I´m having the same issue.

While we're waiting for the owner to respond, I do have a question for you. How are you obtaining the access token? Using client id + secret or using client id + certificate?

Good question 🙂
In my case, I can confirm I am using a certificate. In fact, I have never generated a client secret for this app.

ok thanks! Because I know that SharePoint APIs do require a certificate authentication for some operations when using an app-only flow. I'll let @JeremyKelley take it from here.

I'm using client id + secret, if it matters.
Edit: tried with certificate, same result

I get the same error. I've add Site.ReadWrite.All to my app registration and I am accessing my graph api via client secret. I have not yet tried using a certificate

@simondevries details for configuring a certificate are here, although it's unnecessarily complex since you can use keyvault to generate a certificate for you.

Same exact problem here, no answer anywhere? someone have a workaround?

I'm also experiencing the same issue unfortunately. I've tried acquiring tokens using both certificate and client secret with same result. Here is an excerpt from the token (generated using a certificate):
json{ "typ": "JWT", "nonce": "xxx", "alg": "RS256", "x5t": "xxx", "kid": "xxx" } { "aud": "https://graph.microsoft.com", "iss": "https://sts.windows.net/xxx", "iat": xxx, "nbf": xxx, "exp": xxx, "aio": "xxx", "app_displayname": "xxx", "appid": "xxx", "appidacr": "2", "idp": "https://sts.windows.net/xxx", "oid": "xxx", "roles": ["Sites.ReadWrite.All", "User.Read.All"], "sub": "xxx", "tenant_region_scope": "EU", "tid": "xxx", "uti": "xxx", "ver": "1.0", "xms_tcdt": xxx }

Could you please provide the following response headers corresponding to your request(s):

  • Date (in UTC, please)
  • request-id
  • SPRequestGuid (for requests made to OneDrive for Business)

Bumping the discussion here, are there request IDs available for the failing operations? We are unable to reproduce internally and without this information we can't really investigate further.

Thanks!

Thanks @JeremyKelley for the reminder. I had actually parked this project but I've got the old code up and running to get some output.

Request Uri:
https://graph.microsoft.com/v1.0/subscriptions

Request body:
{"changeType":"updated","notificationUrl":"https://<redacted>.azurewebsites.net/Trigger/ListSubscriptionNotify","resource":"sites/<redacted>.sharepoint.com,4ff19269-f6b0-41d1-b961-024d0a9bb212,8437e6b9-45f4-4e7b-804d-0c921eca79ba/lists/2c014d6d-7e3e-4841-a159-a04baa102434","expirationDateTime":"2020-07-25T19:07:27.9028664Z","clientState":"{\"ListSubscriptionId\":0}"}
Request headers:
Authorization: Bearer eyJ0eXAiO....<redacted>

Response body:

{
  "error": {
    "code": "ExtensionError",
    "message": "Operation: Create; Exception: [Status Code: Forbidden; Reason: Access denied. You do not have permission to perform this action or access this resource.]",
    "innerError": {
      "date": "2020-07-24T19:07:37",
      "request-id": "4b29703e-f6b9-4c77-9b9a-30f6d6143e44"
    }
  }
}

Response status code: 403 Forbidden

Response headers:

Cache-Control: private,
request-id: 4b29703e-f6b9-4c77-9b9a-30f6d6143e44,
client-request-id: 4b29703e-f6b9-4c77-9b9a-30f6d6143e44,
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Europe","Slice":"SliceC","Ring":"4","ScaleUnit":"005","RoleInstance":"AGSFE_IN_5"}},
Strict-Transport-Security: max-age=31536000,
Date: Fri, 24 Jul 2020 19:07:36 GMT

Any updates on this? I've exactly the same problem using client secret to create the token.

Request Uri:
https://graph.microsoft.com/v1.0/subscriptions

Request body:

{
    "changeType": "updated",
    "notificationUrl": "https://xxx/notifications/microsoft",
    "resource": "/drive/root",
    "expirationDateTime": "2020-08-08T10:20:57.163925Z"
}

Response body:

{
    "error": {
        "code": "ExtensionError",
        "message": "Operation: Create; Exception: [Status Code: Forbidden; Reason: Access denied]",
        "innerError": {
            "date": "2020-08-05T12:43:11",
            "request-id": "63275e4c-e297-4950-8398-bf7e6c4bb8c8"
        }
    }
}

Response headers:

{
    "cache-control": "private",
    "client-request-id": "7e2685a7-1cd6-5342-052f-963fbe7526b1",
    "content-length": "277",
    "content-type": "application/json",
    "request-id": "63275e4c-e297-4950-8398-bf7e6c4bb8c8"
}

Thats the decoded token:

{
  "typ": "JWT",
  "nonce": "",
  "alg": "RS256",
  "x5t": "",
  "kid": ""
}.{
  "aud": "https://graph.microsoft.com",
  "iss": "https://sts.windows.net/606f4517-9cad-43bb-973f-2647f76724be/",
  "iat": 1596630507,
  "nbf": 1596630507,
  "exp": 1596634407,
  "aio": "",
  "app_displayname": "",
  "appid": "",
  "appidacr": "",
  "idp": "",
  "oid": "",
  "roles": [
    "Sites.ReadWrite.All",
    "Files.ReadWrite.All"
  ],
  "sub": "",
  "tenant_region_scope": "",
  "tid": "",
  "uti": "",
  "ver": "1.0",
  "xms_tcdt": 1593517741
}

@baywet the failures appear to be in the Graph webhooks service; should investigation continue on the Graph side?

@chackman I looked into it and I'm indeed getting the same error in subscription creation.
However, if with the same token (app-only, w/ Sites.ReadWrite.All) on GET /drive/root and I'm getting the following error. My guess is that this is what's making subscription service fail, but subscription service is not translating the error properly. Can you look into it please?

{
  "error": {
    "code": "InvalidAuthenticationToken",
    "message": "CompactToken parsing failed with error code: 80049217",
    "innerError": {
      "date": "2020-08-05T17:37:05",
      "request-id": "2e2ea5f2-ada1-400e-a0ec-325cb6a460d1"
    }
  }
}

@baywet this looks like Graph rejected the token (so probably an auth question as opposed to webhooks); this was a request to the Graph service right?

this is GET https://graph.microsoft.com/v1.0/drive/root

Given the information that we have, this looks like a more general auth issue with Graph and does not appear to be a webhooks or SharePoint issue. Can someone on the Graph side pick up the investigation?

@chackman @baywet this may or may not be useful information, but I'll add it anyway:

My workaround was to create an app-only token for SharePoint, and create a webhook subscription directly via the SharePoint API. Which worked fine.

@chackman do we already have an ICM for that?

@baywet no we do not currently have an ICM

do you mind opening it? since it's a SharePoint permission issue on MS Graph? I think it'll be better if you drive the conversation here.

Here's a simplified code snippet of what I'm trying to achive using Laravel and Microsoft Graph SDK for PHP, maybe it helps

$response = Http::asForm()
    ->withHeaders([
        'Host' => 'login.microsoftonline.com',
        'Content-Type' => 'application/x-www-form-urlencoded'
    ])
    ->post("https://login.microsoftonline.com/" . config('oauth.microsoft.tenantId') . "/oauth2/v2.0/token",
        [
            'client_id' => config('oauth.microsoft.clientId'),
            'scope' => 'https://graph.microsoft.com/.default',
            'client_secret' => config('oauth.microsoft.clientSecret'),
            'grant_type' => 'client_credentials'
        ]);

$token = $response->json()['access_token'];

try {
    $graphResponse = (new Graph)
        ->setAccessToken($token)
        ->createRequest('POST', '/subscriptions')
        ->attachBody([
            'changeType' => 'updated',
            'notificationUrl' => 'https://xxx.ngrok.io/api/webhook/microsoft',
            'resource' => '/drive/root',
            'expirationDateTime' => Carbon::now('UTC')->addMinutes(4200)->toISOString()
        ])
        ->execute();
} catch (Exception $e) {
    ...
}

@stefanheimann you're using a client secret, not a certificate, so an error would be expected I think.

As I'm building a multi-tenancy application I don't think it's appropriate to use a certificate here. The app should also be usable for accounts outside of the organization I'm in. As far as I understood the concept, this wouldn't be possible using a certificate, right?

Certificates vs secret isn't related to multi tenant vs single tenant.

All graph operations support tokens generated using a certificate but some sharepoint operations don't support app tokens generated using a secret.

You should try to switch to using a certificate but I don't know how complex that is in PHP.

@chackman FYI another customer impacted by this https://stackoverflow.com/q/63261811/3808675

@baywet created an IcM

Even I get Operation: Create; Exception: [Status Code: Forbidden; Reason: Access denied] while trying to subscribe to /me/drive/root/ resource. I tried this in Graph Explorer.

EDIT: URL: https://graph.microsoft.com/v1.0/subscriptions

{
    "changeType": "updated",
    "notificationUrl": "https://my.notification.webhook/",
    "resource": "/me/drive/root/",
    "expirationDateTime": "2020-08-17T08:45:56.397732Z",
    "clientState": "CLIENT_STATE"
}

EDIT 2: I do receive the validation token for my webhook, every time I try to subscribe!

I was able to subscribe to Outlook message and it worked as expected...

Any chance that this will be fixed soon? Or should we prepare to build a workaround?

@mwiedemeyer a potential workaround is to subscribe with SharePoint directly. It's very similar, but bypassing Graph: https://docs.microsoft.com/en-us/sharepoint/dev/apis/webhooks/lists/create-subscription

Yes, I know. However I'm trying to use the new EventHubs feature (https://docs.microsoft.com/en-us/graph/change-notifications-delivery) and SharePoint does not support EventHub: notification urls. So that is not an option. Maybe I could switch to delegated permissions, but that will require to add an account to a lot of sites.

Azure Support have confirmed this should now be fixed. It began working in our tenant at 21:00 UTC yesterday.

Although it says fixed, I'm having this issue now too. Tried both in code and graph explorer. Ensured the scopes were correct. Any debugging I can provide to help troubleshoot?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aaronrogers picture aaronrogers  Â·  3Comments

RobinBreman picture RobinBreman  Â·  4Comments

findyoucef picture findyoucef  Â·  4Comments

abhatt29 picture abhatt29  Â·  4Comments

joostvdlinden picture joostvdlinden  Â·  4Comments