Microsoft graph get lists in sites returns 401 - sharepoint

When I try to list all lists in a sharepoint site using this Microsoft Graph query, it returns me an 401 error. But reading a list works fine.
{
"error": {
"code": "unauthenticated",
"message": "Access denied. You do not have permission to perform this action or access this resource.",
"innerError": {
"request-id": "6929864e-9d14-4911-9d7e-d0a29259e05f",
"date": "2017-06-21T21:00:15"
}
}
}
Does not work: https://graph.microsoft.com/beta/sites/{site-id}/lists
Work: https://graph.microsoft.com/beta/sites/{site-id}/lists/{list-id}
Thanks

Typically, a 401 response indicates that the information the server needs to authenticate your API request is either missing from the request or present but somehow invalid. I'd suggest that you:
1) Verify that the Authorization header is present in the request that fails.
2) If present, then verify that the contents of the Authorization header in the request that fails is identical to the contents of the Authorization header in the request that succeeds.
If you're sending the exact same Authorization header in both requests, then I wouldn't expect the server to return a 401 response for one operation but not the other. (If it were a permissions issue -- i.e., the user has rights to perform operation-A but not operation-B, then I'd expect the server to return a 403 Forbidden response for operation-B -- not a 401 Unauthorized response.)
Update (some additional thoughts)
It looks like both operations require one of these two access scopes:
Sites.Read.All
Sites.ReadWrite.All
You should verify that the token you're specifying in the Authorization header of the failing request has at least one of these scopes (although as I said earlier, I'd expect the server to return 403 if you didn't have the proper access scope).
Also, if you obtained the access token via OAuth without a user providing authorization, then perhaps the information in this answer might be helpful: How to use OAuth when there is no user delegation? -- Microsoft Graph API. In the scenario that post describes, the server was returning a 401 response because the developer hadn't explicitly obtained administrator consent for the operation they were attempting to perform.

Can you please try again? This (https://graph.microsoft.com/beta/sites/{site-id}/lists) seems to be working now.

Related

Is it possible to access microsoft graph using custom audience?

I have an API that uses Azure AD to provide access to resources. It has one scope api://{client_id}/Api.Read and following API permissions:
User.Read.All,
User.Read.
When I receive an access token from the AD it has only one aud - {client_id} and when I try to access Microsoft graph (e.g. https://graph.microsoft.com/v1.0/me) I get "Access token validation failure. Invalid audience." response as expected.
My question is - Is it possible to access both graph API and my API using one token and how do it?
I am exchanging current token to a "proper" token using on-behalf-of call: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow
Basically, you just make the following call (copied from the link above):
POST /oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com/<YOUR_TENANT>
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&requested_token_use=on_behalf_of
&client_id=<YOUR_CLIENT_ID>
&client_secret=<YOUR_CLIENT_SECRET>
&assertion=<YOUR_CURRENT_TOKEN>
&scope=<YOUR_NEW_SCOPES>
The response contains the new token to access the resources that are requested in the scopes. My scenario is not exactly yours, but I think this should work for your case as well. You need to make this call server-side.
This assumes that the user has already consented that your app is okay to use <YOUR_NEW_SCOPES>, or otherwise this call will result in "interaction_required" or "invalid_grant" error (something like this, don't remember the exact error name) that basically means you need to raise UI prompt for the user to agree to the new scopes (how to do that is another question)

How read async URL returned (in location header) by a Logic App authenticated through Oauth?

I've created a Logic App, which is configured to authenticate using AD Outh according to this:
https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app
This Logic App it takes a lot of time to execute and to avoid timeout the response was configured with Asynchronous Pattern as mention in:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/async-operations
The authentication with Bearer Token works and the Logic App responses with a URL (in Location header) in which finally will be stored the response.
The problem is that I cant't access to this URL because I'm receiving the next error:
{
"error": {
"code": "DirectApiAuthorizationRequired",
"message": "The request must be authenticated only by Shared Access scheme."
}
}
The problem is that the URL returned in the Location header only contains SAS keys when I run the Logic App using SAS and I need use only OAuth for securiry reasons.
Now, if try to access to this URL using Bearer token the response is:
{
"error": {
"code": "InvalidUseOfOAuthToken",
"message": "The requested operation is not supported, Use of open authentication token is only supported for workflow trigger request."
}
}
Here an example of the URL:
https://prod-05.southcentralus.logic.azure.com/workflows/a98d6ba3becd449db74ac0527a64ec57/runs/08585941366423271731798768425CU04/operations/c4d9cb98-03b3-4c44-87c3-5752c2ed403c?api-version=2016-10-01
So, understanding that is not posible access to this URL using OAuth, How can I force the header location to include the SAS parameters by consuming the logic app using OAuth?
Finally, solution proposed was to use the functionality "Create expiring callback URLs" for Async Logic Apps,
https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app#create-expiring-callback-urls
This consists of creating a temporary URL for each execution, these URL’s contain SAS parameter which will in cretain date . These URLs are created from a call to the ARM Rest API using a Bearer Token and specifying the date on which it will stop working. With this way there is no problem using SAS because are temporary.
https://learn.microsoft.com/en-us/rest/api/logic/workflowversions/listcallbackurl

Azure RBAC: REST API returns empty response for unauthorized request

Through experimentation with the Azure REST API, I have found cases in which a response for an unauthorized request has a 200 code with an empty response:
{
"value": []
}
Specifically, I've observed two scenarios, both occurring using a client application authenticated with a valid bearer token:
If the client has no roles assigned, requests to any API requiring explicit access return a 403 error code as expected.
If the client has a role assigned that does not authorize the endpoint being accessed, a 200 response with an empty payload is returned.
Regarding the second scenario, I would expect that this request would still return a 403 error code since the access is unauthorized given that the assigned role(s).
Is this expected behavior?
Concretely, I've tested the second scenario above by assigning the Network Contributor role to an application and attempting various GET operations outside of the actions permitted. For all unauthorized accesses, an empty value property is returned. When I test the same endpoints with a Reader role, the value property is populated.
This is the answer I received from Microsoft on the subject:
The behavior you are seeing is expected for APIs that return a
collection of resources, the reason for this is that the permissions
are evaluated per resource, so that only the resources where you have
permissions are returned.
This is the way we process the request:
We verify the permissions of the user making the call, if there are no permissions, an Unauthorized error is returned.
The API call is then sent to the resource provider to handle, in this case, we ask for the full collection of resources.
The results returned from the resource providers are then filtered based on the permissions the user has.
The filtered results are returned to the user. (If everything was filtered out, then the response will be empty).
I understand how this may be confusing, in this case, the list API is
not restricted for the user, we restrict the results returned in the
response, that's why a 200 OK with an empty array is the correct
response to the scenario you have shared with us.

how to authenticate to Azure time series insights query API?

I keep getting a AuthenticationFailed error with a InvalidAuthenticationTokenAudience inner error when attempting to query the /environments endpoint.
I have already created an app in the Azure Active Directory, given it access in the time series insights management portal and I can already get an Oauth 2.0 Access token from the auth URL.
I have tried giving the token url the 'https://api.timeseries.azure.com/' resource/audience/scope but the API keeps returning the same error message:
{
"error": {
"code": "AuthenticationFailed",
"message": "Server failed to authenticate the request. The token has been obtained from wrong audience or resource.",
"innerError": {
"code": "InvalidAuthenticationTokenAudience",
"message": "The access token has been obtained from wrong audience or resource '00000002-0000-0000-c000-000000000000'. It should
exactly match (including forward slash) with one of the allowed
audiences 'https://api.timeseries.azure.com/'."
}
} }
I'm using Postman with the Oauth 2.0 authentication type, the client credentials Grant Type and send as basic Auth Header option for the token request.
Has anyone tried this with success?
Update 01:
The decoded (using JWT as suggested in comments) payload portion of one of the tokens shows the that the aud field is 00000002-0000-0000-c000-000000000000. Which is definitely wrong.
Based on the exception, it indicates that the resource is not matching https://api.timeseries.azure.com/ when acquire the access token.
So please make sure that the resource is https://api.timeseries.azure.com/, for more information please refer to the screenshot.
Get access token
I test Get environments API, it works correctly for me.
GET https://api.timeseries.azure.com/environments?api-version=2016-12-12

Designing Token Based Authorization Server Request/Response

Identity in our services are based on a token stored in a database. This is acquired by the client by logging in with a username and password.
Each time a resource is requested, we plan to validate the token and determine if the user is authorized to access that resource.
Our services are deployed separately, and the authorization server can be reached via HTTP.
What's the best practice/common way in authorizing the requests?
Sending token with requested permission and role
I was thinking of passing in the token with the role and requested permission of the user in the token validation request to the authorization server.
{
token: 'xyz',
role: 'ROLE_ADMIN',
permission: 'SAVE_USER'
}
and respond with: 200 for success, 401 for an invalid token, 403 if they are not authorized to use the permission.
Sending only the token in authorization request
Another approach in mind is sending just the token in the token in the token validation request to the authorization server.
{
token: 'xyz'
}
and respond with all the permissions and roles the user have:
{
roles: ['ROLE_ADMIN', 'ROLE_USER'],
permissions: ['SAVE_USER', 'DELETE_USER', 'SHOW_USER']
}
Which of these are more advisable?
Or are there any other/patterns approaches I can consider?
As you're talking about a "service", it means that most likely your service prefers to know what can it do before it requests for it.
For example you may want to highlight those buttons user can click before a request arrives.
So I think the second approach would be fine. And a kind of first approach is gonna be executed while a request is passed to the server, eg. user wants to remove something and it doesn't have sufficient access, so gets a 403.
Talking about security, in both ways you described, there are sufficient checks, eg. in the first one, when user asks for some action, it GETS CHECKED before getting executed and that's what should be done.

Resources