Receiving accessDenied when using App Only permissions calling Graph API sites?search=* - microsoft-graph-api

I have a web application which uses App only tokens to override the end user's permission to retrieve all Site Collections in the tenant. When attempting to use the boiler plate code provided in the example with one minor change, the Graph API is returning accessDenied when attempting to issue the call https://graph.microsoft.com/v1.0/sites?search=*. If I remove WithAppOnly(), the call succeeds [if Delegated rights for Sites.Read.All is assigned]. The Azure AD registered app has admin approved Application-scoped Sites.Read.All assigned to it.
var queryOptions = new List<QueryOption>()
{
new QueryOption("search","*")
};
var sites = await graphServiceClient.Sites.Request(queryOptions)
.WithAppOnly()
.WithScopes("Sites.Read.All")
.GetAsync();
ServiceException: Code: accessDenied
Message: Access denied
Inner error:
AdditionalData:
date: 2021-03-20T21:45:27
request-id: 16933bd6-5e7f-4820-9563-fec75575c9b2
client-request-id: 16933bd6-5e7f-4820-9563-fec75575c9b2
ClientRequestId: 16933bd6-5e7f-4820-9563-fec75575c9b2

You need to add Sites.Read.All of applicaiton permission in the Azure portal.
Note: Click the , because this permission is admin consent required.
Try to test with client credentials flow.
// Get access token
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={client_id}
&scope=https://graph.microsoft.com/.default
&client_secret={client_secret}
&grant_type=client_credentials
// Call MS Graph API
GET https://graph.microsoft.com/v1.0/sites?search={query}

Related

Microsoft Graph - Access Deneined when accessing to calendar events with specifiying user

I am working on creating application which uses Microsoft Graph API to access to calendar events for the users that belongs to an organization.
There is no issue getting event using below endpoint
https://graph.microsoft.com/v1.0/me/calendar/events
However, when accessing to below end point cause 403 error.
https://graph.microsoft.com/v1.0/users/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/calendar/events
403 - Forbidden
{"error":{"code":"ErrorAccessDenied","message":"Access is denied. Check credentials and try again."}}
So far I have below:
Application is registed to Aure with granting
Application.ReadWrite.All
Calendars.ReadWrite
offline_access
User.ReadWrite.All
Have logic to retrieve the access / refresh token.
When the access token is decoded, below scoes are availalbe
"scp": "Application.ReadWrite.All Calendars.ReadWrite User.ReadWrite.All profile openid email"
Others:
Below endpoints work
https://graph.microsoft.com/v1.0/users
https://graph.microsoft.com/v1.0/users/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Below endpoints errors with access denied
https://graph.microsoft.com/v1.0/users/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/calendars
I also tried using User Principal Name instead of ID but it didn't make any difference.
Can someone please help why I am not able to access to the user calendar / events when specifying the user?
Error message showed Access is denied, we can understand that your account doesn't have enough permission to call that api(querying others' calendar events). Since the request calling only related with the access token, no matter whether you have an admin role or not. So let's assume whether you want other users to sign in your app and then they are able to query your calendar events.
According to your description, your token contained scp claim, so I'm sure you are using the delegate permission, which means you signed in and calling api on behalf yourself. And this may be the reason why the access is denied.
We can see the permissions in the screenshot above, I think the application permission type can solve your issue. Using permission type means the api calling is executed by your application itself, but not on behalf of some user. So the application can query any users' calendar events in your tenant.
Using application permission required you to assign application api permission like screenshot below.
Then if you are just testing via tools like postman, using request below to generate access token:
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=sampleCredentia1s
&grant_type=client_credentials
If are composing an asp.net core application and trying to call graph api via graph sdk, follow code snippet below:
using Microsoft.Graph;
using Azure.Identity;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenant_name.onmicrosoft.com";
var clientId = "aad_app_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var events = await graphClient.Users["{user_id}"].Events
.Request()
.Header("Prefer","outlook.timezone=\"Pacific Standard Time\"")
.GetAsync();
Whenever you are trying to access another user calendar events, make sure you have Calendars.Read delegated permission , you can check what type of permission you have in azure portal -
https://learn.microsoft.com/en-us/graph/migrate-azure-ad-graph-configure-permissions?tabs=http%2Cupdatepermissions-azureadgraph-powershell

MS Create GDAP relationship

I am trying to create GDAP relationship request using MS Graph endpoint
POST /beta/tenantRelationships/delegatedAdminRelationships
I am getting an access token from Azure app that has the application permission DelegatedAdminRelationship.ReadWrite.All granted to it.
I verified that the request header contains a bearer access token and that the token contains
"roles": [DelegatedAdminRelationship.ReadWrite.All]
However I am receiving the error: forbiddenUserDoesNotHaveAccess.
What am I missing?
According to the documentation the required scope for DelegatedAdminRelationship.ReadWrite.All permission is only delegated.
Application permission type is not supported.

Microsoft Graph Mail Query - Getting "ErrorAccessDenied"

My company is using Microsoft 365 Business Standard licenses. We are using email through these accounts. We also have a few shared mailboxes. We are trying to create an app that uses the microsoft graph application permissions (rather than the delegated permissions) so the application can access one of the shared mailboxes without needing to be authenticated under the current user.
This is the steps we have taken so far:
Within Microsoft Azure, we have an application in which we have granted application api permissions for Mail.Read, and we have accepted Admin consent.
We authorized as an app, not as a user, in the application using this endpoint https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize, pointing out the required parameters for sending a request. Then, MS API builds this link:
https://login.microsoftonline.com/{some_string}/oauth2/v2.0/authorize?state={some_string}&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2F.default&response_type=code&approval_prompt=auto&redirect_uri=http%3A%2F%2Flocalhost&client_id={some_string}
When we follow the link, we get to the standard authorization form on the site. After we log in, a link is created, where we take the code and create the token: http://localhost/?code={some_string}&state={some_string}&session_state={some_string}
When we try to hit this endpoint: https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages, we get this response:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"date": "2020-09-14T11:22:30",
"request-id": "{some_string}",
"client-request-id": "{some_string}"
}
}
}
I am thinking that hitting this endpoint https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages requires us to pass the token previously generated and/or specify which application is making the query?
Any help or direction on what needs to be done to make this query work would be greatly appreciated. Thank you!
I am thinking that hitting this endpoint https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages requires us to pass the token previously generated and/or specify which application is making the query?
Yes you would need to send the AccessToken in the Authorization header, you should also include the x-anchormailbox header which helps route the request to correct mailbox eg
GET https://graph.microsoft.com/v1.0/users/sharedmailbox#domain.com/messages HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer EwAoA8l6BAAU ... 7PqHGsykYj7A0XqHCjbKKgWSkcAg==
X-AnchorMailbox: sharedmailbox#domain.com
The other thing you might want to check is to ensure you have the correct scopes in your token you can use https://jwt.io/ for that
In order to use application permissions you will need to use the client credentials auth flow (not the authorization code auth flow which uses delegated permissions). To get a token make a request against "/oauth2/v2.0/token" and specify "grant_type=client_credentials" in the request. See examples of client credentials auth flow here for more details: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

Error Microsoft Graph API. Get Messages for Channel

my program through a Graph API call accesses channel messages. I have a problem. For one Azure application it works but for another it doesn't.
The two applications have the same Api authorization. What can it be?
var c = Task.Run(() =>
graphClient.Teams[teams].Channels[channelId].Messages
.Request()
.GetAsync());
It's the error:
Code: UnknownError
Inner error:
AdditionalData:
date: 2020-08-28T12:15:04
request-id: 3026d5b8-8178-45f0-97a2-103d5a602b33
ClientRequestId: 3026d5b8-8178-45f0-97a2-103d5a602b33
It's Api authorization
List channel messages is included in Protected APIs in Microsoft Teams.
To request access to these protected APIs, complete the following request form.
The form requires you to enter the "App id(s) to enable application permissions for".
After that the 403 error will be fixed.

How do I authenticate against the Dynamics 365 Data Export Service API?

I've set up something called the Data Export Service for Dynamics 365 so that it replicates into an Azure SQL database. This is working as expected.
I'm trying to find a way to be proactively notified if this service encounters any errors. There does not appear to be a native way to do this through the setup in CRM itself, but they do provide an API. The Swagger page outlining all methods can be found here.
I'm trying to call the GetProfilesByOrganizationId method using Postman:
https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=4ef7XXXX-XXXX-XXXX-XXXX-XXXXXX8a98f&status=true
I'm having issues with authentication and always receive the following error:
"Message": "Received unauthenticated requestRequest Url https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=4ef7XXXX-XXXX-XXXX-XXXX-XXXXXX8a98f&status=true"
I have registered an application in Azure that has permission to access Dynamics 365 on behalf of the authenticated user which in this case is me, the administrator.
I have set the Type to OAuth 2.0 on the Authorization tab of Postman. I have requested an Access Token using the Grant Type of Authorization Code against the above application successfully. This has added a header to the request:
Key: Authorization
Value: Bearer BIGLONGACCESSTOKEN
Despite this header being present I still get the error mentioned above.
The API documentation implies the authentication is OAuth2 Implicit Grant Flow (click on any red exclamation mark in the documentation) but I can't get this to work in Postman. When I try to request a token with this method I get the error:
unsupported_response_type
... in the Postman console.
Any ideas how to authenticate (with Implicit Grant?) against this API in Postman?
(I'd accept C# examples if they're more appropriate, but I'd be surprised if Postman can't show me what I need)
It looks like the code sample shown by Microsoft can work if updated with newer methods and with some extra configuration in Azure that's not documented.
Azure configuration
By installing the Data Export service (and assuming it's all working) you'll have a new Enterprise Application listed in Azure AD as Crm Exporter.
To take advantage of this application and authenticate with the Data Export API you must configure an app of your own.
Go to the App registrations tab in Azure AD and add a new application registration.
Give it a name and set the Application type to Native. The redirect URI doesn't typically matter as long as it's valid.
Click the Manifest button to edit the manifest, change the property oauth2AllowImplicitFlow to true and save the changes.
The only other important configuration is Required permissions which should be set as below:
Windows Azure Active Directory
Delegated permissions
Sign in and read user profile
Data Export Service for Microsoft Dynamics 365 (Crm Exporter)
Delegated permissions
Have access to Data Export Service for Microsoft Dynamics 365 API
You will then need to click Grant Permissions.
C# changes
The updated method looks like this:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
string clientId = "11cfXXXX-XXXX-XXXX-XXXX-XXXXXXXXd020";
string user = "my.username#domain.com";
string password = "PASSWORD";
var authParam= await AuthenticationParameters.CreateFromResourceUrlAsync(
new Uri("https://discovery.crmreplication.azure.net/crm/exporter/aad/challenge")
);
var context = new AuthenticationContext(authParam.Authority, false);
var credentials = new UserPasswordCredential(user, password);
var token = await context.AcquireTokenAsync(authParam.Resource, clientId, credentials).AccessToken;
You can now query the Data Export API by providing the token as a header:
Authorization : Bearer eJ0y........Hgzk
curl -X GET --header 'Accept: application/json' 'https://discovery.crmreplication.azure.net/crm/exporter/profiles?organizationId=MyOrgId&status=true'

Resources