{
"changeType": "created",
"notificationUrl": "https://webhook.azurewebsites.net/api/send/myNotifyClient",
"resource": "me/mailFolders('Inbox')/messages",
"expirationDateTime":"2016-11-20T18:23:45.9356913Z",
"clientState": "secretClientValue",
"latestSupportedTlsVersion": "v1_2"
}
notificationUrl is your own API endpoint that Graph will send the notification to. It can be any public web HTTPS interface with a certificate issued by a Known CA. I suggest you check Use Change Notifications and Track Changes with Microsoft Graph Guide where Ngrok is used to expose an endpoint running on your local machine to accept MS Graph change notifications
Related
I'm trying to use the subscription feature of the MS graph API to listen to changes in calendars. My app has Calendars.ReadWrite permission to all users set up in Azure, and reading and writing calendar events works well for all users with the access token I've obtained for my app.
However, when calling the POST /subscriptions endpoint to subscribe to changes in one user's calendar, I get "Access to OData is disabled".
POST https://graph.microsoft.com/v1.0/subscriptions
{
"changeType": "created,updated",
"notificationUrl": "https://...my.endpoint...",
"resource": "users/someone%40somedomain.com/events",
"expirationDateTime": "2021-10-27T20:09:25.025Z",
"clientState": "foo"
}
This gives the following error:
"code": "ExtensionError",
"message": "Operation: Create; Exception: [Status Code: Forbidden; Reason: Access to OData is disabled.]"
According to the documentation, this endpoint requires only the same permissions as the subscribed entity, which in my case would be Calendars.Read.
What could be causing this? How do I debug this further to understand why I'm getting this error?
I found some pages suggesting to use PowerShell to modify an ApplicationAccessPolicy. Is this relevant, and is it only possible through PowerShell? Why would there be an obscure policy accessible only through PowerShell and not through the Azure console?
Turns out this was due to the user for whom I was trying to subscribe wasn't in the proper security groups, which were mapped to application policy.
So it had nothing to do with the permissions of my client, but rather of the target user I was trying to subscribe to.
My app uses delegated user access tokens to interact with the MSFT graph api. They have the Calendars.ReadWrite.Shared permission. When making requests to https://graph.microsoft.com/v1.0/subscriptions in production with the following request body:
{
"changeType": "created,updated,deleted",
"notificationUrl": <https_app_notification_url>,
"resource": "/me/calendars/<calendar_id>/events",
"expirationDateTime": (datetime.now(timezone.utc) + timedelta(minutes=4200)).isoformat(),
"clientState": <a_crypto_random_string>
}
almost every time the response is an error with the following in the response body:
[Status Code: Forbidden; Reason: Access is denied. Check credentials and try again.]
The most recent occurrence of this error had the following innerError in the response:
{'date': '2020-05-13T20:58:09', 'request-id': '1448e490-9e45-4a08-9aab-dd9c996c18db'}
This happens even when trying to subscribe to the user's own default calendar.
The strange thing is that the exact same code, when run on my local machine and tunneled to the web via ngrok to expose my app's notificationUrl endpoint, is able to consistently get a 201 from the MSFT's subscriptions endpoint.
I've checked the system time on the server with the date command and there's less than 1 second difference between my local machine and the server. So I don't think the expirationDateTime field is the issue; it's got 30 minutes of buffer built in as I believe the max according to the docs is 4230.
Should I be requesting additional permissions in the oauth scopes for the user access tokens? The docs say that Calendars.Read is enough so I would've thought Calendars.ReadWrite.Shared would do it. Or am I missing something else?
You need Calendars.Read as outlined in the documentation to subscribe to the current user's calendar.
I am using Client application (Client credentials grant) with defined permissions Application.ReadWrite.All and User.ReadWrite.All (both are included in Bearer token) to change accountEnabled to false for a user, like here:
{
"accountEnabled": false,
"city": "C234",
"country": "AFG",
"displayName": "Steve Rogers",
"givenName": "Steve",
"jobTitle": "Azure",
"mailNickname": "steve",
"postalCode": "Z345",
"streetAddress": "S123",
"surname": "Rogers",
"userPrincipalName": "steve#***.onmicrosoft.com",
"id": "aec...278",
"mobilePhone": null
}
But all requests ends with 403
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "e7a...e42",
"date": "2019-04-10T08:21:12"
}
}
}
Documentation doesn't contain any restrictions or requirements of additional permissions. Is it a bug in Graph API?
Thank you guys, I was able to find a root cause - you can't disable a user in Admin role. I was unlucky and select several users and all of them were in Admin role.
https://learn.microsoft.com/en-us/graph/permissions-reference#remarks-2
On my side, it works. The following is my process:
Use the client credential to get bearer token:
To parse the bearer token:
2. Use this bearer token to call ms graph api:
Check the disabled user in the azure portal:
No Its mandatory to grant permission for accessing this API on azure portal.
Make sure you have set required permissions access on portal of your calling API. Also user must not have any directory role in portal.
If you are admin in your AAD, You could grant permission for
users in organization by click Grant permission button.
Then you could use your code (client credential flow to get the
token) and query users information . If you check the claims in
access token issued by azure ad , you could find Directory.Read.All
permission in roles claim
In given reference same thread answered there You could refer here .
Note For Client Credentials code example you could check here
If you still have any query feel free to ask in comment. Thank you.
I am having trouble starting a Microsoft Graph webhook subscription (for a mailbox in particular). When initiating the subscription it appears as though Microsoft accepts all of the parameters I am sending to configure the subscription but fails the total subscription because it is receiving a non 2xx response from the endpoint I have configured.
The reason my endpoint is sending a 401 back to Microsoft is because their POST that includes the subscription validation token is missing the clientState.
I am using the clientState key-value pair to authenticate all the communication between Microsoft and my endpoint. If my endpoint does not see the correct clientState it will return a 401.
Any ideas on what I might be missing or if I should go about this in a different way? In my opinion allowing my endpoint to accept unauthenticated GET/POST's is not an option.
Example request body using POST method including the API key in the header:
{
"changeType": "created",
"clientState": "testClientState",
"resource": "users/<UserName>/messages",
"expirationDateTime": "2017-08-10T10:24:57.0000000Z",
"notificationUrl": "<EndpointURL>"
}
Error Returned from Microsoft:
"error": {
"code": "InvalidRequest",
"message": "Subscription validation request failed. Must respond with 200 OK to this request.",
"innerError": {
"request-id": "adf7fc7b-6b14-4422-8526-c1391be8dd27",
"date": "2017-08-07T16:24:59"
}
}
I understand everything to work as intended until my endpoint is sent the validation token because I receive the validation token but my endpoint rejects it because it is missing the client state.
Endpoint Log Snippet:
queryStringParameters": {
"validationToken": "<ValidationToken sent by Microsoft>"
}
I am basing my API endpoint logic off of some of Microsoft's developer guides. For the subscription creation in particular I am using this guide.
It appears this question was also asked but not answered on GitHub.
I represent Microsoft Graph Web hooks team ...
We verified your request in our MS Graph Service logs and confirmed that it was failed at Subscription validation phase because of HTTP status code='Unauthorized' from your endpoint ... Up to this everything is correct per your observation ...
By design, MS Graph Web hooks do not send the clientState header as part of the Subscription validation request. Please do not expect for this header during the subscription validation.
More information
You would have expected to receive the clientState as part of the validation request header because Office365 graph sends it https://msdn.microsoft.com/en-us/office/office365/api/notify-rest-operations. Office 365 Graph different from MS Graph ...
There are some document improvements observed with this question at https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/subscription_post_subscriptions ... Example Publisher Notification Payload, which is after successful subscription is mentioned together with the Subscription validation … We fixed those.
I think I have sort of the same problem as Microsoft Graph Subscriptions - Method not Allowed and the question is answered and there is this comment Microsoft Graph Subscriptions - Method not Allowed
Request https://graph.microsoft.com/v1.0/subscriptions
{
"changeType": "created,updated,deleted",
"notificationUrl":"https://c5e719ba.ngrok.io/api/ms/watch",
"resource": "me/events",
"expirationDateTime":"2016-12-07T02:23:45.9356913Z",
}
Response Header
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/json
Server: Microsoft-IIS/8.5
request-id: 9bd7a103-5ec0-4ed5-b20d-f8fb4cc75b88
client-request-id: 9bd7a103-5ec0-4ed5-b20d-f8fb4cc75b88
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Europe","Slice":"SliceA","ScaleUnit":"000","Host":"AGSFE_IN_4","ADSiteName":"DUB"}}
Duration: 261.5354
X-Powered-By: ASP.NET
Date: Tue, 06 Dec 2016 23:11:45 GMT
Response
{
"error": {
"code": "",
"message": "Exchange Online resources are not supported for MSA requests.",
"innerError": {
"request-id": "9bd7a103-5ec0-4ed5-b20d-f8fb4cc75b88",
"date": "2016-12-06T23:11:46"
}
}
}
But I'm not sure what should I do to make it work, I'm not using azure, but it seems that if I use Azure Active Directory B2C it should work, if this is what I really must do I think it's a hassle not being able to use all the microsoftgraph without using an azure service. (I can live without getting the profile photo This operation in version 1.0 supports only a user's work or school mailboxes and not personal mailboxes.).
I don't have an office365 account so I don't know if this won't be a problem if the user that uses my application sign in with an office 365 account.. because if it works with a home/commercial account I could verify if the account it's from MSA or home/commercial as a workaround I could do something like this https://github.com/microsoftgraph/msgraph-sdk-android/issues/26 and if I know that it's an MSA account I could ask the user to use another account in order to use the app...
So the question is: in order to make it work with a MSA (live) account do I've to use Azure Active Directory B2C?
Edit: Subscriptions for MSA (Live accounts) can now be created on the graph "beta" version for "me/messages" and "me/contacts".
We also support such MSA/live subscriptions for OneDrive resources like "me/drive/root".