Adicionar autenticação de utilizador a aplicações .NET para Microsoft Graph

Neste artigo, vai adicionar a autenticação de utilizador à aplicação que criou na compilação de aplicações .NET com o Microsoft Graph. Em seguida, utilize a API de utilizador do Microsoft Graph para obter o utilizador autenticado.

Adicionar autenticação de utilizador

A biblioteca de cliente da Identidade do Azure para .NET fornece muitas TokenCredential classes que implementam fluxos de tokens OAuth2. A biblioteca de cliente .NET do Microsoft Graph utiliza essas classes para autenticar chamadas para o Microsoft Graph.

Configurar o cliente do Graph para autenticação de utilizador

Comece por utilizar a DeviceCodeCredential classe para pedir um token de acesso com o fluxo de código do dispositivo.

  1. Crie um novo ficheiro no diretório GraphTutorial com o nome GraphHelper.cs e adicione o seguinte código a esse ficheiro.

    using Azure.Core;
    using Azure.Identity;
    using Microsoft.Graph;
    using Microsoft.Graph.Models;
    using Microsoft.Graph.Me.SendMail;
    
    class GraphHelper
    {
    }
    
  2. Adicione o seguinte código à classe 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. Substitua a função empty InitializeGraph no Program.cs pelo seguinte.

    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);
            });
    }
    

Este código declara duas propriedades privadas, um DeviceCodeCredential objeto e um GraphServiceClient objeto. A InitializeGraphForUserAuth função cria uma nova instância de DeviceCodeCredentiale, em seguida, utiliza essa instância para criar uma nova instância de GraphServiceClient. Sempre que é efetuada uma chamada à API ao Microsoft Graph através do _userClient, utiliza a credencial fornecida para obter um token de acesso.

Testar o DeviceCodeCredential

Em seguida, adicione código para obter um token de acesso a DeviceCodeCredentialpartir do .

  1. Adicione a função a seguir à classe 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. Substitua a função empty DisplayAccessTokenAsync no Program.cs pelo seguinte.

    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. Crie e execute a aplicação. Introduza 1 quando lhe for pedida uma opção. A aplicação apresenta um URL e um código de dispositivo.

    .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. Abra um browser e navegue para o URL apresentado. Introduza o código fornecido e inicie sessão.

    Importante

    Tenha em atenção todas as contas existentes do Microsoft 365 com sessão iniciada no browser ao navegar para https://microsoft.com/devicelogino . Utilize funcionalidades do browser, como perfis, modo de convidado ou modo privado para garantir que se autentica como a conta que pretende utilizar para testes.

  5. Depois de concluído, regresse à aplicação para ver o token de acesso.

    Dica

    Apenas para fins de validação e depuração, pode descodificar tokens de acesso de utilizador (apenas para contas escolares ou profissionais) com o analisador de tokens online da Microsoft em https://jwt.ms. Analisar o token pode ser útil se encontrar erros de token ao chamar o Microsoft Graph. Por exemplo, verificar se a scp afirmação no token contém os âmbitos de permissão esperados do Microsoft Graph.

Obter usuário

Agora que a autenticação está configurada, pode fazer a sua primeira chamada do Microsoft API do Graph. Adicione código para obter o nome e o endereço de e-mail do utilizador autenticado.

  1. Abra ./GraphHelper.cs e adicione a seguinte função à classe 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. Substitua a função empty GreetUserAsync no Program.cs pelo seguinte.

    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}");
        }
    }
    

Se executar a aplicação agora, depois de iniciar sessão na aplicação dá-lhe as boas-vindas pelo nome.

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

Código explicado

Considere o código na GetUserAsync função . São apenas algumas linhas, mas há alguns detalhes importantes a notar.

Aceder a 'eu'

A função utiliza o _userClient.Me construtor de pedidos, que cria um pedido para a API Obter utilizador . Esta API está acessível de duas formas:

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

Neste caso, o código chama o ponto final da GET /me API. Este ponto final é um método de atalho para obter o utilizador autenticado sem saber o respetivo ID de utilizador.

Observação

Uma vez que o GET /me ponto final da API obtém o utilizador autenticado, só está disponível para aplicações que utilizam autenticação de utilizador. As aplicações de autenticação apenas de aplicações não podem aceder a este ponto final.

Pedir propriedades específicas

A função utiliza o Select método no pedido para especificar o conjunto de propriedades de que precisa. Este método adiciona o parâmetro de consulta $select à chamada à API.

Tipo de retorno fortemente escrito

A função devolve um Microsoft.Graph.User objeto serializado da resposta JSON da API. Uma vez que o código utiliza Select, apenas as propriedades pedidas têm valores no objeto devolvido User . Todas as outras propriedades têm valores predefinidos.

Próxima etapa