Microsoft graph - Insufficient privileges when trying to get user info - c#

I'm trying to get user information from Active Directory (email, phone number and assigned groups) using Microsoft graph and implicit flow in angular + asp.net web api application after user logges into the system.
Now we've set up some privileges for the application registered in Azure AD and all the code seems to be working fine using below set up.
The problem is those permissions seem high just for reading profile info and groups of a single user.
According to microsoft documentation delegated User.Read should be enough - link but after changing to below setup and removing User.Read.All for application
below error is thrown:
{
"StatusCode":500,
"Message":"Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation.
Inner error: AdditionalData: date: x request-id: x client-request-id: x ClientRequestId: x "
}
The error is thrown when calling Users from graphClient:
GraphServiceClient graphClient = GetClient();
return await graphClient.Users[userObjectId].Request()
.GetAsync();
private GraphServiceClient GetClient()
{
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(ADClientId)
.WithTenantId(TenantId)
.WithClientSecret(ApplicationSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
return graphClient;
}
Now I'm not sure how to limit those privileges. Whether there is something incorrect with the flow, the C# code or maybe the privileges are incorrect.
Any help would be greatly appreciated.
Regards.

User.Read Delegated permission allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users.
So you can only get https://graph.microsoft.com/v1.0/me or https://graph.microsoft.com/v1.0/user/{userObjectId of the signed-in user} with this permission.
If you want to get other user's information, please use User.ReadBasic.All or User.Read.All Delegated permission (based on your needs). Please note you need to add Delegated permission rather than Application permission.
Reference here.

Related

Authenticate an EWS application by using OAuth is not working

I am changing my existing c#-app from basic authentication to OAuth Authenticate.
I'm using the code example from Microsoft learn page:
// Using Microsoft.Identity.Client 4.22.0
var cca = ConfidentialClientApplicationBuilder
.Create(ConfigurationManager.AppSettings["appId"])
.WithClientSecret(ConfigurationManager.AppSettings["clientSecret"])
.WithTenantId(ConfigurationManager.AppSettings["tenantId"])
.Build();
// The permission scope required for EWS access
var ewsScopes = new string[] { "https://outlook.office365.com/.default" };
//Make the token request
var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync();
On the Azure Active directory in App-Registration with the rigths Mail.* ( see attached image
)
[App rigths]
when I try to get the token with AcquireTokenForClient I get this error:
A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal...
ErrorCode: "invalid_client"
HResult: -2146233088*
Thanks for help
Dani
The only permission that is valid for EWS when using the client credentials flow is full_access_as_app
The Mail. permissions are all for the Graph which supports a much more restrictive permission model that EWS does not. I would suggest you read https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth you has the information you need to modify the manifest directly to add the correct permissions

Graph Api Permission to Read Email

I have the following c# code. I am trying to read email in exchange 365 using graph api as per the following link
Reading user emails using MS Graph API C#
IConfidentialClientApplication cca = ConfidentialClientApplicationBuilder
.Create("myAppId")
.WithTenantId("myTenantId")
.WithClientSecret("myClientSecret")
.Build();
ClientCredentialProvider ccp = new ClientCredentialProvider(cca);
GraphServiceClient client = new GraphServiceClient(ccp);
var users = await client.Users.Request()
.GetAsync();
I executed it and got the following error:
Microsoft.Graph.ServiceException: 'Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
I have given the mail.read and user.read permission as per screenshot.
any advices?
Thanks.
As your code shows, you use the client credential flow which uses application permissions.
If you want to use var users = await client.Users.Request().GetAsync(); to list users, one of the application permissions need to be set.

Create a 'event as online meeting' or only the onlineMeeting using Microsoft Graph API

Any user who logged into our system (IdentityServer as Auth) under a specific tenant should be able to create an event as an online meeting (MS Teams).
We followed Build ASP.NET Core MVC apps with Microsoft Graph and Create and enable an event as an online meeting to create an application that authenticates an AD user of an organization and allow him to create an event as an online meeting.
We are able to implement it successfully and was able to create the event as an online meeting.
But the exact scenario here is any user who is authenticated in our web application (not a AD user) should be able create a MS Teams meeting event and share it with other participants who should be able to join the meeting.
I am not sure how to achieve this.
Edit
Or at least how do I create onlineMeeting ? I tried with Client credentials provider as below
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create("<<App_Id>>")
.WithTenantId("<<Tenant_Id>>")
.WithClientSecret("<<Client_Secret>>")
.Build();
ClientCredentialProvider authenticationProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider);
var onlineMeeting = new OnlineMeeting
{
StartDateTime = DateTimeOffset.Parse("2020-01-15T21:30:34.2444915+05:30"),
EndDateTime = DateTimeOffset.Parse("2020-01-15T22:00:34.2464912+05:30"),
Subject = "User Token Meeting"
};
var meeting = graphClient.Me.OnlineMeetings
.Request()
.AddAsync(onlineMeeting).Result;
but it was throwing
Code: Forbidden
Inner error:
AdditionalData:
request-id: <<some_id>>
date: 2020-07-09T16:42:23
ClientRequestId: <<some_id>>
I been working on your question in few days, I was going to mention some of the suggestions comes with the other answer. But in addition, the main challenge here, the system need to know who is authorized to do what.
So IMO The Best choice to solve this is creating a guest login in AzureAD, than you can use that to create a Team Events. Further more you can added an extra step after guest user logon, so that guest should enter his/her name and use it as reference.
You will need to take these two steps.
Get the right token
Create an event (but change the url to
https://graph.microsoft.com/v1.0/users/the_user#domain.com/events)
The hard part is getting the right token, you have multiple options.
Use the client credentials flow this will force an admin from every new tenant to authorize your application for their organization. You can then use the tenant from the user info to request a token for that tenant and use the user id to create the right url to post to.
Make IdentityServer save the access token and allow you to access it. At coonfiguration level you have access to token callback and there you can also save the Azure AD access token. I think you can add it to a reference token, that way it isn't transmitted everytime but your web application is still able to access it.
Use the on-behalf-of flow, this would require you to pass the Azure AD access token token retrieved from azure AD by the IdentityServer to be passed to your application.
Just remove the identity server from the flow and have your web application logging straight with Azure AD. That way you'll have the right token available all the time.
Edit
After reading your editted question, what you want is a website where the user doesn't have to be an member of your Azure AD, just wants access to some new online meeting?
Best option is to created a shared mailbox, authorize an application (with Calendar.ReadWrite). Get a token with client credentials and call Create Event and then extract the meeting url from the event (that you'll get back when the posts completes succesfully.
To create an online meeting for the "Client Credentials" flow, I used the following:
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create("my-app-client-id")
.WithTenantId("my-aad-tenant-id")
.WithClientSecret("my-client-secret")
.Build();
var authProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphClient = new GraphServiceClient(authProvider);
var meetingGuid = Guid.NewGuid();
var createMeetingResponse = await graphClient.Users["my-aad-user-object-id"].OnlineMeetings
.CreateOrGet(meetingGuid.ToString())
.Request()
.PostAsync();
The issue with your code is that referencing graphClient.Me causes the Graph requests to go to https://graph.microsoft.com/v1.0/me/onlineMeetings, which is not what you want in the "Client Credentials" flow. See this screenshot from the documentation found here: https://learn.microsoft.com/en-us/graph/api/onlinemeeting-createorget?view=graph-rest-1.0&tabs=csharp
I had to grant "application" permissions in Azure Portal to allow my app to access the online meetings API, and I had to create a client secret. I also had to follow this article to create a policy and grant it to specific users using Microsoft Teams PowerShell:
https://learn.microsoft.com/en-us/graph/cloud-communication-online-meeting-application-access-policy
For users not in your organization, you can invite them as a guest user to your tenant.
I had issues using the Microsoft Teams Powershell commands due to settings in Windows Remote Management, which I did something like this to work around:
https://lonesysadmin.net/2017/08/10/fix-winrm-client-issues/

Cannot read full user profiles MS Graph while having the needed scopes

I am using the GraphServiceClient in my code to access multiple endpoints for data. I have a service account who logs in with Azure AD, with the following scopes: Group.Read.All, User.Read.All, Mail.Read.
However, with these needed scopes I cannot get the MailFolders for a users profile or a birthdate from the user. It gives the following error:
ServiceException: Code: -2147024891, System.UnauthorizedAccessException.
The delegated permissions in Azure AD have already granted by admin (https://imgur.com/iFb0rx9).
Example MailFolders:
var result = await client
.Users[user.Id]
.MailFolders
.Request()
.GetAsync();
This is the error that came back:
ServiceException:
Code: ErrorAccessDenied
Message: Access is denied. Check credentials and try again.
Can I not access other users profiles or am I missing something else?
If you have Mail.Read as a delegated permission (meaning you've logged in with a user), then you can only read your own mail, even if someone has given you permissions to their mailbox. In order to read other mailboxes, you need to request the Mail.Read.Shared permission.
If you have Mail.Read as an application permission (meaning no logged in user to your app, using the client credentials flow), then you can read all mailboxes in your org.
I believe that the question is already answered here.
Even when you app has admin consent to do something it does not override the Exchange delegate permission if you know what I mean.
You would need that specific user's token or try to access it as a user who is delegated in Exchange online.

Graph API - Insufficient privileges to complete the operation

When trying to access the Graph Service Client using I am receiving the error:
Code: Authorization_RequestDenied
Message: Insufficient privileges to complete the operation.
After researching this error the most common solution was to set the permissions for the API. This had already been done and has permissions to read basic/full profiles.
I've delete and re-added the APIs.
Below is the code in my AzureAuthenticationProvider class which inherits from IAuthenticationProvider:
public class AzureAuthenticationProvider : IAuthenticationProvider
{
private string _azureDomain = "myDevDom.onmicrosoft.com";
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
try
{
string clientId = "2b823c67-1b0d-4a10-a9e1-737142516f5q";
string clientSecret = "xxxxxx";
AuthenticationContext authContext = new AuthenticationContext("https://login.windows.net/" + _azureDomain + "/oauth2/token");
ClientCredential credentials = new ClientCredential(clientId, clientSecret);
AuthenticationResult authResult = await authContext.AcquireTokenAsync("https://graph.microsoft.com/", credentials);
request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
}
catch (Exception ex)
{
}
}
}
I've tried changing the client secret to an invalid Id and it threw an error, so the client key is correct. I've also tried to verify that the access token is valid by altering the access token, this also returns a error.
The above code seems to work fine.
Below is the code where I'm trying to access Azure AD:
public async Task<IGraphServiceUsersCollectionPage> GetUsersByLastName(string lastname)
{
GraphServiceClient graphClient = new GraphServiceClient(new AzureAuthenticationProvider());
string filter = String.Format("startswith(surname, '{0}')", lastname);
IGraphServiceUsersCollectionPage users = await graphClient.Users.Request().Filter(filter).GetAsync(); //Fails on this line
return users;
}
Please refer to below steps :
From your screenshot , seems you grant Read and write directory data application permission for Windows Azure Active Directory(azure ad graph api) . Since you are using microsoft graph (https://graph.microsoft.com/) , you need to grant application permission for Microsoft Graph :
Since you are admin in your AAD, You could grant permission for users in organization by click Grant permission button shown in above screenshot .
Then you could use your code (client credential flow to get the token) and query users information . If you check the claims in access token issued by azure ad , you could find Directory.Read.All permission in roles claim .
Make sure click "Grant Permissions" and than Yes for all users accounts.
In my case, delete user was not working. I took below steps & it started working for me.
Go to Azure Active Directory > Roles and administrators > Click on 'User administrator' > click on '+ Add assignment' to add your app. (i.e. console app using AAD Graph REST API to interact with Azure Active Directory).
Hope it helps someone.
For me the key to solve this problem was hint:
To use the Graph API with your B2C tenant, you will need to register a dedicated application by using the generic App Registrations menu (All Services and there it is by default not Favourite starred) in the Azure Portal, NOT Azure AD B2C's Applications menu. You can't reuse the already-existing B2C applications that you registered in the Azure AD B2C's Applications menu.
Find more on page AD B2C API access demo
In some cases the actual issue happens because we use "Application permissions" instead of "Delegated permissions". In my application, I have tried to list all the users with application permissions and it wasn't working. When I switched to a delegated permissions, it worked.
So, some quick check would be like this:
Check if you are using Microsoft Graph API or something else
Use Delegated permissions
Click Grant permissions button to propagate permissions :)
Hopefully, this would help someone.
Suppose you want to create group in azure active directory
i have to performer the following steps to solve this problem
AD > App Registered > your app
Select Required Permission
Click Add and select Microsoft Graph and add it
select Microsoft Graph
select Read and write all groups from delegated permission list
And save it
Select Windows Azure Active Directory and grant all application permission
Save it
Grant permissions by ticking 'Directory.Read.All/ Write' is not enough.
I run into the same issue. and solved by adding service principle to administrator role.
If you application is created recently, this can be done Azure AD Powershell.
$pricinple = Get-AzureADServicePrincipal || Where-Object {$_.DisplayName -eq 'youappname'}
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq 'Company Administrator'}
Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $pricinple.ObjectId
for detail, see https://learn.microsoft.com/en-us/powershell/module/Azuread/Add-AzureADDirectoryRoleMember?view=azureadps-2.0
If you application was created long time ago, you will need to use MSOnline.
see: https://learn.microsoft.com/en-us/powershell/module/msonline/Add-MsolRoleMember?view=azureadps-1.0
I am using Credentials flow
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
and my problem was setting Delegate Permissions instead of Application Permission.
I could not get a user because I wasn't using User.Read.All from Application Permissions
https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http
Application User.Read.All, User.ReadWrite.All, Directory.Read.All, Directory.ReadWrite.All
I had to add all "groups" (ID, Access, SAML) into the token.
This can be configurated in the Azure Active Directory Token Configuration and checked via https://jwt.io/.
you should give Directory.Read role to the service principal in the AD page, not the app register page.
by the way. I am use python sdk azure-graphrbac with serviceprincipal
from msrestazure.azure_active_directory import ServicePrincipalCredentials
credential = ServicePrincipalCredentials(ServicePrincipal_APP_ID,ServicePrincipal_SECRET_VALUE,tenant=ServicePrincipal_TENANT_ID,resource="https://graph.windows.net/")
self.client=GraphRbacManagementClient(credential,TENANT_ID,base_url)
Go to Azure Portal -> Active Directory -> App registrations -> Select Your Application -> API permissions
Now, Click on Add a permission and choose Microsoft Graph, select Application Permission and search for User.Read.All
Add these permissions to your application and it should work.

Categories

Resources