Självstudie: Logga in användare och anropa Skrivbordsappen Microsoft Graph i Windows Presentation Foundation (WPF)

I den här självstudien skapar du en inbyggd XAML-app (Windows Desktop) som loggar in användare och hämtar en åtkomsttoken för att anropa Microsoft Graph API.

När du har slutfört guiden kan ditt program anropa ett skyddat API som använder personliga konton (inklusive outlook.com, live.com och andra). Programmet kommer också att använda arbets- och skolkonton från alla företag eller organisationer som använder Microsoft Entra-ID.

I den här självstudien:

  • Skapa ett WPF-projekt (Windows Presentation Foundation) i Visual Studio
  • Installera Microsoft Authentication Library (MSAL) för .NET
  • Registrera programmet
  • Lägga till kod för att stödja användarinloggning och utloggning
  • Lägga till kod för att anropa Microsoft Graph API
  • Testa appen

Förutsättningar

Så här fungerar exempelappen som genereras av den här guiden

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

Exempelprogrammet som du skapar med den här guiden aktiverar ett Windows Desktop-program som frågar Microsoft Graph API eller ett webb-API som accepterar token från en Microsofts identitetsplattform slutpunkt. I det här scenariot lägger du till en token i HTTP-begäranden via auktoriseringshuvudet. Microsoft Authentication Library (MSAL) hanterar tokenanskaffning och förnyelse.

Hantera tokenförvärv för åtkomst till skyddade webb-API:er

När användaren har autentiserats tar exempelprogrammet emot en token som du kan använda för att fråga Microsoft Graph API eller ett webb-API som skyddas av Microsofts identitetsplattform.

API:er som Microsoft Graph kräver en token för att tillåta åtkomst till specifika resurser. Till exempel krävs en token för att läsa en användares profil, komma åt en användares kalender eller skicka e-post. Ditt program kan begära en åtkomsttoken med hjälp av MSAL för att komma åt dessa resurser genom att ange API-omfång. Den här åtkomsttoken läggs sedan till i HTTP-auktoriseringshuvudet för varje anrop som görs mot den skyddade resursen.

MSAL hanterar cachelagring och uppdatering av åtkomsttoken åt dig, så att programmet inte behöver göra det.

NuGet-paket

Den här guiden använder följande NuGet-paket:

Bibliotek beskrivning
Microsoft.Identity.Client Microsoft Authentication Library (MSAL.NET)

Konfigurera projektet

I det här avsnittet skapar du ett nytt projekt som visar hur du integrerar ett Windows Desktop .NET-program (XAML) med inloggning med Microsoft så att programmet kan köra frågor mot webb-API:er som kräver en token.

Programmet som du skapar visar en knapp som anropar Microsoft Graph API, ett område där resultatet visas och en utloggningsknapp.

Kommentar

Föredrar du att ladda ned det här exemplets Visual Studio-projekt i stället? Ladda ned ett projekt och gå vidare till konfigurationssteget för att konfigurera kodexemplet innan du kör det.

Skapa programmet med hjälp av följande steg:

  1. Öppna Visual Studio
  2. I startfönstret väljer du Skapa ett nytt projekt.
  3. I listrutan Alla språk väljer du C#.
  4. Sök efter och välj mallen WPF-app (.NET Framework) och välj sedan Nästa.
  5. I rutan Projektnamn anger du ett namn som Win-App-calling-MsGraph.
  6. Välj en plats för projektet eller acceptera standardalternativet.
  7. I Ramverket väljer du .NET Framework 4.8.
  8. Välj Skapa.

Lägga till MSAL i projektet

  1. I Visual Studio, välj Verktyg>NuGet pakethanterare>Pakethanterarkonsol.

  2. I fönstret Package Manager-konsolen klistrar du in följande Azure PowerShell-kommando:

    Install-Package Microsoft.Identity.Client -Pre
    

Registrera ditt program

Dricks

Stegen i den här artikeln kan variera något beroende på vilken portal du börjar från.

Följ dessa steg för att registrera och konfigurera ditt program:

  1. Logga in på administrationscentret för Microsoft Entra som minst programutvecklare.
  2. Om du har åtkomst till flera klienter använder du ikonen Inställningar på den översta menyn för att växla till den klientorganisation där du vill registrera programmet från menyn Kataloger + prenumerationer.
  3. Bläddra till Identitetsprogram>> Appregistreringar.
  4. Välj Ny registrering.
  5. Ange ett namn för ditt program, till exempel Win-App-calling-MsGraph. Användare av din app kan se det här namnet och du kan ändra det senare.
  6. I avsnittet Kontotyper som stöds väljer du Konton i valfri organisationskatalog (Alla Microsoft Entra-kataloger – Multitenant) och personliga Microsoft-konton (t.ex. Skype, Xbox).
  7. Välj Registrera.
  8. Under Hantera väljer du Autentisering>Lägg till en plattform.
  9. Välj Mobil- och skrivbordsprogram.
  10. I avsnittet Omdirigerings-URI:er väljer du https://login.microsoftonline.com/common/oauth2/nativeclient.
  11. Välj Konfigurera.

Lägg till koden för att initiera MSAL

I det här steget skapar du en klass för att hantera interaktion med MSAL, till exempel hantering av token.

  1. Öppna filen App.xaml.cs och lägg sedan till referensen för MSAL i klassen:

    using Microsoft.Identity.Client;
    
  2. Uppdatera appklassen till följande:

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

Skapa programmets användargränssnitt

Det här avsnittet visar hur ett program kan fråga en skyddad serverdelsserver, till exempel Microsoft Graph.

En MainWindow.xaml-fil skapas automatiskt som en del av projektmallen. Öppna den här filen och ersätt sedan programmets <Grid-nod> med följande kod:

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

Använda MSAL för att hämta en token för Microsoft Graph API

I det här avsnittet använder du MSAL för att hämta en token för Microsoft Graph API.

  1. I filen MainWindow.xaml.cs lägger du till referensen för MSAL i klassen:

    using Microsoft.Identity.Client;
    
  2. MainWindow Ersätt klasskoden med följande kod:

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

Mer information

Hämta en användartoken interaktivt

AcquireTokenInteractive Att anropa metoden resulterar i ett fönster som uppmanar användarna att logga in. Program kräver vanligtvis att användarna loggar in interaktivt första gången de behöver komma åt en skyddad resurs. De kan också behöva logga in när en tyst åtgärd för att hämta en token misslyckas (till exempel när en användares lösenord har upphört att gälla).

Hämta en token obevakat

Metoden AcquireTokenSilent hanterar tokenförvärv och förnyelser utan någon användarinteraktion. När AcquireTokenInteractive körs för första gången AcquireTokenSilent är den vanliga metoden att använda för att hämta token som har åtkomst till skyddade resurser för efterföljande anrop, eftersom anrop till begäran eller förnya token görs tyst.

AcquireTokenSilent Så småningom kan metoden misslyckas. Orsaken till felet kan vara att användaren antingen har loggat ut eller ändrat sitt lösenord på en annan enhet. När MSAL upptäcker att problemet kan lösas genom att kräva en interaktiv åtgärd utlöses ett MsalUiRequiredException undantag. Ditt program kan hantera det här undantaget på två sätt:

  • Det kan göra ett anrop mot AcquireTokenInteractive omedelbart. Det här samtalet leder till att användaren uppmanas att logga in. Det här mönstret används i onlineprogram där det inte finns något tillgängligt offlineinnehåll för användaren. Exemplet som genereras av den här konfigurationen följer det här mönstret, som visas i praktiken första gången du kör exemplet.

  • Eftersom ingen användare har använt programmet, PublicClientApp.Users.FirstOrDefault() innehåller ett null-värde och ett MsalUiRequiredException undantag genereras.

  • Koden i exemplet hanterar sedan undantaget genom att anropa AcquireTokenInteractive, vilket resulterar i att användaren uppmanas att logga in.

  • Den kan i stället visa en visuell indikation för användarna om att en interaktiv inloggning krävs, så att de kan välja rätt tid för att logga in. Eller så kan programmet försöka AcquireTokenSilent igen senare. Det här mönstret används ofta när användare kan använda andra programfunktioner utan avbrott. Till exempel när offlineinnehåll är tillgängligt i programmet. I det här fallet kan användarna bestämma när de vill logga in för att antingen komma åt den skyddade resursen eller uppdatera den inaktuella informationen. Alternativt kan programmet välja att försöka AcquireTokenSilent igen när nätverket har återställts efter att ha varit tillfälligt otillgängligt.

Anropa Microsoft Graph-API:et med hjälp av den token som du nyss fick

Lägg till följande nya metod i .MainWindow.xaml.cs Metoden används för att göra en GET begäran mot Graph API med hjälp av ett auktorisera-huvud:

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

Mer information om hur du gör ett REST-anrop mot ett skyddat API

I det här exempelprogrammet använder GetHttpContentWithToken du metoden för att göra en HTTP-begäran GET mot en skyddad resurs som kräver en token och sedan returnera innehållet till anroparen. Den här metoden lägger till den förvärvade token i HTTP-auktoriseringshuvudet. För det här exemplet är resursen Microsoft Graph API me-slutpunkten , som visar användarens profilinformation.

Lägga till en metod för att logga ut en användare

Om du vill logga ut en användare lägger du till följande metod i MainWindow.xaml.cs filen:

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

Mer information om utloggning av användare

Metoden SignOutButton_Click tar bort användare från MSAL-användarcachen, vilket i praktiken uppmanar MSAL att glömma den aktuella användaren så att en framtida begäran om att hämta en token endast lyckas om den görs som interaktiv.

Även om programmet i det här exemplet stöder enskilda användare stöder MSAL scenarier där flera konton kan loggas in samtidigt. Ett exempel är ett e-postprogram där en användare har flera konton.

Visa grundläggande tokeninformation

Om du vill visa grundläggande information om token lägger du till följande metod i din MainWindow.xaml.cs-fil :

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

Mer information

Förutom den åtkomsttoken som används för att anropa Microsoft Graph-API:et hämtar MSAL även en ID-token efter att användaren har loggat in. Den här token innehåller en liten delmängd information som är relevant för användarna. Metoden DisplayBasicTokenInfo visar den grundläggande information som finns i token. Den visar till exempel användarens visningsnamn och ID, samt tokens förfallodatum och strängen som representerar själva åtkomsttoken. Du kan välja knappen Anropa Microsoft Graph API flera gånger och se att samma token återanvänddes för efterföljande begäranden. Du kan också se att förfallodatumet förlängs när MSAL bestämmer sig för att det är dags att förnya token.

Testa koden

Om du vill köra projektet väljer du F5 i Visual Studio. Ditt program MainWindow visas, som du ser här:

Test your application.

Första gången du kör programmet och väljer knappen Anropa Microsoft Graph API uppmanas du att logga in. Använd ett Microsoft Entra-konto (arbets- eller skolkonto) eller ett Microsoft-konto (live.com, outlook.com) för att testa det.

Sign in to the application.

Första gången du loggar in på ditt program uppmanas du också att ge medgivande för att tillåta programmet att komma åt din profil och logga in dig, som du ser här:

Provide your consent for application access.

Visa programresultat

När du har loggat in bör du se användarprofilinformationen som returneras av anropet till Microsoft Graph-API:et. Resultaten visas i rutan API-anropsresultat . Grundläggande information om token som hämtades via anropet till AcquireTokenInteractive eller AcquireTokenSilent bör visas i rutan Tokeninformation . Resultatet innehåller följande egenskaper:

Property Format beskrivning
Användarnamn user@domain.com Användarnamnet som används för att identifiera användaren.
Token upphör att gälla Datum/tid Tiden då token upphör att gälla. MSAL förlänger förfallodatumet genom att förnya token efter behov.

Mer information om omfång och delegerade behörigheter

Microsoft Graph API kräver user.read-omfånget för att läsa en användares profil. Det här omfånget läggs automatiskt till som standard i varje program som är registrerat i programregistreringsportalen. Andra API:er för Microsoft Graph samt anpassade API:er för serverdelsservern kan kräva ytterligare omfång. Microsoft Graph-API:et kräver omfånget Calendars.Read för att visa användarens kalendrar.

Om du vill komma åt användarens kalendrar i kontexten för ett program lägger du till behörigheten Calendars.Read delegerad till programregistreringsinformationen. Lägg sedan till omfånget Calendars.Read i anropet acquireTokenSilent .

Kommentar

Användaren kan uppmanas att ange ytterligare medgivanden när du ökar antalet omfång.

Hjälp och support

Om du behöver hjälp, vill rapportera ett problem eller vill lära dig mer om dina supportalternativ kan du läsa Hjälp och support för utvecklare.

Nästa steg

Läs mer om att skapa skrivbordsappar som anropar skyddade webb-API:er i vår scenarioserie i flera delar: