Chiamare l'API Microsoft Graph da un'app Windows DesktopCall the Microsoft Graph API from a Windows Desktop app

Questa guida dimostra come un'applicazione .NET per Windows Desktop (XAML) nativa può ottenere un token di accesso e chiamare l'API Microsoft Graph o altre API che richiedono token di accesso dall'endpoint di Azure Active Directory v2.This guide demonstrates how a native Windows Desktop .NET (XAML) application can get an access token and call Microsoft Graph API or other APIs that require access tokens from Azure Active Directory v2 endpoint.

Al termine di questa guida, l'applicazione sarà in grado di chiamare un'API protetta usando sia account personali (ad esempio, outlook.com, live.com e altri) sia account aziendali o di istituti di istruzione di proprietà di aziende o organizzazioni con Azure Active Directory.At the end of this guide, your application will be able to call a protected API using personal accounts (including outlook.com, live.com, and others) as well as work and school accounts from any company or organization that has Azure Active Directory.

Questa guida richiede Visual Studio 2015 Update 3 o Visual Studio 2017.This guide requires Visual Studio 2015 Update 3 or Visual Studio 2017. Se non lo si ha, è possibileDon’t have it? scaricare Visual Studio 2017 gratuitamenteDownload Visual Studio 2017 for free

Come interpretare questa guidaHow this guide works

Come interpretare questa guida

L'applicazione di esempio creata in questa guida consente a un'applicazione per Windows Desktop di eseguire query nell'API Microsoft Graph o in un'API Web che accetta token dall'endpoint di Azure Active Directory v2.The sample application created by this guide enables a Windows Desktop Application to query Microsoft Graph API or a Web API that accepts tokens from Azure Active Directory v2 endpoint. Per questo scenario, viene aggiunto un token a richieste HTTP tramite l'intestazione di autorizzazione.For this scenario, a token is added to HTTP requests via the Authorization header. L'acquisizione e il rinnovo del token vengono gestiti da Microsoft Authentication Library (MSAL).Token acquisition and renewal is handled by the Microsoft Authentication Library (MSAL).

Gestione dell'acquisizione di token per l'accesso ad API Web protetteHandling token acquisition for accessing protected Web APIs

Dopo che l'utente ha eseguito l'autenticazione, l'applicazione di esempio riceve un token che può essere usato per eseguire query nell'API Microsoft Graph o in un'API Web protetta da Microsoft Azure Active Directory v2.After the user authenticates, the sample application receives a token that can be used to query Microsoft Graph API or a Web API secured by Microsoft Azure Active Directory v2.

API come Microsoft Graph richiedono un token di accesso per consentire l'accesso a risorse specifiche, ad esempio per leggere un profilo utente, accedere al calendario dell'utente o inviare un messaggio di posta elettronica.APIs such as Microsoft Graph require an access token to allow accessing specific resources – for example, to read a user’s profile, access user’s calendar or send an email. L'applicazione può richiedere un token di accesso usando la libreria MSAL per accedere alle risorse tramite la definizione di ambiti API.Your application can request an access token using MSAL to access these resources by specifying API scopes. Il token di accesso ottenuto viene quindi aggiunto all'intestazione di autorizzazione HTTP per ogni chiamata effettuata alla risorsa protetta.This access token is then added to the HTTP Authorization header for every call made against the protected resource.

La memorizzazione nella cache e l'aggiornamento dei token di accesso vengono gestiti dalla libreria MSAL e non devono quindi essere effettuati dall'applicazione.MSAL manages caching and refreshing access tokens for you, so your application doesn't need to.

Pacchetti NuGetNuGet Packages

Questa guida usa i pacchetti NuGet seguenti:This guide uses the following NuGet packages:

LibreriaLibrary DescrizioneDescription
Microsoft.Identity.ClientMicrosoft.Identity.Client Microsoft Authentication Library (MSAL)Microsoft Authentication Library (MSAL)

Configurare il progettoSet up your project

Questa sezione fornisce istruzioni dettagliate su come creare un nuovo progetto per illustrare come integrare un'applicazione .NET per Windows Desktop (XAML) con Accedi con Microsoft in modo da poter eseguire query su API Web che richiedono un token.This section provides step-by-step instructions for how to create a new project to demonstrate how to integrate a Windows Desktop .NET application (XAML) with Sign-In with Microsoft so it can query Web APIs that requires a token.

L'applicazione creata in questa guida include un pulsante che consente di generare un grafico dei risultati da visualizzare sullo schermo, oltre a un pulsante di disconnessione.The application created by this guide exposes a button to graph and show results on screen and a sign-out button.

Se invece si preferisce scaricare questo progetto Visual Studio di esempio,Prefer to download this sample's Visual Studio project instead? Scaricare un progetto e passare direttamente al passaggio di configurazione per configurare il codice di esempio prima di eseguirlo.Download a project and skip to the Configuration step to configure the code sample before executing.

Creare l'applicazioneCreate your application

  1. In Visual Studio: File > New > ProjectIn Visual Studio: File > New > Project
  2. In Modelli selezionare Visual C#Under Templates, select Visual C#
  3. Selezionare WPF App (o Applicazione WPF, a seconda della versione di Visual Studio)Select WPF App (or WPF Application depending on the version of your Visual Studio)

Aggiungere Microsoft Authentication Library (MSAL) al progettoAdd the Microsoft Authentication Library (MSAL) to your project

  1. In Visual Studio: Tools > Nuget Package Manager > Package Manager ConsoleIn Visual Studio: Tools > Nuget Package Manager > Package Manager Console
  2. Nella finestra Console di Gestione pacchetti copiare e incollare il codice seguente:Copy/paste the following in the Package Manager Console window:
Install-Package Microsoft.Identity.Client -Pre

Questo pacchetto consente di installare Microsoft Authentication Library (MSAL),The package above installs the Microsoft Authentication Library (MSAL). che gestisce l'acquisizione, la memorizzazione nella cache e l'aggiornamento dei token utente usati per accedere ad API protette da Azure Active Directory v2.MSAL handles acquiring, caching and refreshing user toskens used to access APIs protected by Azure Active Directory v2.

Aggiungere il codice per inizializzare MSALAdd the code to initialize MSAL

Questo passaggio consente di creare una classe per gestire l'interazione con la libreria MSAL, ad esempio per la gestione dei token.This step will help you create a class to handle interaction with MSAL Library, such as handling of tokens.

  1. Aprire il file App.xaml.cs e aggiungere alla classe il riferimento relativo alla libreria MSAL:Open the App.xaml.cs file and add the reference for MSAL library to the class:
using Microsoft.Identity.Client;
  1. Aggiornare la classe App con il codice seguente:Update the App class to the following:
public partial class App : Application
{
    //Below is the clientId of your app registration. 
    //You have to replace the below with the Application Id for your app registration
    private static string ClientId = "your_client_id_here";

    public static PublicClientApplication PublicClientApp = new PublicClientApplication(ClientId);

}

Creare l'interfaccia utente dell'applicazioneCreate your application’s UI

La sezione seguente illustra come un'applicazione può eseguire una query su un server back-end protetto come Microsoft Graph.The section below shows how an application can query a protected backend server like Microsoft Graph. Nell'ambito del modello di progetto viene automaticamente creato un file MainWindow.xaml.A MainWindow.xaml file should automatically be created as a part of your project template. Aprire il file e seguire le istruzioni seguenti:Open this file this file and then follow the instructions below:

Sostituire il valore <Grid> dell'applicazione con il seguente:Replace your application’s <Grid> with be the following:

<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>

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.

Creare un'applicazione (Rapida)Create an application (Express)

È ora necessario registrare l'applicazione nel portale di registrazione delle applicazioni Microsoft:Now you need to register your application in the Microsoft Application Registration Portal:

  1. Registrare l'applicazione tramite il portale di registrazione delle applicazioni MicrosoftRegister your application via the Microsoft Application Registration Portal
  2. Immettere un nome per l'applicazione e l'indirizzo di posta elettronicaEnter a name for your application and your email
  3. Assicurarsi che l'opzione per l'installazione guidata sia selezionataMake sure the option for Guided Setup is checked
  4. Seguire le istruzioni per ottenere l'ID dell'applicazione e incollarlo nel codiceFollow the instructions to obtain the application ID and paste it into your code

Aggiungere le informazioni di registrazione dell'applicazione alla soluzione (Avanzata)Add your application registration information to your solution (Advanced)

È ora necessario registrare l'applicazione nel portale di registrazione delle applicazioni Microsoft:Now you need to register your application in the Microsoft Application Registration Portal:

  1. Passare al portale di registrazione delle applicazioni Microsoft per registrare un'applicazioneGo to the Microsoft Application Registration Portal to register an application
  2. Immettere un nome per l'applicazione e l'indirizzo di posta elettronicaEnter a name for your application and your email
  3. Assicurarsi che l'opzione per l'installazione guidata sia deselezionataMake sure the option for Guided Setup is unchecked
  4. Fare clic su Add Platform, selezionare Native Application e quindi fare clic su SalvaClick Add Platform, then select Native Application and hit Save
  5. Copiare il GUID nell'ID applicazione, tornare a Visual Studio, aprire App.xaml.cs e sostituire your_client_id_here con l'ID applicazione appena registrato:Copy the GUID in Application ID, go back to Visual Studio, open App.xaml.cs and replace your_client_id_here with the Application ID you just registered:
private static string ClientId = "your_application_id_here";

Test your code

To test your application in Visual Studio, press F5 to run your project. The MainWindow for your application is displayed:

Test your application

When you're ready to run your test, use a Microsoft Azure Active Directory account (work or school account) or a Microsoft account (live.com, outlook.com) to sign in. The first time that you run the application, you're prompted to sign in:

Sign in to the application

The first time that you sign in to your application, you're prompted to provide your consent to allow the application to access your profile and to sign you in:

Provide your consent for application access

View application results

After you sign in, you should see the user profile information returned by the call to the Microsoft Graph API. The results are displayed in the API Call Results box. Basic information about the token that was acquired via the call to AcquireTokenAsync or AcquireTokenSilentAsync should be visible in the Token Info box. The results contain the following properties:

Property Format Description
Name User's full name The user’s first and last name.
Username user@domain.com The username that is used to identify the user.
Token Expires DateTime The time at which the token expires. MSAL extends the expiration date by renewing the token as necessary.
Access Token String The token string that is sent to HTTP requests that require an Authorization header.

More information about scopes and delegated permissions

The Microsoft Graph API requires the user.read scope to read a user's profile. This scope is automatically added by default in every application that's registered on the registration portal. Other APIs for Microsoft Graph, as well as custom APIs for your back-end server, might require additional scopes. The Microsoft Graph API requires the Calendars.Read scope to list the user’s calendars.

To access the user’s calendars in the context of an application, add the Calendars.Read delegated permission to the application registration information. Then, add the Calendars.Read scope to the acquireTokenSilent call.

Nota

The user might be prompted for additional consents as you increase the number of scopes.

Help and support

If you need help, want to report an issue, or would like to learn more about your support options, see the following article: