Добавление проверки подлинности пользователей в приложения .NET для Microsoft Graph

В этой статье описано, как добавить проверку подлинности пользователей в приложение, созданное в разделе Создание приложений .NET с помощью Microsoft Graph. Затем вы используете API пользователя Microsoft Graph для получения пользователя, прошедшего проверку подлинности.

Добавление проверки подлинности пользователя

Клиентская библиотека удостоверений Azure для .NET предоставляет множество TokenCredential классов, реализующих потоки маркеров OAuth2. Клиентская библиотека Microsoft Graph .NET использует эти классы для проверки подлинности вызовов Microsoft Graph.

Настройка клиента Graph для проверки подлинности пользователей

Начните с использования DeviceCodeCredential класса , чтобы запросить маркер доступа с помощью потока кода устройства.

  1. Создайте файл в каталоге GraphTutorial с именем GraphHelper.cs и добавьте в этот файл следующий код.

    using Azure.Core;
    using Azure.Identity;
    using Microsoft.Graph;
    using Microsoft.Graph.Models;
    using Microsoft.Graph.Me.SendMail;
    
    class GraphHelper
    {
    }
    
  2. Добавьте приведенный ниже код в класс GraphHelper.

    // Settings object
    private static Settings? settings;
    
    // User auth token credential
    private static DeviceCodeCredential? deviceCodeCredential;
    
    // Client configured with user authentication
    private static GraphServiceClient? userClient;
    
    public static void InitializeGraphForUserAuth(
        Settings settings,
        Func<DeviceCodeInfo, CancellationToken, Task> deviceCodePrompt)
    {
        GraphHelper.settings = settings;
    
        var options = new DeviceCodeCredentialOptions
        {
            ClientId = settings.ClientId,
            TenantId = settings.TenantId,
            DeviceCodeCallback = deviceCodePrompt,
        };
    
        deviceCodeCredential = new DeviceCodeCredential(options);
    
        userClient = new GraphServiceClient(deviceCodeCredential, settings.GraphUserScopes);
    }
    
  3. Замените пустую InitializeGraph функцию в Program.cs на следующую.

    void InitializeGraph(Settings settings)
    {
        GraphHelper.InitializeGraphForUserAuth(
            settings,
            (info, cancel) =>
            {
                // Display the device code message to
                // the user. This tells them
                // where to go to sign in and provides the
                // code to use.
                Console.WriteLine(info.Message);
                return Task.FromResult(0);
            });
    }
    

Этот код объявляет два частных свойства: DeviceCodeCredential объект и GraphServiceClient объект . Функция InitializeGraphForUserAuth создает новый экземпляр DeviceCodeCredential, а затем использует его для создания нового экземпляра GraphServiceClient. Каждый раз, когда вызов API выполняется к Microsoft Graph через _userClient, он использует предоставленные учетные данные для получения маркера доступа.

Тестирование DeviceCodeCredential

Затем добавьте код для получения маркера доступа из DeviceCodeCredential.

  1. Добавьте к классу GraphHelper следующую функцию:

    public static async Task<string> GetUserTokenAsync()
    {
        // Ensure credential isn't null
        _ = deviceCodeCredential ??
            throw new NullReferenceException("Graph has not been initialized for user auth");
    
        // Ensure scopes isn't null
        _ = settings?.GraphUserScopes ?? throw new ArgumentNullException("Argument 'scopes' cannot be null");
    
        // Request token with given scopes
        var context = new TokenRequestContext(settings.GraphUserScopes);
        var response = await deviceCodeCredential.GetTokenAsync(context);
        return response.Token;
    }
    
  2. Замените пустую DisplayAccessTokenAsync функцию в Program.cs на следующую.

    async Task DisplayAccessTokenAsync()
    {
        try
        {
            var userToken = await GraphHelper.GetUserTokenAsync();
            Console.WriteLine($"User token: {userToken}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error getting user access token: {ex.Message}");
        }
    }
    
  3. Выполните сборку и запуск приложения. Введите 1 при появлении запроса на выбор параметра. Приложение отображает URL-адрес и код устройства.

    .NET Graph Tutorial
    
    Please choose one of the following options:
    0. Exit
    1. Display access token
    2. List my inbox
    3. Send mail
    4. Make a Graph call
    1
    To sign in, use a web browser to open the page https://microsoft.com/devicelogin and
    enter the code RB2RUD56D to authenticate.
    
  4. Откройте браузер и перейдите по url-адресу. Введите предоставленный код и войдите в систему.

    Важно!

    Помните о всех существующих учетных записях Microsoft 365, которые вошли в браузер при просмотре страницы https://microsoft.com/devicelogin. Используйте функции браузера, такие как профили, гостевой режим или частный режим, чтобы проверить подлинность в качестве учетной записи, которую вы планируете использовать для тестирования.

  5. После завершения вернитесь к приложению, чтобы увидеть маркер доступа.

    Совет

    Только для проверки и отладки можно декодировать маркеры доступа пользователей (только для рабочих или учебных учетных записей) с помощью средства синтаксического анализа токенов Майкрософт в сети по адресу https://jwt.ms. Анализ маркера может оказаться полезным, если при вызове Microsoft Graph возникают ошибки маркера. Например, убедитесь, что scp утверждение в маркере содержит ожидаемые области разрешений Microsoft Graph.

Получение пользователя

Теперь, когда проверка подлинности настроена, вы можете выполнить первый вызов Microsoft API Graph. Добавьте код для получения имени и адреса электронной почты пользователя, прошедшего проверку подлинности.

  1. Откройте ./GraphHelper.cs и добавьте следующую функцию в класс GraphHelper .

    public static Task<User?> GetUserAsync()
    {
        // Ensure client isn't null
        _ = userClient ??
            throw new NullReferenceException("Graph has not been initialized for user auth");
    
        return userClient.Me.GetAsync((config) =>
        {
            // Only request specific properties
            config.QueryParameters.Select = ["displayName", "mail", "userPrincipalName"];
        });
    }
    
  2. Замените пустую GreetUserAsync функцию в Program.cs на следующую.

    async Task GreetUserAsync()
    {
        try
        {
            var user = await GraphHelper.GetUserAsync();
            Console.WriteLine($"Hello, {user?.DisplayName}!");
    
            // For Work/school accounts, email is in Mail property
            // Personal accounts, email is in UserPrincipalName
            Console.WriteLine($"Email: {user?.Mail ?? user?.UserPrincipalName ?? string.Empty}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error getting user: {ex.Message}");
        }
    }
    

Если вы запускаете приложение сейчас, после входа приложение приветствует вас по имени.

Hello, Megan Bowen!
Email: MeganB@contoso.com

Описание кода

Рассмотрим код в GetUserAsync функции. Это всего несколько строк, но есть некоторые ключевые детали, которые следует обратить внимание.

Доступ к "мне"

Функция использует построитель _userClient.Me запросов, который создает запрос к API get user . Этот API доступен двумя способами:

GET /me
GET /users/{user-id}

В этом случае код вызывает конечную точку GET /me API. Эта конечная точка является ярлыком для получения пользователя, прошедшего проверку подлинности, не зная его идентификатора пользователя.

Примечание.

GET /me Так как конечная точка API получает пользователя, прошедшего проверку подлинности, она доступна только для приложений, использующих проверку подлинности пользователя. Приложения для проверки подлинности только для приложений не могут получить доступ к этой конечной точке.

Запрос определенных свойств

Функция использует Select метод в запросе для указания набора необходимых ей свойств. Этот метод добавляет параметр запроса $select в вызов API.

Строго типизированный тип возвращаемого значения

Функция возвращает объект, Microsoft.Graph.User десериализованный из ответа JSON из API. Так как код использует Select, только запрошенные свойства имеют значения в возвращаемом объекте User . Все остальные свойства имеют значения по умолчанию.

Следующее действие