InvalidAuthenticationToken error using msal and graph api from sharepoint - sharepoint

I am using the example msal-react to authenticate and consume sharepoint services using their graph api, create an application on AAD with delegated permissions.
I am assigning the scopes "https://mytenant.sharepoint.com/.default" and I get the following error code: "InvalidAuthenticationToken" message: "Access token validation failure. Invalid audience." check the token I get on the JWT.io page .
Thank you very much for your support

You are using the graph API to perform CRUD operations for SharePoint sites, so you should get an access token for the graph API instead of the SharePoint REST API.
So please change your scope to: https://graph.microsoft.com/.default.

I tried to reproduce the same in my environment via Postman and got below results:
I registered one SPA application and added SharePoint API permissions like below:
I generated access token via Postman with below parameters:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
client_id:appID
grant_type:authorization_code
scope: https://mytenant.sharepoint.com/.default
code:code
redirect_uri: https://jwt.ms
code_verifier:S256
Response:
When I decoded the token, it has SharePoint as audience and scp claim as below:
I got the same error as you when I used above token to call SharePoint from below graph API call:
GET https://graph.microsoft.com/v1.0/sites/<siteID>/lists
Response:
To resolve the error, assign Microsoft Graph API permissions for SharePoint like below:
Now, generate the access token again by changing the scope to https://graph.microsoft.com/.default as suggested by #Carl Zhao like below:
POST https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
client_id:appID
grant_type:authorization_code
scope: https://graph.microsoft.com/.default
code:code
redirect_uri: https://jwt.ms
code_verifier:S256
Response:
When I decoded the above token, I got Microsoft Graph as audience and scp claims are as below:
When I used above token to call SharePoint site lists from below graph API call, I got the results successfully like below:
GET https://graph.microsoft.com/v1.0/sites/<siteID>/lists
Response:
Note that, your token audience should be https://graph.microsoft.com while making graph calls and scp claim should contain Microsoft graph permissions.

Related

User unauthorized though the token is correct

I'm trying to integrate D365FO with a third party application, I was able to do the proper setup and register my app, fetch the Token as shown below:
I used the resource as the link for D365FO at the development machine, which is https://usnconeboxax1aos.cloud.onebox.dynamics.com/ and read the D365FO data as shown below:
I want to change the login methid, so I do login on behalf of the user, using the password, so I Disabled thesecurirty details at Azure (based on this), as below:
And got teh token of the loged user successfult as below:
But once I tried fetching the same data which I was able to fetch before, I got 401 unauthorized, though I'm loggin in using the Admin account:
The error 401 Unauthorized usually occurs if you make calls to the resource with invalid audience.
When you generate the access token with scope as user.read openid profile offline_access, audience will be Microsoft Graph that won't work with D365FO.
I tried to reproduce the same in my environment via Postman and got below results:
I registered one Azure AD application and added same API permissions like below:
Now I generated tokens with grant type as password by including same parameters as you like below:
POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token
client_id: <appID>
client_secret: <secret>
scope: user.read openid profile offline_access
grant_type: password
username: admin#xxxxxxxxx.onmicrosoft.com
password: xxxxxxxxxxx
Response:
You can decode the above access token by pasting it in jwt.ms to check the audience.
When I decoded the access token, I got aud claim as 00000003-0000-0000-c000-000000000000 (i.e, Microsoft Graph) like below:
If you use this token to read D365FO data, you will get 401 Unauthorized error as audience is invalid.
To resolve the error, you need to generate access token with resource value as base URL of your D365FO instance by making below changes:
POST https://login.microsoftonline.com/organizations/oauth2/token
client_id: <appID>
client_secret: <secret>
resource: <base URL of your D365FO instance without the trailing '/'>
grant_type: password
username: admin#xxxxxxxxx.onmicrosoft.com
password: xxxxxxxxxxx
In your case, value of resource parameter should be https://usnconeboxax1aos.cloud.onebox.dynamics.com
This token will have audience same as your D365FO root URL. To confirm that, you can decode it in jwt.ms. If you use this token to read D365FO data, it will work!
Reference:
Test services by using third-party utilities - Finance & Operations | Dynamics 365 | Microsoft

401 unauthorized: Access token validation failure calling Sharepoint

My goal is to get the list of sites with their web URL from REST API. I created one application in my tenant by granting it SharePoint API permissions.
I received the access token with client_credentials flow:
POST https://login.microsoft.com/864cc7c2-e44a-4a7e-bc1a-42b37ca38e66/oauth2/v2.0/token
client_id - 3affdc0e-04b4-495f-9346-7f5beda9c5ce,
grant_type - client_credentials,
client_secret - xxxxxx,
scope - https://< mytenant >.sharepoint.com/.default
But the issue is when I use that token to call the API. When I pass the Bearer token to call API, it's giving 401 unauthorized error like this:
{ 'error': { 'code': 'InvalidAuthenticationToken', 'message': 'Access token validation failure. Invalid Audience. ' } }
I think I messed up somewhere but don't know where in particular. Can anyone help me out?
But if I call the same in Microsoft Graph, I'm getting what I want which is very strange.
I tried to reproduce the same in my environment via Postman and got the below results:
I created an Azure AD application and granted SharePoint permissions like this:
I generated the access token with same parameters as you like below:
POST https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/token
Response:
When I tried to get the list of sites with their web URLs using below query, I got the same error:
GET https://graph.microsoft.com/v1.0/sites?$select=webUrl,siteCollection
Response:
To resolve the error, you need to do changes like below:
Make sure to grant API permissions for Microsoft Graph instead of SharePoint like below:
Change the scope as https://graph.microsoft.com/.default to get access token like below:
Using the above token, I got the list of sites with their web URLs successfully like below:
Reference:
List sites - Microsoft Graph v1.0 | Microsoft Docs
You can't use the token of the SPO api to call the graph API endpoint, you should call the SPO api endpoint to list the websites:
GET https://{tenant-name}.sharepoint.com/_api/v2.0/sites

Azure AD me profile

I have error "Access token validation failure. Invalid audience."
For application set api permissions to offline_access, openid, profile, User.Read.
User start auth, go to MS auth site, ask about login, password and grand.
After exchange code to access token i well receive
{'token_type': 'Bearer', 'scope': 'offline_access openid profile User.Read', 'expires_in': '3906', 'ext_expires_in': '3906', 'expires_on': '1653988700', 'not_before': '1653984493', 'resource': 'my_azure_client_id', ....}
Then i try get profile for current user with this access token.
As result i have error "Access token validation failure. Invalid audience."
Help pease)
UPDATE
Configured permissions
The reason behind getting that error is because your token has wrong audience.
Please check what token you are using to call Graph API.
I tried to reproduce the same in my environment.
If you are using ID Token instead of Access Token, you may get error like below:
To know whether you are giving access token or id token, decode it in JSON Web Tokens - jwt.io.
For access token, aud claim will be "https://graph.microsoft.com" or "00000003-0000-0000-c000-000000000000"
For id token, aud claim will be "your_app_client_id"
Choose the access token carefully with aud as "https://graph.microsoft.com" while calling Microsoft Graph API:
To get profile for current user, you can make use of below query:
GET https://graph.microsoft.com/v1.0/me
I got the profile successfully using access token like below:
Replace your scope with https://graph.microsoft.com/.default while generating access token to avoid confusion.
Reference:
oauth 2.0 - Microsoft Graph API: Access token validation failure. Invalid audience - Stack Overflow
UPDATE:
In order to get authorization code, make the request by changing scope like below:
https://login.microsoftonline.com/your_tenant_id/oauth2/v2.0/authorize?
client_id=your_client_id
&response_type=code
&redirect_uri=xxxxxx
&response_mode=query
&scope=https://graph.microsoft.com/.default
&state=12345

How to query the Sharepoint REST api (not the Graph api) using an Azure AD registered application?

I have a web application registered in Azure AD and have it working with the Graph API. But I would like to be able to instead query the Sharepoint REST API.
I have added the sharepoint delegated permission scope "AllSites.Read" to my application (in addition to the Graph API scopes that I was using before) and request this scope (in addition to the other delagated msgraph scopes) when I get the oauth token from the user. I successfully get the token, using https://login.microsoftonline.com/common/oauth2/v2.0 for the authorization/token calls, but am unable to make a successful query:
My query looks like client.get(f"https://{tenant}.sharepoint.com/_api/web/lists") where tenant is the tenant of the particular user who's token I am using.
The error I get looks like {'error_description': 'Invalid issuer or signature.'} with reason="Token contains invalid signature.";category="invalid_client"' in the header of the response.
I am able to query the Graph api, but would like to also be able to query the Sharepoint REST api, because the Graph api is is insufficient for my actual use case, which will be to get Sharepoint groups (Graph api does not give sharepoint groups when I ask for groups, only Office 365 and Azure AD groups).
Update:
The permissions I've set on the app:
I have not added any scopes in Expose API, I don't know if I need to. I did not need this part to have it working with Graph API.
Lastly I'll mention that in Postman, controlled environment purely with this as the request, with OAuth 2.0:
Auth URL: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
Access Token URL: https://login.microsoftonline.com/common/oauth2/v2.0/token
client_id
client_secret
Scope: AllSites.Read
I get a token successfully, with all the roles, although it still doesn't give me access to https://<tenant>.sharepoint.com/_api/web/lists. I get the following error:
"error": {
"code": "-2147024891, System.UnauthorizedAccessException",
"message": {
"lang": "en-US",
"value": "Access denied. You do not have permission to perform this action or access this resource."
}
}
}
which admittedly is probably a step forward from the invalid client error I was getting before, but still quite stuck.
I was able to get this to work in Postman:
OAuth 2.0
Grant Type: Authorization Code
Auth URL: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
Access Token URL: https://login.microsoftonline.com/common/oauth2/v2.0/token
Client ID: <client_id>
Client Secret: <client_secret>
Scope: https://<tenant>.sharepoint.com/AllSites.FullControl
The token I get back has all of the permissions that I set on the application, including the Graph API ones and the Sharepoint scopes that I did not request in the Scope parameter of the auth request:
"scp": "AllSites.FullControl AllSites.Read Directory.Read.All Files.Read.All Group.Read.All MyFiles.Read Sites.Read.All Sites.Search.All User.Read User.Read.All", which was a little surprising.
A key point was setting the tenant url in the scope so that the aud parameter in the token comes back for the right tenant. It was coming back before configured for the resourceAppId associated with the Graph permissions (00000003-0000-0000-c000-000000000000), rather than the Sharepoint permissions. This way, aud got set to https://<tenant>.sharepoint.com and I was able to access https://<tenant>.sharepoint.com/_api/web/lists.
You can try to get the acccess token in PostMan for a testing purpose.
Callback URL: https://www.getpostman.com/oauth2/callback
Auth URL : https://login.microsoftonline.com/common/oauth2/authorize?resource=https://<tenant_name>.sharepoint.com
Access Token URL : https://login.microsoftonline.com/common/oauth2/token
Client ID : <Application_ID>
Client Secret : <KEY>
Grant Type : Authorization Code
Will pop up a login window to sign in and then generate the access token and get the SharePoint groups:
Reference:
Use Postman and Azure AD to send REST request to SharePoint Online

SharePoint Rest API how to get Access Token?

Just starting to work with SharePoint and Microsoft authentication and trying to get a SharePoint List into a JavaScript App. From Microsoft documentation, I need to use the following:
GET https://{site_url}/_api/web/lists/GetByTitle('List Title')
Authorization: "Bearer " + accessToken
Accept: "application/json;odata=verbose"
Have searched everywhere to find an definitive answer to how to obtain this accessToken. All the documentation I can find from Microsoft seem to be out of date. Does anyone know the current method to obtain an accessToken?
To call SharePoint specific APIs you need to get a SPO specific access token. You can "swap" an regular MS Graph refresh token for an SPO specific token by doing the following:
Get a delegated auth token from graph as you normally would
(https://learn.microsoft.com/en-us/graph/auth-v2-user)
Use the refresh_token you got and exchange it for an SPO access token by calling the auth endpoint again:
POST https://login.microsoftonline.com/{{tenantName}}/oauth2/v2.0/token
With the following form data:
client_id=<APP ID>
client_secret=<APP SECRET>
refresh_token=<REFRESH TOKEN FROM ABOVE>
grant_type=refresh_token
scope=https://<YOUR TENANT NAME>.sharepoint.com/Sites.Read.All
Take the access token and call the SPO API
You must ensure your app is registered with the correct permissions. In the case above the app must have Sites.Read.All for example.
You could refer to this article to get access token:
https://global-sharepoint.com/sharepoint-online/in-4-steps-access-sharepoint-online-data-using-postman-tool/
Post https://accounts.accesscontrol.windows.net/<Tenant ID>/tokens/OAuth/2
Body:
grant_type client_credentials
client_id <Client ID>
client_secret <Client Secret>
resource 00000003-0000-0ff1-ce00-000000000000/<tenant>.sharepoint.com#<Tenant ID>
My test result:
There is not much documentation for SP API, but it still works. You may follow documentation to get token for Graph API by whatever type of authentication is suitable for your scenario, but instead of passing scopes for Graph API (which is "https://graph.microsoft.com/.default"), you should pass scopes for Sharepoint API which is "https://{your tenant name}.sharepoint.com/.default"
".default" will provide you the access with all permissions which was assigned in Azure AD - so also make sure, that Azure admin has granted you required API permissions for SharePoint API.
This will also work for MSAL.

Resources