Graph Api Permission to Read Email - c#

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.

Related

How to authenticate correctly in SharePoint Online from Azure Function with API Graph?

Ciao,
I'm working on a Azure Function that need to read/write to a SharePoint Online list using API Graph. I've some problems on authentication.
I've followed this steps:
Created one SharePoint Online site and one list
Registered my app in Azure Active Directory (single-tenant)
Generated one secret
Added Sites.Selected authorization to my app
Requested permissions to my administrator following this link
Wrote code for use API Graph
Below app's authorizations:
Below my code:
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "my-tenant-id";
var clientId = "my-client-id";
var clientSecret = "my-secret";
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphServiceClient = new GraphServiceClient(clientSecretCredential, scopes);
var test = await graphServiceClient
.Sites["my-site-id"]
.Lists["my-list-id"]
.Items.Request().GetAsync();
When I execute this code I obtain this error: Message: Either scp or roles claim need to be present in the token.
How can I resolve this error?
Thank you a lot
I tried to reproduce the same in my environment and got the same error as below:
To resolve the error, I created an Azure AD Application and granted API Permissions like below:
Note that, you can only add Sites.Selected API permission based on your requirement.
I generated the token with scope as https://graph.microsoft.com/.default by using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope:https://graph.microsoft.com/.default
grant_type:client_credentials
Using the above generated access token, I am able to authenticate to SharePoint successfully like below:
https://graph.microsoft.com/v1.0/sites/

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

Microsoft graph - Insufficient privileges when trying to get user info

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.

Azure Active directory integration c# windows application

We need to integrate the Azure Active directory with the our Add-in project for Login implementation single sign on mode.
So, in this case how can we get logged in user’s email address?
As shown in below screenshot, we are unable to fetch user email address if it is on Azure Active Directory.
If Active directory is on local server, we are able to fetch the email address. Using following code snippet
( System.DirectoryServices.AccountManagement.UserPrincipal.Current.EmailAddress )
we have already tried using graph API. Although /me not working. we are getting exception as Request_ResourceNotFound
If you want to call Graph API with the SDK in C# application, please refer to the following steps:
Install SDK
Install-Package Microsoft.Graph
Install-Package Microsoft.Graph.Auth -IncludePrerelease
Code
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithTenantId(tenantID)
.WithClientSecret(clientSecret)
.Build();
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
For more details, please refer to the document and the article.
Update
If we use client credential authentication, please use the following code to get one user
var user = await graphClient.User
.Request()
.Filter("mail eq \'<your emial>\'")
.GetAsync();

Using authProvider with MS SDK for graph calls in C#

I'm trying create a C# console application to connect to graph API and get a list of users from AzureAD from a tenant. I have registered the app and the admin has given me the following
Tenant Name and Tenant ID
Client ID (also sometimes called App Id)
Client Secret
Using the sdk the C# code I need to use looks like this (https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=cs):
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var users = await graphClient.Users
.Request()
.GetAsync();
However, the console application will run as a batch process so there will be no user interaction at all. So in order to provide the authProvider I followed this article on MS docs site: https://learn.microsoft.com/en-us/graph/sdks/choose-authentication-providers?tabs=CS
And I think for my purpose I need to go for the "Client Credential OAuth flow". The code which is shown on that URL. But here it is too.
IConfidentialClientApplication clientApplication = ClientCredentialProvider.CreateClientApplication(clientId, clientCredential);
ClientCredentialProvider authProvider = new ClientCredentialProvider(clientApplication);
The trouble is that Visual Studio does not recognise ClientCredentialProvider class. I'm not sure which assembly to import. I'm using the following usings in the top.
using Microsoft.Identity.Client;
using Microsoft.IdentityModel.Clients;
using Microsoft.IdentityModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
I'm not very experienced with GitHub repos and I'm using Visual Studio 2015. I would be interested in sample code; I have looked but cannot find any. MS have some lectures but they use another type of auth Provider which is authenticating interactively which is not what I'm looking for. I want obtain the token using the TenantId/ClientId and Client Secret.
ClientCredentialProvider is part of the Microsoft.Graph.Auth package. You can read more about this package at https://github.com/microsoftgraph/msgraph-sdk-dotnet-auth
Note that this package is currently (as of 2019-05-15) in preview, so you may want to wait before using this in a production application.
Alternatively, the following example uses the Microsoft Authentication Library for .NET (MSAL) directly to set up the Microsoft Graph SDK using app-only authentication:
// The Azure AD tenant ID or a verified domain (e.g. contoso.onmicrosoft.com)
var tenantId = "{tenant-id-or-domain-name}";
// The client ID of the app registered in Azure AD
var clientId = "{client-id}";
// *Never* include client secrets in source code!
var clientSecret = await GetClientSecretFromKeyVault(); // Or some other secure place.
// The app registration should be configured to require access to permissions
// sufficient for the Microsoft Graph API calls the app will be making, and
// those permissions should be granted by a tenant administrator.
var scopes = new string[] { "https://graph.microsoft.com/.default" };
// Configure the MSAL client as a confidential client
var confidentialClient = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithAuthority($"https://login.microsoftonline.com/$tenantId/v2.0")
.WithClientSecret(clientSecret)
.Build();
// Build the Microsoft Graph client. As the authentication provider, set an async lambda
// which uses the MSAL client to obtain an app-only access token to Microsoft Graph,
// and inserts this access token in the Authorization header of each API request.
GraphServiceClient graphServiceClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => {
// Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
var authResult = await confidentialClient
.AcquireTokenForClient(scopes)
.ExecuteAsync();
// Add the access token in the Authorization header of the API request.
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
})
);
// Make a Microsoft Graph API query
var users = await graphServiceClient.Users.Request().GetAsync();
(Note that this example uses the latest version of the Microsoft.Identity.Client package. Earlier versions (before version 3) did not include ConfidentialClientApplicationBuilder.)
As mentioned above - at the time of writinf Sept 2021, the package: Microsoft.Graph.Auth is deprecated. This means ClientCredentialProvider is no longer available.
https://www.nuget.org/packages/Microsoft.Graph.Auth/
The alternative is to use the solution propsed by Philippe above.
If you wanna cycle trough the users, replace the var users with the following code:
IGraphServiceUsersCollectionPage users = graphServiceClient.Users.Request().GetAsync().Result;
foreach (User user in users)
{
Console.WriteLine("Found user: " + user.Id);
}

Categories

Resources