"One or more scopes are not compatible with each other" error when retrieving access token for the - azure-active-directory

I have an app that integrated with Outlook, Calendar via the Azure AD REST API v.2. I have tried to use the incremental and dynamic scopes to "upgrade" the user's token so that the app can access OneDrive as well, (so the user could directly upload her email attachments in her cloud).
The authorization code retrieval redirects went well and the user is asked for the additional scope after login (files.readwrite). However, on step 2 when I try to obtain the access token I get the following error:
System.Exception: Acquire token by authorization code returned BadRequest:
{
"error": "invalid_scope",
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. One or more scopes in 'https://outlook.office.com/mail.readwrite https://outlook.office.com/mail.send https://outlook.office.com/contacts.readwrite https://outlook.office.com/calendars.readwrite https://outlook.office.com/people.read files.readwrite' are not compatible with each other.\\r\\nTrace ID: b02fa0bf-6e86-4156-81e8-294dbc851500\\r\\nCorrelation ID: 3697bd18-554c-47e6-81cc-de3c47780fc9\\r\\nTimestamp: 2018-02-01 15:26:10Z",
"error_codes": [
70011
],
"timestamp": "2018-02-01 15:26:10Z",
"trace_id": "b02fa0bf-6e86-4156-81e8-294dbc851500",
"correlation_id": "3697bd18-554c-47e6-81cc-de3c47780fc9"
}
Or this error:
System.Exception: Acquire token by authorization code returned BadRequest:
{
"error": "invalid_request",
"error_description": "AADSTS700022: The provided value for the input parameter scope is not valid because it contains more than one resource. The scope https://outlook.office.com/mail.readwrite https://outlook.office.com/mail.send https://outlook.office.com/contacts.readwrite https://outlook.office.com/calendars.readwrite https://outlook.office.com/people.read files.readwrite is not valid.\\r\\nTrace ID: 9781d206-11b3-46c8-b972-8c4e77641c00\\r\\nCorrelation ID: 7e63af89-6e95-45f4-abaa-8f32051fb9ef\\r\\nTimestamp: 2018-02-01 15:36:32Z",
"error_codes": [
700022
],
"timestamp": "2018-02-01 15:36:32Z",
"trace_id": "9781d206-11b3-46c8-b972-8c4e77641c00",
"correlation_id": "7e63af89-6e95-45f4-abaa-8f32051fb9ef"
}
I assume I can't use the same token for both Outlook and OneDrive access because they are "different resources", one being part of the Office 365 and the other in Microsoft graph, however, I struggle to find a comprehensive list of which resources are compatible with which in here (https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-scopes).
My question is, does this mean that I will need to maintain 2 different tokens (my app uses the offline scope to refresh the token) for OneDrive and Outlook?
Also is there a difference between OneDrive for a personal account and OneDrive for a business accounts (which I think is the same as Sharepoint)? When working with outlook I can use the same code for outlook.com and Office365 emails, but I am not sure this is the case when it comes to working with files.
With the Google APIs it's quite simple to just add the Google Drive (or any other API) scope to your Gmail access scopes, but I guess that's not the case with the Microsoft APIs.
Thanks

Yes you will need two tokens. As juunas said in his comment, the problem is the audience, or the aud parameter in the token. You're asking for scopes that apply to two different audiences: https://outlook.office.com and https://graph.microsoft.com.
The good news is that these two APIs do have overlapping scopes, and Azure AD will allow you to use a refresh token issued for Graph to get a token for the Outlook API. So here's what I suggest (assuming you're doing authorization code flow)
Do your authorization request using Graph scopes:
mail.readwrite
mail.send
contacts.readwrite
calendars.readwrite
people.read
files.readwrite
Do a token request with grant_type=authorization_code using those same Graph scopes. This gets your Graph token + refresh token.
Do a token request with grant_type=refresh_token using the refresh token from previous step, but this time with ONLY the Outlook-applicable scopes, qualified for https://outlook.office.com. This gets your Outlook token.
https://outlook.office.com/mail.readwrite
https://outlook.office.com/mail.send
https://outlook.office.com/contacts.readwrite
https://outlook.office.com/calendars.readwrite
https://outlook.office.com/people.read

Related

SharePoint Access token has two different scope values for tenants

when I decode SharePoint access token for Tenant A and B it shows as below
for the tenant A
"scp": "AllSites.FullControl User.Read User.ReadBasic.All"
for the tenant B
"scp": ".1f7f4061-caa1-44c4-b29a-6d877e9a5211"
are there any possible reasons to this kind of result for different tenants where i am expecting Teanat A result.
my token request call is similar to this
{ "grant_type", "authorization_code" },
{ "client_id", azureConfig.ClientId },
{ "client_secret", azureConfig.ClientSecret },
{ "scope", "https://123435350365.sharepoint.com/.default"},
{ "redirect_uri","url" },
{ "code", code }
I tried to reproduce the same in my environment and got the scopes successfully in both tenants.
I used the below parameters for both the tenants and got the access token for SharePoint successfully:
After decoding the token, I got the scope for both tenants successfully like below:
Please check the scope you are giving for Tenant B and verify whether your tenant has access to SharePoint API or not.
After decoding the token for Tenant B please check the aud and iss claims are valid or not.
Please note that value for the SharePoint Online Tenant Id may vary for each Tenant.
Make sure if you are giving permissions for Microsoft Graph then change the scope to https://graph.microsoft.com/.default.
If still the issue persists, try to raise Azure Support Ticket.
You can refer the below links to get some pointer to resolve the issue:
azure - SharePoint online OAuth2 token invalid_scope - Stack Overflow
How to access SharePoint Online data using Postman - REST API and Bearer token

Access Token through Azure Active Directory for Graph API ends in Property Error

I'm trying to call the Graph API: https://graph.microsoft.com/v1.0/me/sendMail.
I run the query successfully with the Graph Explorer, where I gave my user the Mail.Send permission. And if I use the Access Token from the Graph Explorer in Postman it works too.
But if I use my own Access Token which I create from calling the Azure Active Directory App in ends in this error:
{
"error": {
"code": "RequestBodyRead",
"message": "The property 'subject' does not exist on type 'Microsoft.OutlookServices.Message'. Make sure to only use property names that are defined by the type or mark the type as open type. REST APIs for this mailbox are currently in preview. You can find more information about the preview REST APIs at https://dev.outlook.com/.",
"innerError": {
"date": "2021-12-23T12:47:23",
"request-id": "cbb00b85-295b-45e2-abc7-f064ec52f994",
"client-request-id": "cbb00b85-295b-45e2-abc7-f064ec52f994"
}
}
The body in the message is the same, I just changed the Access Token from the Graph Explorer to the one I created. The Access Token is created through a POST Request to:
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded
client_id=535fb09-9f3-476-9bf-4f126479986
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=qWgdYAmab0YSkuL1qPX
&grant_type=client_credentials
I checked both Tokens with https://jwt.io/ if they vary in some way. The only thing which was odd was the parameter "aud" for Audience. The value in my Token was different than the one from the Graph Explorer, but I don't know if I can change that.
The Azure Active Directory App does have the necessary permissions, also with Admin consens.
enter image description here
Help is much appreciated.
You have given Delegated permissions to the application which allow your app to call an API on behalf of a user.
But you authenticate using only application credentials where no user is involved.
In that case only Application permissions apply.
You either need to grant the "Send mail as any user" Application permission (and use /users/user-id instead of /me), or you need to change how you authenticate such that it involves a user at some point of the process.

What is the .default scope for graph.microsoft.com

I can use a service principal to get an access-token from https://graph.microsoft.com but when I try to get a token for https://graph.microsoft.com/.default I get the following error.
What is possible impact if my token was issued without this scope?
Get Token request returned http error: 400 and server response:
{
"error": "invalid_resource",
"error_description": "AADSTS500011: The resource principal named https://graph.microsoft.com/.default was not found in the tenant named 4c000000-0000-0000-0000-0000000000. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
Trace ID: 00-00-00-00000
Correlation ID: 00-00-00-000
Timestamp: 2020-08-06 00:17:31Z
"error_codes": [ 500011 ],
"timestamp": "2020-08-06 00:17:31Z",
"trace_id": "d301a1cb-8feb-44e0-8b04-e463dd8d5b00",
"correlation_id": "92947479-d924-49fd-8e29-1d7cbe70d289",
"error_uri": "https://login.microsoftonline.com/error?code=500011"
}
In case anybody else wonders what the /.default scope is all about you can check out this Microsoft doc:
The /.default scope is built in for every application that refers to the static list of permissions configured on the application registration.
So basically, the /.default scope infers the permissions from the according application.
I noticed that you use the v1.0 endpoint to get the access token. It generally uses Resource as the request parameter.
For v1.0 endpoints, there is generally no need to use the /.default scope,you need to add the /.default scope only when you use the v2.0 endpoint to get the token.
So you can use this token with confidence,this has no impact.

Azure Active Directory Authorization Token Has Expired

We are working on a custom connector for Power Apps. This connector basically uses post, get, patch, delete methods of the Dynamics Rest API. For authentication, we are using AAD as mentioned.
We are writing swagger JSON and uploading the file to create/update the custom connector, after which we have to provide CRM URL, Client ID, and Client Secret.
Everything was working smoothly until the custom connector started throwing error that the authorization token has expired.
{
"status": 400,
"source": "https://unitedstates-002.token.azure-apim.net:443/tokens/unitedstates-002/-5Ftest-20final-5Fc8793734b9d234d8-5F1ae6317311eb737e/a6bf39bb183d4f89870ba39642194dbe/exchange",
"message": "Error from token exchange: Bad authorization token. The access token has expired."
}
This error went away after we recreated the custom connector using the same swagger JSON without any change.
How can we avoid this error without needing to recreate the connector every time? Is there anything we are missing regarding to AD Tokens?
You can set the token lifetimes as per the documentation.
Please see here for more information:
Configurable token lifetimes in Azure Active Directory
Edit: This is apparently being deprecated May 1, 2020, but you should call for a refresh token if the token you currently have has expired.

How to solve "NoPermissionsInAccessToken" returned by Microsoft Graph when reading calendar or sending mail

Within our department we have a Classic ASP website that has been using our corporate Google accounts for authentication and to insert events into our Google Calendars. The organisation has just switched from Google to Office 365 and I'm trying to switch the code to use Outlook instead - with no success.
I can use the access token to GET https://graph.microsoft.com/v1.0/me and see the basic profile, but if I try to read calendar events or send an e-mail I see the message:
"error": {
"code": "NoPermissionsInAccessToken",
"message": "The token contains no permissions, or permissions can not be understood."
I created an Azure account with my personal Microsoft account and added an application. I added my colleagues and my corporate account as guest users. I set the permissions required and did the admin consent thing:
I then followed the steps on this page.
I first visit https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize, including the following query items:
client_id={client id}
response_type=code
redirect_uri={our URL}
response_mode=query
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={number}
This returns a "code", which I send to https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/token, including:
grant_type=authorization_code
client_secret={client secret}
client_id={client id}
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
state={same number as above}
redirect_uri={same URL as above}
code={code returned from /authorize}
This returns the id, access and refresh tokens. If I decode the access token using https://jwt.ms/, it seems to contain the appropriate audience and scope:
"aud": "https://graph.microsoft.com"
"scp": "Calendars.ReadWrite email Mail.Send openid profile User.Read"
...although I notice that there is no "roles" entry, which I see in some of the documentation. Is that an issue?
I then send the access token to https://graph.microsoft.com/v1.0/me with the following headers:
"Authorization", "Bearer {access token}"
"Host", "graph.microsoft.com"
"Content-Type", "application/json"
"Prefer", "outlook.timezone Europe/London"
That will return my e-mail address, etc., but if I change the URL to anything else, such as /me/photo/$value, /me/calendar/events, or try to send an e-mail I'm told that there are no permissions in the token.
I see that there are other similar questions, but they are mostly for the client_credentials flow (I'm not sure that makes any difference), and none of the answers has helped me resolve my problem.
Can someone please let me know if I've obviously missed anything - or I'm going about this in the wrong way to access Graph data on the client side? It seemed so straightforward with Google, but I'm finding the Microsoft documentation and examples a bit less detailed.
Adding guest users is meaningless.
What you have done is Admin consent for the Azure AD with your personal Microsoft account.
What you actually need to do is Admin consent for the target Azure AD/ O365 tenant.
Construct a consent link as following:
https://login.windows.net/{tenant ID of the target Azure AD}/oauth2/authorize?response_type=id_token&client_id={client ID}&redirect_uri={reply url}&response_mode=form_post&nonce=a4014117-28aa-47ec-abfb-f377be1d3cf5&resource=https://graph.microsoft.com&prompt=admin_consent
Access it in a browser and log in with an admin account of target Azure AD.
Another issue is that you are using Get access on behalf of a user. So you have to assign Delegated permissions rather than Application permissions in the Azure AD app.

Resources