This post is a contribution from Manish Kumar, an engineer with the SharePoint Developer Support team
This post is an attempt to guide Developers in troubleshooting issues that they may come across when doing the development using
Microsoft Graph API and possible things to check to resolve those issues. Some of the approaches discussed would be common irrespective of the Office 365 resource (workload) being retrieved e.g. SharePoint list or Outlook mail.
- Have I registered my app correctly?
- First thing to check is whether you have an app designed to run in interactive mode or in unattended mode. This will give you clarity on whether you need to register the app as a native app or web app, and the permissions that you need to grant to the app. For example, if you create a Native app from the Azure AD app registration page, you would not see an option of adding Application permission to any API (like Microsoft Graph). The reason being that native apps are expected to be installed on devices and run in interactive mode and expected to have just Delegated permissions.
- Whether you intend to develop only for Azure AD organizations/accounts or for both Microsoft account and Azure AD accounts? This would determine the Azure AD v1.0 vs v2.0 endpoint usage and how the permission scopes are set. More reading here -
https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-compare.
And make sure you’re not running into any limitations associated with v2.0 endpoint -
https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-limitations.
- Have the permissions been set correctly?
When setting app permissions, there are couple of options – Delegated vs Application permission. You would use the Delegated permission when the app needs the permission on behalf of a user to certain resources that belong to the user. Useful in interactive scenarios. On the other hand, Application permissions have wider scope and are granted directly to applications without any user interaction. Useful in running background services.So, how to verify your app permissions?
Most of the time we run into issues where the call to Graph API resource returns 401 Unauthorized or Access Denied errors. First thing to check in such scenario is the permissions scope on the access token. Any JWT token decoder tool can be used for looking at the claims on the token. Or some of the Azure AD Authentication libraries may provide inbuilt functions for decoding the token.Examples of permission on the access token:- User access token permission scope (decoded using http://jwt.calebb.net):
The user token obtained with Delegated permissions, would also contain the user information in the claims.
For example,
name: "Manish Kumar",
upn: "Manish.Kumar@domain.onmicrosoft.com", - App-only access token permission scope (decoded using http://jwt.calebb.net):
- User access token permission scope (decoded using http://jwt.calebb.net):
- Has the admin granted consent to the app that have requested permissions that explicitly require admin consent?
All Application permissions require admin consent and there are some Delegated permissions too that require admin consent. So, if any of those permissions are added or changed, it’s important to grant the app admin consent first, before hitting the token endpoint. See ‘Get administrator consent’ section under https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service. - Why am I not getting refresh token for app-only access token (using Client credentials grant flow)?
We need to note that with the app-only scenario, in AAD, refresh token is not needed. The likely rationale is that app-only token retrieval is a one step process and when the access token nears expiry or expires, the app should hit the token endpoint to get a new access token. The refresh token is returned when the app is run in delegated mode with user interaction. In that case, it’s a two-step process to retrieve access token. The first step is to get authorization code and then to use that code to obtain the access token as the second step. In this scenario, having a refresh token helps avoid making two calls wherein the app can use the refresh token to get the access token directly in one call. - I’ve changed the app permissions in the registration portal, but I’m not getting the user consent prompt. Why?
This is likely because you have not added any new permission to the existing permission set for the application. The user consent prompt will be thrown for any new permissions that have been added to the app but not consented before. - Have you tried Microsoft Graph Explorer for emulating the calls?
Microsoft Graph Explorer allows you to explore the calls to the service with sample data as well by signing into your Microsoft account. One thing to note is that Graph Explorer (as of now) gets a user token for the account you signed-in. So, if you intend to test the calls made with app-only token, you’d have to consider using other REST clients. - What about the calls that can’t be made through Graph Explorer?
For those calls that can’t be made using Graph Explorer, you can use any REST client like Postman to make those calls manually. For authorization code grant flow, below are the steps:- Get authorization code from authorization endpoint
- Get access token from token endpoint
- Pass the access token to Authorization header along with the Graph API call.
Links:
https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_user
https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service - Have you looked at the known issues documentation for Graph API?
At times you may feel that you’re following all the steps but still not getting through. For example, using client credentials grant flow (with app-only token) to make call to retrieve group events but it fails with 401 Unauthorized error. Well, it is because retrieving group events is only supported for Delegated permissions as of now. Therefore, reviewing the knowns issues - https://developer.microsoft.com/en-us/graph/docs/concepts/known_issues is right place to start in such scenarios. - Is it a problem at SDK level or Graph API level?
There are multitudes of Graph API SDKs available for different dev platforms. At times it is possible that there is a problem with the SDK and it is not constructing the HTTP requests (GET/POST/others) correctly and hence the value is not returned as expected. To isolate the problem at SDK level, take a network capture (like Fiddler) and review the calls to make sure that it looks correct as per the documentation. Besides that, as noted in point (6), you can leverage Graph Explorer for reference, if that call is available there. - Is your app throttling the Microsoft Graph service?
Look at the response code for the calls made from your app for HTTP status code 429 for throttling confirmation. The app developer should design the app in a way that avoids throttling at first place and is able to identify and gracefully handle any throttling scenarios if it occurs. - Are you running the Beta version of the API?
The Beta version is only meant for testing purpose and subject to change. Therefore, not to be used in production. So, isolate whether the problem exists with just the Beta version or the generally available version (v1.0). - How to get help?
If it is a feature request, post it here -
https://officespdev.uservoice.com/forums/224641-feature-requests-and-feedback/category/101632-microsoft-graph-o365-rest-apis
For posting your queries, leverage the Stackoverflow forum for Microsoft Graph API https://stackoverflow.com/questions/tagged/microsoft-graph
This post is by no means exhaustive in nature. Besides, there are changes continuously made to improve the developer and end user experience with Office 365. Thus, calling for appropriate changes in troubleshooting approach.