Usare Microsoft Authentication Library (MSAL) per ottenere un token per l'API Microsoft GraphUse the Microsoft Authentication Library (MSAL) to get a token for the Microsoft Graph API

Questa sezione illustra come usare MSAL per ottenere un token per l'API Microsoft Graph.This section shows how to use MSAL to get a token the Microsoft Graph API.

  1. In MainWindow.xaml.cs aggiungere alla classe il riferimento della libreria MSAL:In MainWindow.xaml.cs, add the reference for MSAL library to the class:
using Microsoft.Identity.Client;
  1. Sostituire il codice della classe MainWindow con:Replace MainWindow class code with:
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 AcquireTokenAsync - to acquire a token requiring user to sign-in
    /// </summary>
    private async void CallGraphButton_Click(object sender, RoutedEventArgs e)
    {
        AuthenticationResult authResult = null;

        try
        {
            authResult = await App.PublicClientApp.AcquireTokenSilentAsync(_scopes, App.PublicClientApp.Users.FirstOrDefault());
        }
        catch (MsalUiRequiredException ex)
        {
            // A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token
            System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");

            try
            {
                authResult = await App.PublicClientApp.AcquireTokenAsync(_scopes);
            }
            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;
        }
    }
}

Altre informazioniMore Information

Acquisizione di un token utente in modo interattivoGetting a user token interactive

Se si chiama il metodo AcquireTokenAsync, viene visualizzata una finestra in cui si chiede all'utente di eseguire l'accesso.Calling the AcquireTokenAsync method results in a window prompting the user to sign in. In genere, le applicazioni chiedono agli utenti di accedere in modo interattivo la prima volta che devono accedere a una risorsa protetta o quando un'operazione invisibile di acquisizione di un token ha esito negativo (ad esempio, perché la password dell'utente è scaduta).Applications usually require a user to sign in interactively the first time they need to access a protected resource, or when a silent operation to acquire a token fails (e.g. the user’s password expired).

Acquisizione di un token utente in modo invisibileGetting a user token silently

AcquireTokenSilentAsync gestisce le acquisizioni e i rinnovi dei token senza alcuna interazione da parte dell'utente.AcquireTokenSilentAsync handles token acquisitions and renewal without any user interaction. Dopo aver eseguito AcquireTokenAsync la prima volta, per le chiamate successive il metodo generalmente usato per ottenere token per accedere a risorse protette è AcquireTokenSilentAsync: le chiamate per richiedere o rinnovare token vengono effettuate in modo invisibile per l'utente.After AcquireTokenAsync is executed for the first time, AcquireTokenSilentAsync is the usual method used to obtain tokens used to access protected resources for subsequent calls - as calls to request or renew tokens are made silently. Alla fine, tuttavia, AcquireTokenSilentAsync avrà esito negativo perché, ad esempio, l'utente si sarà disconnesso o avrà modificato la password in un altro dispositivo.Eventually, AcquireTokenSilentAsync will fail – e.g. the user has signed out, or has changed their password on another device. Se MSAL rileva che il problema può essere risolto richiedendo un'azione interattiva, viene attivata una MsalUiRequiredException.When MSAL detects that the issue can be resolved by requiring an interactive action, it fires an MsalUiRequiredException. L'applicazione può gestire questa eccezione in due modi:Your application can handle this exception in two ways:

  1. Effettuare subito una chiamata a AcquireTokenAsync, in modo da chiedere all'utente di eseguire l'accesso.Make a call against AcquireTokenAsync immediately, which results in prompting the user to sign-in. Questo criterio viene usato in genere nelle applicazioni online in cui non sono disponibili contenuti offline per l'utente.This pattern is usually used in online applications where there is no offline content in the application available for the user. L'esempio generato in questa installazione guidata usa questo criterio, che è possibile vedere in pratica la prima volta che si esegue l'esempio: poiché nessun utente ha mai usato l'applicazione, PublicClientApp.Users.FirstOrDefault() conterrà un valore null e verrà generata un'eccezione MsalUiRequiredException.The sample generated by this guided setup uses this pattern: you can see it in action the first time you execute the sample: because no user ever used the application, PublicClientApp.Users.FirstOrDefault() will contain a null value, and an MsalUiRequiredException exception will be thrown. Il codice dell'esempio gestirà quindi l'eccezione chiamando AcquireTokenAsync, ovvero chiedendo all'utente di eseguire l'eccesso.The code in the sample then handles the exception by calling AcquireTokenAsync resulting in prompting the user to sign-in.

  2. Le applicazioni possono anche generare un'indicazione visiva per informare l'utente che è necessario un accesso interattivo, in modo da consentire di scegliere il momento più opportuno per accedere. In alternativa, l'applicazione riproverà a eseguire AcquireTokenSilentAsync in un secondo momento.Applications can also make a visual indication to the user that an interactive sign-in is required, so the user can select the right time to sign in, or the application can retry AcquireTokenSilentAsync at a later time. Questo metodo viene usato in genere quando l'utente può accedere ad altre funzionalità dell'applicazione senza essere interrotto, ad esempio quando nell'applicazione sono disponibili contenuti offline.This is usually used when the user can use other functionality of the application without being disrupted - for example, there is offline content available in the application. In questo caso, l'utente può decidere quando eseguire l'accesso per accedere alla risorsa protetta o per aggiornare informazioni obsolete. In alternativa, l'applicazione può decidere di riprovare a eseguire AcquireTokenSilentAsync se la rete viene ripristinata dopo essere stata temporaneamente non disponibile.In this case, the user can decide when they want to sign in to access the protected resource, or to refresh the outdated information, or your application can decide to retry AcquireTokenSilentAsync when network is restored after being unavailable temporarily.

Chiamare l'API Microsoft Graph usando il token appena ottenutoCall the Microsoft Graph API using the token you just obtained

  1. Aggiungere il nuovo metodo seguente al file MainWindow.xaml.cs.Add the new method below to your MainWindow.xaml.cs. Questo metodo consente di eseguire una richiesta GET all'API Graph usando un'intestazione di autorizzazione:The method is used to make a GET request against Graph API using an Authorize header:
/// <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();
    }
}

Altre informazioni sull'esecuzione di una chiamata REST a un'API protettaMore information on making a REST call against a protected API

In questa applicazione di esempio, viene usato il metodo GetHttpContentWithToken per eseguire una richiesta HTTP GET a una risorsa protetta che richiede un token e restituisce il contenuto al chiamante.In this sample application, the GetHttpContentWithToken method is used to make an HTTP GET request against a protected resource that requires a token and then return the content to the caller. Questo metodo aggiunge il token acquisito nell'intestazione di autorizzazione HTTP.This method adds the acquired token in the HTTP Authorization header. Per questo esempio, la risorsa è l'endpoint me dell'API Microsoft Graph, che consente di visualizzare informazioni sul profilo dell'utente.For this sample, the resource is the Microsoft Graph API me endpoint – which displays the user's profile information.

Aggiungere un metodo per disconnettere l'utenteAdd a method to sign out the user

  1. Aggiungere il metodo seguente al file MainWindow.xaml.cs per disconnettere l'utente:Add the following method to your MainWindow.xaml.cs to sign out the user:
/// <summary>
/// Sign out the current user
/// </summary>
private void SignOutButton_Click(object sender, RoutedEventArgs e)
{
    if (App.PublicClientApp.Users.Any())
    {
        try
        {
            App.PublicClientApp.Remove(App.PublicClientApp.Users.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}";
        }
    }
}

Altre informazioni sulla disconnessioneMore info on Sign-Out

L'oggetto SignOutButton_Click rimuove l'utente dalla cache utente di MSAL: in questo modo, MSAL dimenticherà l'utente corrente e un'eventuale richiesta futura di acquisizione di un token riuscirà solo effettuata in modo interattivo.SignOutButton_Click removes the user from MSAL user cache – this will effectively tell MSAL to forget the current user so a future request to acquire a token will only succeed if it is made to be interactive. Anche se l'applicazione in questo esempio supporta un unico utente, MSAL supporta anche scenari in cui è possibile eseguire contemporaneamente l'accesso di più account, come nel caso di un'applicazione di posta elettronica in cui un utente dispone di più account.Although the application in this sample supports a single user, MSAL supports scenarios where multiple accounts can be signed-in at the same time – an example is an email application where a user has multiple accounts.

Visualizzare informazioni di base sul tokenDisplay Basic Token Information

  1. Aggiungere il metodo seguente al file MainWindow.xaml.cs per visualizzare informazioni di base sul token:Add the following method to to your MainWindow.xaml.cs to display basic information about the token:
/// <summary>
/// Display basic information contained in the token
/// </summary>
private void DisplayBasicTokenInfo(AuthenticationResult authResult)
{
    TokenInfoText.Text = "";
    if (authResult != null)
    {
        TokenInfoText.Text += $"Name: {authResult.User.Name}" + Environment.NewLine;
        TokenInfoText.Text += $"Username: {authResult.User.DisplayableId}" + Environment.NewLine;
        TokenInfoText.Text += $"Token Expires: {authResult.ExpiresOn.ToLocalTime()}" + Environment.NewLine;
        TokenInfoText.Text += $"Access Token: {authResult.AccessToken}" + Environment.NewLine;
    }
}

Altre informazioniMore Information

I token acquisiti tramite OpenID Connect contengono anche un piccolo subset di informazioni relative all'utente.Tokens acquired via OpenID Connect also contain a small subset of information pertinent to the user. DisplayBasicTokenInfo consente di visualizzare le informazioni di base contenute nel token, quali l'ID e il nome visualizzato dell'utente, la data di scadenza del token e la stringa che rappresenta il token di accesso.DisplayBasicTokenInfo displays basic information contained in the token: for example, the user's display name and ID, as well as the token expiration date and the string representing the access token itself. Queste informazioni possono essere visualizzate dall'utente.This information is displayed for you to see. Premendo più volte il pulsante Call Microsoft Graph API (Chiama API Microsoft Graph), è possibile vedere che lo stesso token è stato usato per richieste successive.You can hit the Call Microsoft Graph API button multiple times and see that the same token was reused for subsequent requests. Se MSAL decide che è il momento di rinnovare il token, è possibile anche vedere la data di scadenza estesa.You can also see the expiration date being extended when MSAL decides it is time to renew the token.