I am trying to use the create subscription API to open a subscription channel on a calendar's events such that we can receive updates when interviewers respond to the interview.
I have tried many variations to get this request to work:
I have gone through the oauth process to retrieve graph access tokens for a user with the following permission Scopes:
Mail.SendCalendars.ReadWrite.SharedUser.ReadBasic.AllUsing the access tokens with the above scopes, before attempting to create the subscription, I add an event with {eventId} to a shared calendar, let's say with the user relative id of {sharedCalendarId}.
Using the same access tokens to create the same Authorization header with permission scopes listed above, I consistently receive the same ExtensionError response. Below I will list the various permutations of request I have made to the graph API.
Urls Attempted
I have sent each permutation of the subscription POST requests to the following URLs:
https://graph.microsoft.com/v1.0/subscriptionshttps://graph.microsoft.com/beta/subscriptionsRequest Headers
Content-Type: application/jsonAuthorization: Bearer {authToken}Request Bodies Attempted
The changeType and notificationUrl, and expirationDateTime are the same for all requests.
I have tried 3 different variations on the resource string, and have tried the request with and without the clientState.
First I tried the fully identified resource and added clientState:
{
"changeType": "created,updated",
"notificationUrl": "https://{domain-with-valid-https-certs}/calendar/microsoft/notifications",
"resource": "users/{userPrincipalName}/calendars/{sharedCalendarId}/events",
"clientState": "{thisIsLimitedTo128Characters}",
"expirationDateTime": "2018-05-23T21:02:45.487Z"
}
Next, I abandoned clientState for the sake of narrowing down the problem and I used me instead of {userPrincipalName}:
{
...
"resource": "me/calendars/{sharedCalendarId}/events"
}
Then I abandoned the shared calendar to see if that was the problem and used a resource that's an example in the docs.
{
...
"resource": "me/events"
}
While I seem to receive the validation request to the notificationUrl provided (and the server responds appropriately) the request to create the subscription then responds with this kind of error:
{
code: "ExtensionError",
message: "Operation: Create; Exception: [Status Code: Forbidden; Reason: Forbidden]",
innerError: {
"request-id": "0d86a983-ea50-4226-905c-38f0e8f12308",
date: "2018-05-23T03:55:38"
}
}
What's confusing is that I am attempting to create this subscription on a calendar I have just successfully created or changed and event, so the 403 seems like it should not be related to access to the resource.
Are there specific permissions or scopes that need to be granted for us to successfully create subscriptions to a calendar's events? Is there a different API we should be using?
In order to subscribe to a resource, you minimally need read access to the resource. So for events, you would need Calendars.Read. Since you have more than that, you should be fine. (Reference)
I believe your problem is that you are not including expirationDateTime in the payload. This is a required property (documented here, arguably not the best place for this to be listed). Set it to a value equal to or less than the maximum for calendar, 4230 minutes (Reference).
Self-answer here for anyone having a similar issue who doesn't want to dig through comments.
After some debugging help from Marc LaFleur and Jason Johnston (thanks for the responses!), the answer to my specific question is "sort of".
No, there are no specific Subscriptions.* scopes, and they are not needed to create subscription channels.
But, quixotically, the POST /subscriptions creation endpoint requires more specific permission scopes than the resource itself.
In my example, the Calendars.ReadWrite.Shared permission does indeed allow my app to read and write events to the user's calendars and shared calendars, but I was unable to create a subscription channel for the same calendar.
Requesting the less permissive and more specific scope of Calendars.ReadWrite in addition to Calendars.ReadWrite.Shared solved my problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With