Tutorial: conectar usuários e chamar o Microsoft Graph no aplicativo da área de trabalho da WPF (Windows Presentation Foundation)

Neste tutorial, você criará um aplicativo nativo .NET da Área de Trabalho do Windows (XAML) que conecta usuários e obtém um token de acesso para chamar a API do Microsoft Graph.

Depois de concluir o guia, seu aplicativo poderá chamar uma API protegida que usa contas pessoais (incluindo o outlook.com, live.com e outros). O aplicativo também usará contas corporativas e de estudante de qualquer empresa ou organização que usa o Microsoft Entra ID.

Neste tutorial:

  • Criar um projeto do WPF (Windows Presentation Foundation) no Visual Studio
  • Instalar a MSAL (Biblioteca de Autenticação da Microsoft) para .NET
  • Registrar o aplicativo
  • Adicionar código para entrada e saída do usuário
  • Adicionar código para chamar a API do Microsoft Graph
  • Testar o aplicativo

Pré-requisitos

Como o aplicativo de exemplo gerado por este guia funciona

Screenshot of how the sample app generated by this tutorial works.

O aplicativo de exemplo que você cria com este guia habilita um aplicativo da Área de Trabalho do Windows que consulta a API do Microsoft Graph ou uma API Web que aceita tokens de um ponto de extremidade da plataforma de identidade da Microsoft. Para esse cenário, você adiciona um token às solicitações HTTP por meio do cabeçalho de Autorização. A MSAL (Biblioteca de Autenticação da Microsoft) lida com a aquisição e a renovação de tokens.

Manipulando a aquisição de token para acessar APIs Web protegidas

Após a autenticação do usuário, o aplicativo de exemplo receberá um token que pode ser usado para consultar a API do Microsoft Graph ou uma API Web protegida pela plataforma de identidade da Microsoft.

APIs, como o Microsoft Graph, exigem um token para permitir o acesso a recursos específicos. Por exemplo, um token é necessário para ler o perfil ou acessar o calendário de um usuário ou enviar um email. O aplicativo pode solicitar um token de acesso usando a MSAL para acessar esses recursos especificando escopos de API. Esse token de acesso é então adicionado ao cabeçalho de Autorização HTTP de cada chamada feita no recurso protegido.

A MSAL gerencia o armazenamento em cache e a atualização de tokens de acesso para você, de forma que o aplicativo não precise fazer isso.

Pacotes NuGet

Este guia usa os seguintes pacotes NuGet:

Biblioteca Descrição
Microsoft.Identity.Client Biblioteca de Autenticação da Microsoft (MSAL.NET)

Configurar o seu projeto

Nesta seção, você criará um novo projeto para demonstrar como integrar um aplicativo .NET da Área de Trabalho do Windows (XAML) com a opção Entrar com uma Conta Microsoft, de maneira que o aplicativo possa consultar APIs Web que exigem um token.

O aplicativo que você criará exibirá um botão que chamará a API do Microsoft Graph, uma área para exibir os resultados e um botão de saída.

Observação

Prefere baixar este projeto do Visual Studio de exemplo? Baixe um projeto e vá para a Etapa de configuração para configurar o exemplo de código antes de executá-lo.

Crie o aplicativo usando as seguintes etapas:

  1. Abra o Visual Studio
  2. Na janela inicial, selecione Criar um novo projeto.
  3. Na lista suspensa Todos os idiomas, selecione C#.
  4. Pesquise e escolha o modelo Aplicativo WPF (.NET Framework) e selecione Avançar.
  5. Na caixa Nome do projeto, insira um nome como Win-App-calling-MsGraph.
  6. Escolha um Local para o projeto ou aceite a opção padrão.
  7. No Framework, selecione .NET Framework 4.8.
  8. Selecione Criar.

Adicionar MSAL ao seu projeto

  1. No Visual Studio, selecione Ferramentas>Gerenciador de Pacotes do NuGet>Console do Gerenciador de Pacotes.

  2. Na janela do Console do Gerenciador de Pacotes, cole o seguinte comando do Azure PowerShell:

    Install-Package Microsoft.Identity.Client -Pre
    

Registre seu aplicativo

Dica

As etapas neste artigo podem variar ligeiramente com base no portal do qual você começa.

Para registrar e configurar seu aplicativo, siga estas etapas:

  1. Faça login no Centro de administração do Microsoft Entra como pelo menos um Desenvolvedor de aplicativos.
  2. Se você tiver acesso a vários locatários, use o ícone de Configurações no menu superior para alternar para o locatário no qual deseja registrar o aplicativo no menu Diretórios + assinaturas.
  3. Navegue até Identidade>Aplicativos>Registros do aplicativo.
  4. Selecione Novo registro.
  5. Insira um Nome para seu aplicativo, por exemplo, Win-App-calling-MsGraph. Os usuários do seu aplicativo podem ver esse nome e você pode alterá-lo mais tarde.
  6. Na seção Tipos de conta com suporte, selecione Contas em qualquer diretório organizacional (Qualquer diretório do Microsoft Entra – Multilocatário) e contas Microsoft pessoais (por exemplo, Skype, Xbox).
  7. Selecione Registrar.
  8. Em Gerenciar, escolha Autenticação>Adicionar uma plataforma.
  9. Selecione Aplicativos móveis e da área de trabalho.
  10. Na seção URIs de Redirecionamento, selecione https://login.microsoftonline.com/common/oauth2/nativeclient.
  11. Selecione Configurar.

Adicionar o código para inicializar a MSAL

Nesta etapa, você cria uma classe para lidar com a interação com a MSAL, por exemplo, com a manipulação de tokens.

  1. Abra o arquivo App.xaml.cs e adicione a referência para a MSAL à classe:

    using Microsoft.Identity.Client;
    
  2. Atualize a classe app para o seguinte:

    public partial class App : Application
    {
        static App()
        {
            _clientApp = PublicClientApplicationBuilder.Create(ClientId)
                .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
                .WithDefaultRedirectUri()
                .Build();
        }
    
        // Below are the clientId (Application Id) of your app registration and the tenant information.
        // You have to replace:
        // - the content of ClientID with the Application Id for your app registration
        // - the content of Tenant by the information about the accounts allowed to sign-in in your application:
        //   - For Work or School account in your org, use your tenant ID, or domain
        //   - for any Work or School accounts, use `organizations`
        //   - for any Work or School accounts, or Microsoft personal account, use `common`
        //   - for Microsoft Personal account, use consumers
        private static string ClientId = "Enter_the_Application_Id_here";
    
        private static string Tenant = "common";
    
        private static IPublicClientApplication _clientApp ;
    
        public static IPublicClientApplication PublicClientApp { get { return _clientApp; } }
    }
    

Criar a interface do usuário do aplicativo

Esta seção mostra como um aplicativo pode consultar um servidor de back-end protegido como o Microsoft Graph.

Um arquivo MainWindow.xaml será criado automaticamente como parte de seu modelo de projeto. Abra esse arquivo e substitua o nó <Grade> do aplicativo pelo seguinte código:

<Grid>
    <StackPanel Background="Azure">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
            <Button x:Name="CallGraphButton" Content="Call Microsoft Graph API" HorizontalAlignment="Right" Padding="5" Click="CallGraphButton_Click" Margin="5" FontFamily="Segoe Ui"/>
            <Button x:Name="SignOutButton" Content="Sign-Out" HorizontalAlignment="Right" Padding="5" Click="SignOutButton_Click" Margin="5" Visibility="Collapsed" FontFamily="Segoe Ui"/>
        </StackPanel>
        <Label Content="API Call Results" Margin="0,0,0,-5" FontFamily="Segoe Ui" />
        <TextBox x:Name="ResultText" TextWrapping="Wrap" MinHeight="120" Margin="5" FontFamily="Segoe Ui"/>
        <Label Content="Token Info" Margin="0,0,0,-5" FontFamily="Segoe Ui" />
        <TextBox x:Name="TokenInfoText" TextWrapping="Wrap" MinHeight="70" Margin="5" FontFamily="Segoe Ui"/>
    </StackPanel>
</Grid>

Usar a MSAL para obter um token para a API do Microsoft Graph

Nesta seção, você usará a MSAL para obter um token da API do Microsoft Graph.

  1. No arquivo MainWindow.xaml.cs, adicione a referência da MSAL à classe:

    using Microsoft.Identity.Client;
    
  2. Substitua o código da classe MainWindow pelo seguinte código:

    public partial class MainWindow : Window
    {
        //Set the API Endpoint to Graph 'me' endpoint
        string graphAPIEndpoint = "https://graph.microsoft.com/v1.0/me";
    
        //Set the scope for API call to user.read
        string[] scopes = new string[] { "user.read" };
    
    
        public MainWindow()
        {
            InitializeComponent();
        }
    
      /// <summary>
        /// Call AcquireToken - to acquire a token requiring user to sign-in
        /// </summary>
        private async void CallGraphButton_Click(object sender, RoutedEventArgs e)
        {
            AuthenticationResult authResult = null;
            var app = App.PublicClientApp;
            ResultText.Text = string.Empty;
            TokenInfoText.Text = string.Empty;
    
            var accounts = await app.GetAccountsAsync();
            var firstAccount = accounts.FirstOrDefault();
    
            try
            {
                authResult = await app.AcquireTokenSilent(scopes, firstAccount)
                    .ExecuteAsync();
            }
            catch (MsalUiRequiredException ex)
            {
                // A MsalUiRequiredException happened on AcquireTokenSilent.
                // This indicates you need to call AcquireTokenInteractive to acquire a token
                System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");
    
                try
                {
                    authResult = await app.AcquireTokenInteractive(scopes)
                        .WithAccount(accounts.FirstOrDefault())
                        .WithPrompt(Prompt.SelectAccount)
                        .ExecuteAsync();
                }
                catch (MsalException msalex)
                {
                    ResultText.Text = $"Error Acquiring Token:{System.Environment.NewLine}{msalex}";
                }
            }
            catch (Exception ex)
            {
                ResultText.Text = $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}";
                return;
            }
    
            if (authResult != null)
            {
                ResultText.Text = await GetHttpContentWithToken(graphAPIEndpoint, authResult.AccessToken);
                DisplayBasicTokenInfo(authResult);
                this.SignOutButton.Visibility = Visibility.Visible;
            }
        }
        }
    

Mais informações

Obter um token de usuário interativamente

A chamada ao método AcquireTokenInteractive resulta em uma janela que solicita a conexão do usuário. Os aplicativos geralmente exigem que os usuários façam logon interativamente na primeira vez que precisarem acessar um recurso protegido. Eles também podem precisar se conectar quando ocorre uma falha em uma operação silenciosa para adquirir um token (por exemplo, quando a senha de um usuário expirou).

Obter um token de usuário no modo silencioso

O método AcquireTokenSilent manipula as aquisições e renovações de tokens sem nenhuma interação do usuário. Depois que AcquireTokenInteractive for executado pela primeira vez, AcquireTokenSilent será o método comum usado para obter tokens que acessam recursos protegidos nas próximas chamadas – já que as chamadas para solicitar ou renovar tokens são feitas no modo silencioso.

Eventualmente, o método AcquireTokenSilent poderá falhar. Os motivos da falha podem ser que o usuário se desconectou ou alterou a senha em outro dispositivo. Quando a MSAL detecta que o problema pode ser resolvido com a solicitação de uma ação interativa, ela dispara uma exceção MsalUiRequiredException. O aplicativo pode tratar essa exceção de duas maneiras:

  • Ele pode fazer uma chamada para AcquireTokenInteractive imediatamente. Essa chamada resulta na solicitação de entrada do usuário. Esse padrão é usado em aplicativos online em que não há conteúdo offline disponível ao usuário. O exemplo gerado por esta configuração segue este padrão, que poderá ser visto em ação na primeira vez que o exemplo for executado.

  • Como nenhum usuário usou o aplicativo, PublicClientApp.Users.FirstOrDefault() conterá um valor nulo e uma exceção MsalUiRequiredException será lançada.

  • Em seguida, o código no exemplo trata a exceção chamando AcquireTokenInteractive, o que resulta na solicitação de entrada do usuário.

  • Ele também pode apresentar uma indicação visual aos usuários informando que uma entrada interativa é necessária, para que eles possam selecionar a hora certa de entrar. O aplicativo também pode tentar novamente AcquireTokenSilent mais tarde. Frequentemente, esse padrão é usado quando os usuários podem usar outras funcionalidades do aplicativo sem interrupções. Por exemplo, quando o conteúdo offline está disponível no aplicativo. Nesse caso, os usuários podem decidir quando desejam entrar para acessar o recurso protegido ou para atualizar as informações desatualizadas. Como alternativa, o aplicativo pode optar por repetir AcquireTokenSilent quando a rede é restaurada depois de estar temporariamente indisponível.

Chamar a API do Microsoft Graph usando o token obtido recentemente

Adicione o seguinte método a MainWindow.xaml.cs. O método é usado para fazer uma solicitação GET na API do Graph usando um cabeçalho de autorização:

/// <summary>
/// Perform an HTTP GET request to a URL using an HTTP Authorization header
/// </summary>
/// <param name="url">The URL</param>
/// <param name="token">The token</param>
/// <returns>String containing the results of the GET operation</returns>
public async Task<string> GetHttpContentWithToken(string url, string token)
{
    var httpClient = new System.Net.Http.HttpClient();
    System.Net.Http.HttpResponseMessage response;
    try
    {
        var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
        //Add the token in Authorization header
        request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        response = await httpClient.SendAsync(request);
        var content = await response.Content.ReadAsStringAsync();
        return content;
    }
    catch (Exception ex)
    {
        return ex.ToString();
    }
}

Mais informações sobre como fazer uma chamada REST em uma API protegida

Neste exemplo de aplicativo, use o método GetHttpContentWithToken para fazer uma solicitação HTTP GET em um recurso protegido que exige um token e, em seguida, retornar o conteúdo para o chamador. Esse método adiciona o token adquirido no cabeçalho de Autorização HTTP. Para este exemplo, o recurso é o ponto de extremidade me da API do Microsoft Graph – que exibe as informações de perfil do usuário.

Adicionar um método para desconectar um usuário

Para desconectar um usuário, adicione o seguinte método ao arquivo MainWindow.xaml.cs:

/// <summary>
/// Sign out the current user
/// </summary>
private async void SignOutButton_Click(object sender, RoutedEventArgs e)
{
    var accounts = await App.PublicClientApp.GetAccountsAsync();

    if (accounts.Any())
    {
        try
        {
            await App.PublicClientApp.RemoveAsync(accounts.FirstOrDefault());
            this.ResultText.Text = "User has signed-out";
            this.CallGraphButton.Visibility = Visibility.Visible;
            this.SignOutButton.Visibility = Visibility.Collapsed;
        }
        catch (MsalException ex)
        {
            ResultText.Text = $"Error signing-out user: {ex.Message}";
        }
    }
}

Mais informações sobre como desconectar o usuário

O método SignOutButton_Click remove os usuários do cache de usuário da MSAL, o que diz para a MSAL esquecer o usuário atual, de modo que uma solicitação futura de aquisição de um token seja bem sucedida apenas se for feita para ser interativa.

Embora o aplicativo neste exemplo ofereça suporte a um único usuário, a MSAL oferece suporte a cenários em que várias contas podem estar conectadas ao mesmo tempo. Um exemplo é um aplicativo de email onde um usuário tem várias contas.

Exibir informações básicas de token

Para exibir informações básicas sobre o token, adicione o seguinte método ao arquivo MainWindow.xaml.cs:

/// <summary>
/// Display basic information contained in the token
/// </summary>
private void DisplayBasicTokenInfo(AuthenticationResult authResult)
{
    TokenInfoText.Text = "";
    if (authResult != null)
    {
        TokenInfoText.Text += $"Username: {authResult.Account.Username}" + Environment.NewLine;
        TokenInfoText.Text += $"Token Expires: {authResult.ExpiresOn.ToLocalTime()}" + Environment.NewLine;
    }
}

Mais informações

Além do token de acesso que é usado para chamar a API do Microsoft Graph, após o usuário se autenticar, a MSAL também obterá um token de ID. Esse token contém um pequeno subconjunto de informações pertinentes aos usuários. O método DisplayBasicTokenInfo exibe as informações básicas contidas no token. Por exemplo, ele mostra o nome de exibição do usuário e a ID, bem como a data de expiração do token e a cadeia de caracteres que representa o token de acesso em si. Pressione o botão Chamar API do Microsoft Graph várias vezes e veja que o mesmo token foi reutilizado em solicitações posteriores. Você também pode ver a data de validade sendo estendida quando a MSAL decidir que é hora de renovar o token.

Testar seu código

Para executar o projeto no Visual Studio, selecione F5. Seu aplicativo MainWindow é exibido, conforme mostrado aqui:

Test your application.

Na primeira vez em que você executar o aplicativo e selecionar o botão Chamar a API do Microsoft Graph você será solicitado a entrar. Use uma conta do Microsoft Entra (conta corporativa ou de estudante) ou uma conta da Microsoft (live.com, outlook.com) para testá-lo.

Sign in to the application.

Na primeira vez que você entrar no seu aplicativo, você também será solicitado a fornecer autorização para permitir que o aplicativo acesse seu perfil e o conecte, como mostrado aqui:

Provide your consent for application access.

Veja os resultados de aplicativo

Depois de entrar, você deverá ver as informações do perfil do usuário retornadas pela chamada da API do Microsoft Graph. Os resultados são exibidos na caixa Resultados da Chamada da API. As informações básicas sobre o token que foi adquirido através da chamada para AcquireTokenInteractive ou AcquireTokenSilent devem estar visíveis na caixa Informações de Token. Os resultados contêm as propriedades a seguir:

Propriedade Formatar Descrição
Nome de usuário user@domain.com O nome de usuário que é usado para identificar o usuário.
O Token Expira Datetime A data e hora em que o token expira. MSAL estende a data de validade renovando o token, conforme necessário.

Mais informações sobre escopos e permissões delegadas

A API do Microsoft Graph requer o escopo user.read para ler o perfil do usuário. Esse escopo é adicionado automaticamente, por padrão, a cada aplicativo que é registrado no Portal de Registro de Aplicativos. Outras APIs do Microsoft Graph, bem como APIs personalizadas do servidor de back-end, podem exigir escopos adicionais. A API do Microsoft Graph requer o escopo Calendars.Read para listar os calendários do usuário.

Para acessar os calendários do usuário no contexto de um aplicativo, adicione a permissão delegada Calendars.Read às informações de registro do aplicativo. Em seguida, adicione o escopo Calendars.Read à chamada acquireTokenSilent.

Observação

Talvez o usuário precise fornecer autorizações adicionais à medida que o número de escopos aumentar.

Ajuda e suporte

Se precisar de ajuda, quiser relatar um problema ou desejar saber mais sobre as opções de suporte, confira Ajuda e suporte para desenvolvedores.

Próximas etapas

Saiba mais sobre como criar aplicativos de área de trabalho que chamam APIs Web protegidas em nossa série de cenários com várias partes: