What is the .default scope for graph.microsoft.com - azure-active-directory

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.

Related

Azure Authentication - Access Token returning wrong AUD(00000003-0000-0000-c000-000000000000)

I'm trying to authenticate with API Management in Azure through OAuth. I've set up that piece fine.
However from the response, the aud(00000003-0000-0000-c000-000000000000) is invalid from the access token.
Any suggestions/ideas to get the accurate aud in access_token.
I tried to reproduce the same in my environment and got the results like below:
I generated the access token with the same aud as you and got the validation error:
I agree with juunas, To authenticate with API Management in Azure through OAuth, make sure to pass the scope while generating the access token.
I created an Azure AD Application, exposed an API and added scope like below:
Added API permissions like below:
To resolve the error, make sure to pass scope as api://AppID/.default.
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:api://ee1782a6-a994-4013-a396-XXXXX/.default
grant_type:client_credentials
A valid access token to access APIM will be generated like below:
To pass the particular scope from react app using MSAL you can make refer the below sample code:
auth: {
authority: "https://login.microsoftonline.com/common",
clientId: "ClientID",
postLogoutRedirectUri: RedirectURI
redirectUri: RedirectURI
validateAuthority: true,
navigateToLoginRequestUrl: true,
},
cache:
{ cacheLocation: 'sessionStorage',
storeAuthStateInCookie: true,
},
},
{
scopes: ['api://clientid/.default']
},
LoginType.Redirect
References:
OAuth 2.0 Authorisation with the Client Credentials Flow on Azure API Management by Paco de la Cruz
Connect React App with Azure AD using react msal by Ray
You have mistaken the values.
TL;DR: ignore "access token", obtain and read "id token" and verify that "aud" field is your client ID.
First you might obtain a single-use access code (likely something like 0.ABC). Optionally you could fetch open id token. "scope" must include "openid"
Then you can fetch actual open id token using the single-use code. "scope" must be "openid" again. Response might include:
access token - which can be anything including random number of characters, string, your full details or an JWT; I believe that Microsoft returns JWT which is meant to the "00000003-0000-0000-c000-000000000000" audience (meaning "only 00000003-0000-0000-c000-000000000000 can use it - ignore if you are NOT the one")
id token - which is an JWT and should contain your application ID (client ID) in the "aud" field
Always check the "aud" as this says who is the token created for. If it is not you - the token is not for you.

powerbi api authentication - wrong scope

I try to get the list of the datasets for a particular tenant, using:
https://api.powerbi.com/v1.0/myorg/datasets
I get then a 403 error, it seems that my access code is not suitable for this call.
I could get an access_code successfully but I assume that it has the wrong scope since the response states:
"scope": "openid profile email User.Read"
yet I granted the correct permissions in azure:
when trying to add in the scope in the authentication call: openid offline_access DataSet.ReadWrite.All then I get an invalid_grant error
Try openid profile email https://analysis.windows.net/powerbi/api/.default as the scope.
You can find this endpoint while adding the power bi permission from Azure Portal:

Can I get an id_token from Azure AD for my app?

Using the client_credentials flow in Azure AD, I am unable to retrieve an id_token for my app.
I am experimenting with the Azure AD OAuth/OpenID endpoints, and running into some questions.
I create a simple app with minimal config through the Graph API (a beta endpoint, but still). I have removed all the headers and anonymised in code snippets below:
curl -X POST \
https://graph.microsoft.com/beta/applications \
-d '{
"displayName": "App Name",
"passwordCredentials": [
{
"endDateTime": "2299-12-30T23:00:00Z",
"startDateTime": "2019-02-14T20:19:14.686691Z",
"secretText": "<SOME KEY>",
"displayName": "Client Secret"
}
]
}'
In the response from Azure AD, I get an appId:
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#applications/$entity",
"id": "<SOME GUID>",
"deletedDateTime": null,
"isFallbackPublicClient": null,
"appId": "<SOME GUID>",
...
This is enough for me to be able to retrieve an access_token from the v1 OAuth endpoint:
curl -X POST \
https://login.microsoftonline.com/tenant_id/oauth2/token \
-d 'client_id=appId&client_secret=secretText&grant_type=client_credentials'
Response:
{
"token_type": "Bearer",
"expires_in": "3600",
"ext_expires_in": "3600",
"expires_on": "1550220412",
"not_before": "1550216512",
"resource": "00000002-0000-0000-c000-000000000000",
"access_token": "<JWT access token>"
}
Since I didn't specify a resource in my call, I get the default Graph API resource.
Now, what I also would like to get is an id_token for my app. I have been able to get these tokens from other OpenID providers. However, the OpenID Connect Core spec. gives me reason to think that id_tokens are for end users only, not apps:
"The ID Token is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when using a Client, and potentially other requested Claims"
(From https://openid.net/specs/openid-connect-core-1_0.html#IDToken)
Adding resource=openid to the POST to the token endpoint above won't work, since openid is a scope, not a resource.
Switching to the v2 endpoints, I get access to a scope parameter. I can obtain an access token from there by setting scope=https://graph.microsoft.com/.default, explicitly requesting the access I got by default through the v1 endpoint.
However, setting the scope to for instance scope=https://graph.microsoft.com/.default openid does not give me an id_token for my app, and the access token looks identical to the previous call.
Trying just scope=openid gives me the following error from Azure AD:
AADSTS70011: The provided request must include a 'scope' input parameter. The provided value for the input parameter 'scope' is not valid. The scope openid is not valid.
All this combined leads me to believe that the OpenID providers I have used and have issued id_tokens through the client_credentials flow are breaking the spec, and that id_tokens can only be obtained for end users (using the authorization_code flow gives me an id_token from Azure AD for myself without any issues).
Is this a correct conclusion, or can I force Azure AD to issue id_tokens to apps as well as end users?
An id_token is issued when a user signs-in. Client credentail flows have no user, so no id_token is issued.
you'd need to use a flow like authorization code grant or openID connect to sign a user in. The response will have a id_token.
You cannot use the client credentials flow to get the id_token for app-only, it only returns the access_token.

Azure AAD and Graph API: Insufficient privileges to complete the operation

Context: I've a console app which wants to use Graph API to talk to AAD to check if a particular userId exists in the tenant or not.
I've been following the guidelines here: https://learn.microsoft.com/en-us/graph/auth-v2-service?view=graph-rest-1.0
I'm able to generate a token using this:
https://login.microsoftonline.com/common/oauth2/v2.0/token
client_id=x
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=x
&grant_type=client_credentials
But when I call the graph API I get this ERROR:
https://graph.microsoft.com/v1.0/users/12345678-73a6-4952-a53a-e9916737ff7f
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "x",
"date": "x"
}
}
}
My AAD App has all the permissions from:
1. Microsoft Graph
2. Windows Azure Active Directory
I tried changing the scope to
scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
But this is the error I get while generating token:
The provided value for the input parameter 'scope' is not valid. The scope https://graph.microsoft.com/user.read is not valid.
I've tried combinations of "User.Read", "User.Basic.Read", etc. but nothing works.
The most likely reason why this is not working is because the permission which you have configured your app registration to require have not actually been granted by an administrator of your organization.
In your code, your app is authenticating as an application only. There is no signed-in user involved, and it requires your app to use and keep confidential a key used to authenticate (the client_secret parameter).
In this scenario, requesting the scope https://graph.microsoft.com/.default is the correct approach. What you're saying to Azure AD is: "please provide an access token for all the application permissions this app has been granted". Requesting the scope https://graph.microsoft.com/User.Read is not the correct approach because there is no application permission with that name.
Does the app you created have delegated permissions or application permissions to that scope?
Most likely the former. Delegated permissions don’t apply to client credentials flow.

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

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

Resources