Tutorial: Iniciar sessão de utilizadores e chamar o Microsoft Graph na aplicação de ambiente de trabalho Windows Presentation Foundation (WPF)
Neste tutorial, você cria um aplicativo nativo do Windows Desktop .NET (XAML) que entra nos usuários e obtém um token de acesso para chamar a API do Microsoft Graph.
Quando você concluir o guia, seu aplicativo poderá chamar uma API protegida que usa contas pessoais (incluindo outlook.com, live.com e outros). O aplicativo também usará contas corporativas e escolares de qualquer empresa ou organização que use o Microsoft Entra ID.
Neste tutorial:
- Criar um projeto do Windows Presentation Foundation (WPF) no Visual Studio
- Instalar a Biblioteca de Autenticação da Microsoft (MSAL) para .NET
- Registar a candidatura
- Adicionar código para dar suporte ao login e logout do usuário
- Adicionar código para chamar a API do Microsoft Graph
- Testar a aplicação
Pré-requisitos
Como funciona o aplicativo de exemplo gerado por este guia
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 da Web que aceita tokens de um ponto de extremidade da plataforma de identidade da Microsoft. Para esse cenário, você adiciona um token a solicitações HTTP por meio do cabeçalho Authorization. A Biblioteca de Autenticação da Microsoft (MSAL) lida com a aquisição e renovação de tokens.
Manipulando a aquisição de tokens para acessar APIs da Web protegidas
Depois que o usuário é autenticado, o aplicativo de exemplo recebe um token que você pode usar para consultar a API do Microsoft Graph ou uma API da 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 de um usuário, acessar o calendário de um usuário ou enviar e-mails. Seu aplicativo pode solicitar um token de acesso usando o MSAL para acessar esses recursos especificando escopos de API. Esse token de acesso é então adicionado ao cabeçalho de Autorização HTTP para cada chamada feita no recurso protegido.
O MSAL gerencia o cache e a atualização de tokens de acesso para você, para que seu aplicativo não precise.
Pacotes NuGet
Este guia usa os seguintes pacotes NuGet:
Biblioteca | Description |
---|---|
Microsoft.Identity.Client | Biblioteca de Autenticação da Microsoft (MSAL.NET) |
Configure o seu projeto
Nesta seção, você cria um novo projeto para demonstrar como integrar um aplicativo .NET da Área de Trabalho do Windows (XAML) com o Sign-In com a Microsoft para que o aplicativo possa consultar APIs da Web que exigem um token.
O aplicativo que você cria exibe um botão que chamará a API do Microsoft Graph, uma área para exibir os resultados e um botão de saída.
Nota
Prefere baixar o projeto Visual Studio deste exemplo? Baixe um projeto e pule para a etapa Configuração para configurar o exemplo de código antes de executá-lo.
Crie o aplicativo usando as seguintes etapas:
- Abrir o Visual Studio
- Na janela Iniciar, selecione Criar um novo projeto.
- Na lista suspensa Todos os idiomas, selecione C#.
- Procure e escolha o modelo Aplicativo WPF (.NET Framework) e selecione Avançar.
- Na caixa Nome do projeto , digite um nome como Win-App-calling-MsGraph.
- Escolha um local para o projeto ou aceite a opção padrão.
- No Framework, selecione .NET Framework 4.8.
- Selecione Criar.
Adicionar MSAL ao seu projeto
No Visual Studio, selecione Ferramentas>Gestor de pacote NuGet>Consola do Gestor de Pacotes.
Na janela Console do Gerenciador de Pacotes, cole o seguinte comando do Azure PowerShell:
Install-Package Microsoft.Identity.Client -Pre
Registar a aplicação
Gorjeta
As etapas neste artigo podem variar ligeiramente com base no portal a partir do qual você começou.
Para registar e configurar a sua aplicação, siga estes passos:
- Entre no centro de administração do Microsoft Entra como pelo menos um desenvolvedor de aplicativos.
- Se você tiver acesso a vários locatários, use o ícone Configurações no menu superior para alternar para o locatário no qual deseja registrar o aplicativo no menu Diretórios + assinaturas.
- Navegue até Registros do aplicativo Identity>Applications>.
- Selecione Novo registo.
- Introduza um Nome para a sua aplicação, por exemplo
Win-App-calling-MsGraph
. Os usuários do seu aplicativo podem ver esse nome e você pode alterá-lo mais tarde. - Na seção Tipos de conta suportados, selecione Contas em qualquer diretório organizacional (Qualquer diretório Microsoft Entra - Multilocatário) e contas pessoais da Microsoft (por exemplo, Skype, Xbox).
- Selecione Registar.
- Em Gerir, selecione Autenticação>Adicionar uma plataforma.
- Selecione Aplicações móveis e de ambiente de trabalho.
- Na seção Redirecionar URIs, selecione https://login.microsoftonline.com/common/oauth2/nativeclient.
- Selecione Configurar.
Adicione o código para inicializar o MSAL
Nesta etapa, você cria uma classe para manipular a interação com o MSAL, como a manipulação de tokens.
Abra o ficheiro App.xaml.cs e, em seguida, adicione a referência para MSAL à classe:
using Microsoft.Identity.Client;
Atualize a classe do aplicativo 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 back-end protegido, como o Microsoft Graph.
Um arquivo MainWindow.xaml é criado automaticamente como parte do seu modelo de projeto. Abra este ficheiro e, em seguida, substitua o nó Grid> da <aplicação 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>
Use o MSAL para obter um token para a API do Microsoft Graph
Nesta seção, você usa o MSAL para obter um token para a API do Microsoft Graph.
No arquivo MainWindow.xaml.cs, adicione a referência para MSAL à classe:
using Microsoft.Identity.Client;
Substitua o código de
MainWindow
classe 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 utilizador interativamente
Chamar o AcquireTokenInteractive
método resulta em uma janela que solicita que os usuários entrem. Os aplicativos geralmente exigem que os usuários entrem interativamente na primeira vez que precisam acessar um recurso protegido. Eles também podem precisar entrar quando uma operação silenciosa para adquirir um token falhar (por exemplo, quando a senha de um usuário expirou).
Obter um token de utilizador automaticamente
O AcquireTokenSilent
método lida com aquisições e renovações de token sem qualquer interação do usuário. Depois AcquireTokenInteractive
é executado pela primeira vez, AcquireTokenSilent
é o método usual a ser usado para obter tokens que acessam recursos protegidos para chamadas subsequentes, porque as chamadas para solicitar ou renovar tokens são feitas silenciosamente.
Eventualmente, o AcquireTokenSilent
método pode falhar. Os motivos para a falha podem ser que o usuário tenha saído ou alterado sua senha em outro dispositivo. Quando o MSAL deteta que o problema pode ser resolvido exigindo uma ação interativa, ele dispara uma MsalUiRequiredException
exceção. Seu aplicativo pode lidar com essa exceção de duas maneiras:
Pode fazer uma chamada contra
AcquireTokenInteractive
imediatamente. Essa chamada resulta em solicitar que o usuário entre. Esse padrão é usado em aplicativos online onde não há conteúdo offline disponível para o usuário. O exemplo gerado por essa configuração segue esse padrão, que pode ser visto em ação na primeira vez que você executar o exemplo.Como nenhum usuário usou o aplicativo,
PublicClientApp.Users.FirstOrDefault()
contém um valor nulo e umaMsalUiRequiredException
exceção é lançada.O código no exemplo manipula a exceção chamando
AcquireTokenInteractive
, o que resulta em solicitar que o usuário entre.Em vez disso, ele pode apresentar uma indicação visual aos usuários de que um login interativo é necessário, para que eles possam selecionar o momento certo para entrar. Ou o aplicativo pode tentar
AcquireTokenSilent
novamente mais tarde. Esse padrão é freqüentemente usado quando os usuários podem usar outras funcionalidades do aplicativo sem interrupção. 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 atualizar as informações desatualizadas. Como alternativa, o aplicativo pode decidir tentarAcquireTokenSilent
novamente quando a rede for restaurada depois de ter ficado temporariamente indisponível.
Chame a API do Microsoft Graph usando o token que você acabou de obter
Adicione o seguinte novo método ao seu MainWindow.xaml.cs
. O método é usado para fazer uma solicitação contra a GET
API do Graph usando um cabeçalho Authorization:
/// <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 relação a uma API protegida
Neste aplicativo de exemplo, você usa o GetHttpContentWithToken
método para fazer uma solicitação HTTP GET
em relação a um recurso protegido que requer um token e, em seguida, retornar o conteúdo para o chamador. Este método adiciona o token adquirido no cabeçalho HTTP Authorization. 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 sair de um usuário
Para sair de um usuário, adicione o seguinte método ao seu MainWindow.xaml.cs
arquivo:
/// <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 a saída do usuário
O SignOutButton_Click
método remove os usuários do cache de usuário do MSAL, que efetivamente diz ao MSAL para esquecer o usuário atual para que uma solicitação futura para adquirir um token seja bem-sucedida somente se ele for feito para ser interativo.
Embora o aplicativo neste exemplo ofereça suporte a usuários únicos, o MSAL oferece suporte a cenários em que várias contas podem ser conectadas ao mesmo tempo. Um exemplo é um aplicativo de e-mail onde um usuário tem várias contas.
Exibir informações básicas do token
Para exibir informações básicas sobre o token, adicione o seguinte método ao seu 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 usado para chamar a API do Microsoft Graph, depois que o usuário entrar, o MSAL também obtém um token de ID. Esse token contém um pequeno subconjunto de informações pertinentes aos usuários. O DisplayBasicTokenInfo
método exibe as informações básicas contidas no token. Por exemplo, ele exibe o nome de exibição e ID do usuário, bem como a data de expiração do token e a cadeia de caracteres que representa o próprio token de acesso. Você pode selecionar o botão Chamar a API do Microsoft Graph várias vezes e ver que o mesmo token foi reutilizado para solicitações subsequentes. Você também pode ver a data de expiração sendo estendida quando a MSAL decidir que é hora de renovar o token.
Teste o seu código
Para executar seu projeto, no Visual Studio, selecione F5. Seu aplicativo MainWindow é exibido.
Na primeira vez que você executar o aplicativo e selecionar o botão Chamar API do Microsoft Graph , você será solicitado a entrar. Use uma conta Microsoft Entra (conta corporativa ou de estudante) ou uma conta da Microsoft (live.com, outlook.com) para testá-la.
Fornecer consentimento para acesso ao aplicativo
Na primeira vez que iniciar sessão na sua aplicação, ser-lhe-á também pedido que forneça consentimento para permitir que a aplicação aceda ao seu perfil e inicie sessão, conforme mostrado aqui:
Ver resultados da aplicação
Depois de entrar, você verá as informações de perfil de usuário retornadas pela chamada para a API do Microsoft Graph. Os resultados são exibidos na caixa Resultados da chamada de API. Informações básicas sobre o token que foi adquirido por meio da chamada para AcquireTokenInteractive
ou AcquireTokenSilent
deve estar visível na caixa Informações do token. Os resultados contêm as seguintes propriedades:
Property | Formato | Description |
---|---|---|
Nome de utilizador | user@domain.com | O nome de usuário que é usado para identificar o usuário. |
Token expira | DateTime | O momento em que o token expira. A MSAL estende a data de expiração 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 de um usuário. Esse escopo é adicionado automaticamente por padrão em todos os aplicativos registrados no Portal de Registro de Aplicativos. Outras APIs para o Microsoft Graph e APIs personalizadas para seu servidor back-end podem exigir mais escopos. 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 à acquireTokenSilent
chamada.
Nota
O usuário pode ser solicitado a fornecer consentimentos adicionais à medida que você aumenta o número de escopos.
Ajuda e suporte
Se precisar de ajuda, quiser comunicar um problema ou quiser saber mais sobre as suas opções de suporte, consulte Ajuda e suporte para programadores.
Próximo passo
Saiba mais sobre como criar aplicativos da área de trabalho que chamam APIs da Web protegidas em nossa série de cenários com várias partes: