Search code examples
c#.net-coreazure-active-directorymicrosoft-graph-apiazure-web-app-service

How want to get user detail from the Azure Directory using C# and Graph API


I want to get user detail using there userPrincipleName or object ID.

I tried like this but they gave me error that I mentioned below.

The expression cannot be evaluated.A common cause of this error is attempting to pass a lambda into a delegate.

This is c# Code

using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models;

namespace UserProperties;

public class GraphHandler
{
    public GraphServiceClient GraphClient { get; set; }

    public GraphHandler(string tenantId, string clientId, string clientSecret)
    {
        GraphClient = CreateGraphClient(tenantId, clientId, clientSecret);
    }
    public GraphServiceClient CreateGraphClient(string tenantId, string clientId, string clientSecret)
    {
        var options = new TokenCredentialOptions
        {
            AuthorityHost = AzureAuthorityHosts.AzurePublicCloud            
        };

        var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
        var scopes = new[] { "https://graph.microsoft.com/.default" };

        return new GraphServiceClient(clientSecretCredential, scopes);
    }

    public async Task<User?> GetUser(string userPrincipalName)
    {
        return await GraphClient.Users[userPrincipalName].GetAsync();
    }

    public void userDetail()
    {
        var user =  GraphClient.Me.GetAsync();
        Console.WriteLine(user);
    }
}

how can I rid out of this, can someone suggest me.

I want to get user Detail from the azure directory.

Thank you


Solution

  • The error occurred as you are making use of ClientSecretCredential and calling /me endpoint.

    • ClientSecretCredential is non interactive flow and /me endpoint works only with user interactive flow.
    • Hence either switch to user interactive flow or use ClientSecretCredential and call users/UserId endpoint.

    Grant application API permissions to use ClientSecretCredential:

    enter image description here

    And modify the code by changing GraphClient.Users[userId].GetAsync() like below:

    using Azure.Identity;
    using Microsoft.Graph;
    using Microsoft.Graph.Models;
    using System;
    using System.Threading.Tasks;
    
    namespace UserProperties
    {
        public class GraphHandler
        {
            public GraphServiceClient GraphClient { get; set; }
    
            public GraphHandler()
            {
                var tenantId = "TenantID";
                var clientId = "ClientID";
                var clientSecret = "ClientSecret";
                GraphClient = CreateGraphClient(tenantId, clientId, clientSecret);
            }
    
            public GraphServiceClient CreateGraphClient(string tenantId, string clientId, string clientSecret)
            {
                var options = new TokenCredentialOptions
                {
                    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
                };
    
                var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
                var scopes = new[] { "https://graph.microsoft.com/.default" };
    
                return new GraphServiceClient(clientSecretCredential, scopes);
            }
    
            public async Task userDetail()
            {
                try
                {
                    // Example usage to get user details directly
                    var userId = "UserID"; // Replace with the desired user's ID
                    var user = await GraphClient.Users[userId].GetAsync();
    
                    // Print user ID and DisplayName
                    Console.WriteLine($"User ID: {user.Id}");
                    Console.WriteLine($"Display Name: {user.DisplayName}");
                }
                catch (ServiceException ex)
                {
                    Console.WriteLine($"Error getting user details: {ex.Message}");
                }
            }
        }
    
        class Program
        {
            static async Task Main(string[] args)
            {
                GraphHandler handler = new GraphHandler();
    
                // Example usage to get my details
                await handler.userDetail();
            }
        }
    }
    

    The user details displayed successfully like below:

    ![enter image description here](https://i.imgur.com/loOGkB7.png)

    If you want to call /me endpoint, then grant User.Read delegated API permission and refer this MsDoc (except Client credentials provider choose any of the flow) and choose interactive flow to authenticate.

    UPDATE:

    To get the User Profile Photo, use the below code:

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Azure.Identity;
    using Microsoft.Graph;
    using Microsoft.Graph.Models;
    
    namespace UserProperties
    {
        public class GraphHandler
        {
            public GraphServiceClient GraphClient { get; set; }
    
            public GraphHandler()
            {
                var tenantId = "TenantID";
                var clientId = "ClientID";
                var clientSecret = "ClientSecret";
                GraphClient = CreateGraphClient(tenantId, clientId, clientSecret);
            }
    
            public GraphServiceClient CreateGraphClient(string tenantId, string clientId, string clientSecret)
            {
                var options = new TokenCredentialOptions
                {
                    AuthorityHost = Azure.Identity.AzureAuthorityHosts.AzurePublicCloud
                };
    
                var clientSecretCredential = new Azure.Identity.ClientSecretCredential(tenantId, clientId, clientSecret, options);
                var scopes = new[] { "https://graph.microsoft.com/.default" };
    
                return new GraphServiceClient(clientSecretCredential, scopes);
            }
    
            public async Task<User> GetUser(string userId)
            {
                try
                {
                    var user = await GraphClient.Users[userId].GetAsync();
                    return user;
                }
                catch (ServiceException ex)
                {
                    Console.WriteLine($"Error getting user details: {ex.Message}");
                    return null;
                }
            }
    
            public async Task PrintProfilePicture(string userId)
            {
                var user = await GetUser(userId);
                if (user != null)
                {
                    try
                    {
                        using (var photoStream = await GraphClient.Users[userId].Photo.Content.GetAsync())
                        {
                            var fileName = $"{userId}_profile_pic.jpg";
                            using (var fileStream = File.Create(fileName))
                            {
                                await photoStream.CopyToAsync(fileStream);
                                Console.WriteLine($"Profile picture saved as: {fileName}");
                            }
                        }
                    }
                    catch (ServiceException ex)
                    {
                        Console.WriteLine($"Error downloading profile picture: {ex.Message}");
                    }
                }
            }
        }
    
        class Program
        {
            static async Task Main(string[] args)
            {
                var handler = new GraphHandler();
                var userId = "UserID"; // Replace with the desired user's ID
                await handler.PrintProfilePicture(userId);
            }
        }
    }
    

    enter image description here

    enter image description here

    Reference:

    Get a user - Microsoft Graph v1.0 | Microsoft