Desktop-app die web-API's aanroept: Een token verkrijgen

Nadat u een exemplaar van de openbare clienttoepassing hebt gemaakt, gebruikt u deze om een token te verkrijgen dat u vervolgens gebruikt om een web-API aan te roepen.

De web-API wordt gedefinieerd door de scopes . Ongeacht de ervaring die u in uw toepassing biedt, is het patroon dat u moet gebruiken:

  • Systematisch proberen een token op te halen uit de tokencache door aan te AcquireTokenSilent roepen.
  • Als deze aanroep mislukt, gebruikt u de stroom die u wilt gebruiken. Deze AcquireToken wordt hier weergegeven door AcquireTokenXX .

In MSAL.NET

AuthenticationResult result;
var accounts = await app.GetAccountsAsync();
IAccount account = ChooseAccount(accounts); // for instance accounts.FirstOrDefault
                                            // if the app manages is at most one account
try
{
 result = await app.AcquireTokenSilent(scopes, account)
                   .ExecuteAsync();
}
catch(MsalUiRequiredException ex)
{
  result = await app.AcquireTokenXX(scopes, account)
                    .WithOptionalParameterXXX(parameter)
                    .ExecuteAsync();
}

Hier zijn de verschillende manieren om tokens te verkrijgen in een bureaubladtoepassing.

Interactief een token verkrijgen

In het volgende voorbeeld ziet u minimale code om interactief een token op te halen voor het lezen van het gebruikersprofiel met Microsoft Graph.

In MSAL.NET

string[] scopes = new string[] {"user.read"};
var app = PublicClientApplicationBuilder.Create(clientId).Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
{
 result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
             .ExecuteAsync();
}
catch(MsalUiRequiredException)
{
 result = await app.AcquireTokenInteractive(scopes)
             .ExecuteAsync();
}

Verplichte parameters

AcquireTokenInteractive heeft slechts één verplichte parameter, , die een overzicht bevat van tekenreeksen die de scopes definiëren waarvoor scopes een token vereist is. Als het token voor Microsoft Graph is, kunt u de vereiste scopes vinden in de API-verwijzing van elke Microsoft Graph API in de sectie met de naam 'Machtigingen'. Om bijvoorbeeld de contactpersonen van de gebruiker weerte geven, moet het bereik 'User.Read', 'Contacts.Read' worden gebruikt. Raadpleeg Microsoft Graph-machtigingen voor meer informatie.

In Android moet u ook de bovenliggende activiteit opgeven met behulp van , zoals wordt weergegeven, zodat het token na de interactie terugkomt .WithParentActivityOrWindow op die bovenliggende activiteit. Als u dit niet opgeeft, wordt er een uitzondering gemaakt bij het aanroepen .ExecuteAsync() van .

Specifieke optionele parameters in MSAL.NET

WithParentActivityOrWindow

De gebruikersinterface is belangrijk omdat deze interactief is. AcquireTokenInteractive heeft één specifieke optionele parameter die de bovenliggende gebruikersinterface kan opgeven voor platforms die deze ondersteunen. Bij gebruik in een bureaubladtoepassing heeft .WithParentActivityOrWindow een ander type, dat afhankelijk is van het platform. U kunt ook de optionele parameter voor het bovenliggende venster weglaten om een venster te maken, als u niet wilt bepalen waar het aanmeldingsdialoogvenster op het scherm wordt weergegeven. Dit is van toepassing op toepassingen die zijn gebaseerd op een opdrachtregel, die worden gebruikt om aanroepen door te geven aan andere back-end-service en waarvoor geen vensters nodig zijn voor gebruikersinteractie.

// net45
WithParentActivityOrWindow(IntPtr windowPtr)
WithParentActivityOrWindow(IWin32Window window)

// Mac
WithParentActivityOrWindow(NSWindow window)

// .NET Standard (this will be on all platforms at runtime, but only on NetStandard at build time)
WithParentActivityOrWindow(object parent).

Opmerkingen:

  • Op .NET Standard is de verwachte object Activity op Android, UIViewController iOS, NSWindow Mac en IWin32Window IntPr Windows.

  • In Windows moet u aanroepen vanuit de UI-thread, zodat de ingesloten browser de juiste context voor AcquireTokenInteractive UI-synchronisatie krijgt. Niet aanroepen vanuit de UI-thread kan ertoe leiden dat berichten niet goed worden opgelopen en dat er impasses ontstaan met de gebruikersinterface. Een manier om Microsoft Authentication Libraries (MSAL's) aan te roepen vanuit de UI-thread als u zich nog niet in de UI-thread hebt, is door de op Dispatcher WPF te gebruiken.

  • Als u WPF gebruikt, kunt u de klasse gebruiken om een venster op te halen uit een WindowInteropHelper.Handle WPF-besturingselement. Vervolgens is de aanroep van een WPF-besturingselement ( this ):

    result = await app.AcquireTokenInteractive(scopes)
                      .WithParentActivityOrWindow(new WindowInteropHelper(this).Handle)
                      .ExecuteAsync();
    

WithPrompt

WithPrompt() wordt gebruikt om de interactiviteit met de gebruiker te bepalen door een prompt op te geven.

Afbeelding van de velden in de promptstructuur. Deze constante waarden bepalen interactiviteit met de gebruiker door het type prompt te definiëren dat wordt weergegeven door de methode WithPrompt().

De klasse definieert de volgende constanten:

  • SelectAccount dwingt de STS om het dialoogvenster voor accountselectie weer te geven dat accounts bevat waarvoor de gebruiker een sessie heeft. Deze optie is handig wanneer toepassingsontwikkelaars gebruikers willen laten kiezen uit verschillende identiteiten. Deze optie zorgt er voor dat MSAL naar prompt=select_account de id-provider wordt verzenden. Dit is de standaardoptie. Het is een goede taak om de best mogelijke ervaring te bieden op basis van de beschikbare informatie, zoals het account en de aanwezigheid van een sessie voor de gebruiker. Wijzig het niet tenzij u een goede reden hebt om dit te doen.
  • Consent stelt de ontwikkelaar van de toepassing in staat om de gebruiker te dwingen om toestemming te vragen, zelfs als er al eerder toestemming is verleend. In dit geval verzendt MSAL prompt=consent naar de id-provider. Deze optie kan worden gebruikt in sommige beveiligingstoepassingen waarbij de organisatiegovernance vereist dat de gebruiker telkens wanneer de toepassing wordt gebruikt het toestemmingsdialoogvenster krijgt te zien.
  • ForceLogin stelt de ontwikkelaar van de toepassing in staat om de gebruiker om referenties te vragen door de service, zelfs als deze gebruikersprompt mogelijk niet nodig is. Deze optie kan handig zijn om de gebruiker zich opnieuw aan te melden als het ophalen van een token mislukt. In dit geval verzendt MSAL prompt=login naar de id-provider. Soms wordt het gebruikt in beveiligingsgerichte toepassingen waarbij de organisatiegovernance vereist dat de gebruiker zich telkens wanneer hij of zij toegang wil krijgen tot specifieke onderdelen van een toepassing, opnieuw moet worden zich opnieuw aan te geven.
  • Create activeert een aanmeldingservaring, die wordt gebruikt voor External Identities, door naar de prompt=create id-provider te verzenden. Deze prompt mag niet worden verzonden voor Azure AD B2C apps. Zie Een gebruikersstroom voor selfservice-aanmeldingtoevoegen aan een app voor meer informatie.
  • Never (alleen voor .NET 4.5 en WinRT) wordt de gebruiker niet gevraagd, maar wordt geprobeerd de cookie te gebruiken die is opgeslagen in de verborgen ingesloten webweergave. Zie Webweergaven in MSAL.NET. Het gebruik van deze optie kan mislukken. In dat geval geeft een AcquireTokenInteractive uitzondering weer om te melden dat er een gebruikersinterface-interactie nodig is. U moet een andere Prompt parameter gebruiken.
  • NoPrompt verzendt geen prompt naar de id-provider, die daarom besluit de beste aanmeldingservaring aan de gebruiker te presenteren (een aanmelding of account selecteren). Deze optie is ook verplicht voor Azure Active Directory (Azure AD) B2C-beleid voor het bewerken van profielen. Zie voor meer informatie Azure AD B2C specifieke informatie.

WithUseEmbeddedWebView

Met deze methode kunt u opgeven of u het gebruik van een ingesloten WebView of de webweergave van het systeem (indien beschikbaar) wilt forceeren. Zie Gebruik van webbrowsers voor meer informatie.

var result = await app.AcquireTokenInteractive(scopes)
                    .WithUseEmbeddedWebView(true)
                    .ExecuteAsync();

WithExtraScopeToConsent

Deze modifier wordt gebruikt in een geavanceerd scenario waarin u wilt dat de gebruiker vooraf toestemming geeft voor verschillende resources en u geen incrementele toestemming wilt gebruiken, die normaal gesproken wordt gebruikt met MSAL.NET/the Microsoft Identity Platform. Zie Vooraf toestemming van de gebruiker vragen voor verschillende resources voor meer informatie.

var result = await app.AcquireTokenInteractive(scopesForCustomerApi)
                     .WithExtraScopeToConsent(scopesForVendorApi)
                     .ExecuteAsync();

MetCustomWebUi

Een webinterface is een mechanisme om een browser aan te roepen. Dit mechanisme kan een toegewezen UI WebBrowser-besturingselement zijn of een manier om het openen van de browser te delegeren. MSAL biedt implementaties van webinterfaces voor de meeste platforms, maar er zijn gevallen waarin u de browser zelf wilt hosten:

  • Platforms die niet expliciet worden gedekt door MSAL, bijvoorbeeld Blazor, Unity en Mono op desktops.
  • U wilt de gebruikersinterface van uw toepassing testen en een geautomatiseerde browser gebruiken die kan worden gebruikt met Selenium.
  • De browser en de app die MSAL uitvoeren, staan in afzonderlijke processen.
In een oogopslag

Hiervoor geeft u MSAL op, dat moet worden weergegeven in een browser naar keuze, zodat de eindgebruiker items zoals de gebruikersnaam start Url kan invoeren. Nadat de verificatie is uitgevoerd, moet uw app worden door gegeven aan MSAL , dat een code bevat end Url die wordt geleverd door Azure AD. De host van end Url is altijd redirectUri . Als u wilt end Url onderscheppen, gaat u op een van de volgende dingen te werk:

  • Controleer browseromleidingen totdat redirect Url wordt geraakt.
  • De browser omleiden naar een URL die u bewaakt.
WithCustomWebUi is een extensibility point

WithCustomWebUi is een extensibility point dat u kunt gebruiken om uw eigen gebruikersinterface in openbare clienttoepassingen te bieden. U kunt de gebruiker ook via het /Authorize-eindpunt van de id-provider laten gaan en zich laten aanmelden en toestemming geven. MSAL.NET kunt vervolgens de verificatiecode inwisselen en een token krijgen. Het wordt bijvoorbeeld gebruikt in Visual Studio om toepassingen met elektronen (bijvoorbeeld Visual Studio Feedback) de webinteractie te laten bieden, maar laat het over aan MSAL.NET om het meeste werk te doen. U kunt deze ook gebruiken als u automatisering van de gebruikersinterface wilt bieden. In openbare clienttoepassingen maakt MSAL.NET gebruik van de PKCE-standaard (Proof Key for Code Exchange) om ervoor te zorgen dat de beveiliging in acht wordt genomen. Alleen MSAL.NET kunt de code inwisselen. Zie RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (RFC 7636 - Proof Key voor codeuitwisseling door openbare OAuth-clients) voor meer informatie.

using Microsoft.Identity.Client.Extensions;
Gebruiken metCustomWebUi

Volg deze .WithCustomWebUI stappen om te gebruiken.

  1. Implementeer de ICustomWebUi-interface. Zie deze website voor meer informatie. Implementeert één AcquireAuthorizationCodeAsync methode en accepteer de autorisatiecode-URL die wordt berekend door MSAL.NET. Laat de gebruiker vervolgens de interactie met de id-provider uitvoeren en de URL retourneren waarmee de id-provider uw implementatie samen met de autorisatiecode zou hebben aangeroepen. Als u problemen hebt, moet uw implementatie een uitzondering MsalExtensionException veroorzaken om goed samen te werken met MSAL.

  2. Gebruik in AcquireTokenInteractive uw aanroep de .WithCustomUI() modifier die het exemplaar van uw aangepaste webinterface door geven.

    result = await app.AcquireTokenInteractive(scopes)
                      .WithCustomWebUi(yourCustomWebUI)
                      .ExecuteAsync();
    
Voorbeelden van de implementatie van ICustomWebUi in testautomatisering: SeleniumWebUI

Het MSAL.NET team heeft de UI-tests herschreven om dit mechanisme voor extensibility te gebruiken. Als u geïnteresseerd bent, bekijkt u de seleniumWebUI-klasse in de MSAL.NET broncode.

Een geweldige ervaring bieden met SystemWebViewOptions

In MSAL.NET 4.1 SystemWebViewOptions kunt u het volgende opgeven:

  • De URI om naar te gaan ( ) of het HTML-fragment om weer te geven ( ) in het geval van BrowserRedirectError HtmlMessageError aanmeldings- of toestemmingsfouten in de webbrowser van het systeem.
  • De URI om naar te gaan ( BrowserRedirectSuccess ) of het HTML-fragment om weer te geven ( ) in het geval van een HtmlMessageSuccess geslaagde aanmelding of toestemming.
  • De actie die moet worden uitgevoerd om de systeembrowser te starten. U kunt uw eigen implementatie leveren door de gemachtigde in OpenBrowserAsync te stellen. De klasse biedt ook een standaard implementatie voor twee browsers: respectievelijk voor Microsoft Edge OpenWithEdgeBrowserAsync OpenWithChromeEdgeBrowserAsync en Microsoft Edge op Chromium.

Als u deze structuur wilt gebruiken, schrijft u iets zoals in het volgende voorbeeld:

IPublicClientApplication app;
...

options = new SystemWebViewOptions
{
 HtmlMessageError = "<b>Sign-in failed. You can close this tab ...</b>",
 BrowserRedirectSuccess = "https://contoso.com/help-for-my-awesome-commandline-tool.html"
};

var result = app.AcquireTokenInteractive(scopes)
                .WithEmbeddedWebView(false)       // The default in .NET Core
                .WithSystemWebViewOptions(options)
                .Build();

Andere optionele parameters

Zie AcquireTokenInteractive AcquireTokenInteractiveParameterBuildervoor meer informatie over alle andere optionele parameters voor .

Geïntegreerde Windows-authenticatie

Als u een domeingebruiker wilt aanmelden op een domein of computer die lid is van Azure AD, gebruikt u Geïntegreerde Windows-verificatie (IWA).

Beperkingen

  • Geïntegreerde Windows-verificatie is alleen bruikbaar voor federatief+ gebruikers, dat wil zeggen gebruikers die zijn gemaakt in Active Directory en worden gemaakt door Azure AD. Gebruikers die rechtstreeks in Azure AD zijn gemaakt zonder Active Directory-ondersteuning, ook wel beheerde gebruikers genoemd, kunnen deze verificatiestroom niet gebruiken. Deze beperking heeft geen invloed op de stroom voor gebruikersnaam en wachtwoord.

  • Met IWA wordt meervoudige verificatie (MFA) niet overgeslagen. Als MFA is geconfigureerd, kan IWA mislukken als een MFA-uitdaging is vereist, omdat MFA gebruikersinteractie vereist.

    IWA is niet-interactief, maar MFA vereist interactiviteit van de gebruiker. U kunt niet bepalen wanneer de id-provider MFA aanvraagt om te worden uitgevoerd, de tenantbeheerder wel. Uit onze waarnemingen blijkt dat MFA is vereist wanneer u zich vanuit een ander land of andere regio, wanneer u niet via VPN bent verbonden met een bedrijfsnetwerk en soms zelfs wanneer u bent verbonden via VPN. Verwacht geen deterministische set regels. Azure AD maakt gebruik van AI om continu te leren of MFA vereist is. Terugvallen op een gebruikersprompt zoals interactieve verificatie of apparaatcodestroom als IWA mislukt.

  • De doorgegeven instantie PublicClientApplicationBuilder moet zijn:

    • Tenant van het formulier , waarbij de GUID is die de tenant-id of een domein vertegenwoordigt https://login.microsoftonline.com/{tenant}/ dat is gekoppeld aan de tenant tenant.
    • Voor werk- en schoolaccounts: https://login.microsoftonline.com/organizations/ .
    • Persoonlijke Microsoft-accounts worden niet ondersteund. U kunt geen /common- of /consumers-tenants gebruiken.
  • Omdat Geïntegreerde Windows-verificatie een stille stroom is:

    • De gebruiker van uw toepassing moet eerder hebben ingestemd met het gebruik van de toepassing.
    • Of de tenantbeheerder moet eerder toestemming hebben gegeven aan alle gebruikers in de tenant om de toepassing te kunnen gebruiken.
    • Met andere woorden:
  • Deze stroom is ingeschakeld voor .NET Desktop-, .NET Core- en UWP-apps.

Zie machtigingen en toestemming van het Microsoft Identity Platform voormeer informatie over toestemming.

Meer informatie over het gebruik ervan

In MSAL.NET gebruikt u:

AcquireTokenByIntegratedWindowsAuth(IEnumerable<string> scopes)

Normaal gesproken hebt u slechts één parameter nodig ( scopes ). Afhankelijk van de manier waarop uw Windows-beheerder het beleid heeft ingesteld, kunnen toepassingen op uw Windows-computer de aangemelde gebruiker mogelijk niet op zoeken. In dat geval gebruikt u een tweede methode, , en geeft u de gebruikersnaam van de aangemelde gebruiker door als .WithUsername() UPN-indeling, bijvoorbeeld joe@contoso.com .

In het volgende voorbeeld wordt het meest actuele geval gegeven, met uitleg over het soort uitzonderingen dat u kunt krijgen en de oplossingen.

static async Task GetATokenForGraph()
{
 string authority = "https://login.microsoftonline.com/contoso.com";
 string[] scopes = new string[] { "user.read" };
 IPublicClientApplication app = PublicClientApplicationBuilder
      .Create(clientId)
      .WithAuthority(authority)
      .Build();

 var accounts = await app.GetAccountsAsync();

 AuthenticationResult result = null;
 if (accounts.Any())
 {
  result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
      .ExecuteAsync();
 }
 else
 {
  try
  {
   result = await app.AcquireTokenByIntegratedWindowsAuth(scopes)
      .ExecuteAsync(CancellationToken.None);
  }
  catch (MsalUiRequiredException ex)
  {
   // MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application
   // with ID '{appId}' named '{appName}'.Send an interactive authorization request for this user and resource.

   // you need to get user consent first. This can be done, if you are not using .NET Core (which does not have any Web UI)
   // by doing (once only) an AcquireToken interactive.

   // If you are using .NET core or don't want to do an AcquireTokenInteractive, you might want to suggest the user to navigate
   // to a URL to consent: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope=user.read

   // AADSTS50079: The user is required to use multi-factor authentication.
   // There is no mitigation - if MFA is configured for your tenant and AAD decides to enforce it,
   // you need to fallback to an interactive flows such as AcquireTokenInteractive or AcquireTokenByDeviceCode
   }
   catch (MsalServiceException ex)
   {
    // Kind of errors you could have (in ex.Message)

    // MsalServiceException: AADSTS90010: The grant type is not supported over the /common or /consumers endpoints. Please use the /organizations or tenant-specific endpoint.
    // you used common.
    // Mitigation: as explained in the message from Azure AD, the authority needs to be tenanted or otherwise organizations

    // MsalServiceException: AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.
    // Explanation: this can happen if your application was not registered as a public client application in Azure AD
    // Mitigation: in the Azure portal, edit the manifest for your application and set the `allowPublicClient` to `true`
   }
   catch (MsalClientException ex)
   {
      // Error Code: unknown_user Message: Could not identify logged in user
      // Explanation: the library was unable to query the current Windows logged-in user or this user is not AD or AAD
      // joined (work-place joined users are not supported).

      // Mitigation 1: on UWP, check that the application has the following capabilities: Enterprise Authentication,
      // Private Networks (Client and Server), User Account Information

      // Mitigation 2: Implement your own logic to fetch the username (e.g. john@contoso.com) and use the
      // AcquireTokenByIntegratedWindowsAuth form that takes in the username

      // Error Code: integrated_windows_auth_not_supported_managed_user
      // Explanation: This method relies on an a protocol exposed by Active Directory (AD). If a user was created in Azure
      // Active Directory without AD backing ("managed" user), this method will fail. Users created in AD and backed by
      // AAD ("federated" users) can benefit from this non-interactive method of authentication.
      // Mitigation: Use interactive authentication
   }
 }

 Console.WriteLine(result.Account.Username);
}

Zie AcquireTokenByIntegratedWindowsAuthParameterBuildervoor een lijst met mogelijke modifiers op AcquireTokenByIntegratedWindowsAuthParameterBuilder.

Gebruikersnaam en wachtwoord

U kunt ook een token verkrijgen door de gebruikersnaam en het wachtwoord op te geven. Deze stroom is beperkt en wordt niet aanbevolen, maar er zijn nog steeds gebruiksgevallen waarin dit nodig is.

De stroom voor gebruikersnaam en wachtwoord wordt niet aanbevolen omdat het niet veilig is dat uw toepassing een gebruiker om het wachtwoord vraagt. Zie Wat is de oplossing voor het groeiende probleem met wachtwoorden? voor meer informatie. De voorkeursstroom voor het op de silent ophalen van een token op windows-computers die lid zijn van een domein is Geïntegreerde Windows-verificatie. U kunt ook de apparaatcodestroom gebruiken.

Het gebruik van een gebruikersnaam en wachtwoord is in sommige gevallen handig, zoals DevOps-scenario's. Maar als u een gebruikersnaam en wachtwoord wilt gebruiken in interactieve scenario's waarin u uw eigen gebruikersinterface biedt, moet u nadenken over hoe u hier weg van kunt gaan. Door een gebruikersnaam en wachtwoord te gebruiken, geeft u een aantal dingen op:

  • Kernen van moderne identiteit. Een wachtwoord kan phished worden en opnieuw worden afgespeeld omdat een gedeeld geheim kan worden onderschept. Deze is niet compatibel met wachtwoordloos.
  • Gebruikers die MFA moeten doen, kunnen zich niet aanmelden omdat er geen interactie is.
  • Gebruikers kunnen geen eenmalige aanmelding (SSO) doen.

Beperkingen

De volgende beperkingen zijn ook van toepassing:

  • De stroom voor gebruikersnaam en wachtwoord is niet compatibel met voorwaardelijke toegang en meervoudige verificatie. Als uw app wordt uitgevoerd in een Azure AD-tenant waar de tenantbeheerder meervoudige verificatie vereist, kunt u deze stroom dus niet gebruiken. Veel organisaties doen dat.
  • Het werkt alleen voor werk- en schoolaccounts (niet voor MSA).
  • De stroom is beschikbaar op .NET Desktop en .NET Core, maar niet op UWP.

B2C-specifieke informatie

Zie resource-eigenaar wachtwoordreferenties (ROPC) met B2C voor meer informatie.

Gebruik deze

IPublicClientApplicationbevat de methode AcquireTokenByUsernamePassword .

Het volgende voorbeeld biedt een vereenvoudigde case.

static async Task GetATokenForGraph()
{
 string authority = "https://login.microsoftonline.com/contoso.com";
 string[] scopes = new string[] { "user.read" };
 IPublicClientApplication app;
 app = PublicClientApplicationBuilder.Create(clientId)
       .WithAuthority(authority)
       .Build();
 var accounts = await app.GetAccountsAsync();

 AuthenticationResult result = null;
 if (accounts.Any())
 {
  result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
                    .ExecuteAsync();
 }
 else
 {
  try
  {
   var securePassword = new SecureString();
   foreach (char c in "dummy")        // you should fetch the password
    securePassword.AppendChar(c);  // keystroke by keystroke

   result = await app.AcquireTokenByUsernamePassword(scopes,
                                                    "joe@contoso.com",
                                                     securePassword)
                      .ExecuteAsync();
  }
  catch(MsalException)
  {
   // See details below
  }
 }
 Console.WriteLine(result.Account.Username);
}

In het volgende voorbeeld wordt het meest actuele geval gegeven, met uitleg over het soort uitzonderingen dat u kunt krijgen en de oplossingen.

static async Task GetATokenForGraph()
{
 string authority = "https://login.microsoftonline.com/contoso.com";
 string[] scopes = new string[] { "user.read" };
 IPublicClientApplication app;
 app = PublicClientApplicationBuilder.Create(clientId)
                                   .WithAuthority(authority)
                                   .Build();
 var accounts = await app.GetAccountsAsync();

 AuthenticationResult result = null;
 if (accounts.Any())
 {
  result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
                    .ExecuteAsync();
 }
 else
 {
  try
  {
   var securePassword = new SecureString();
   foreach (char c in "dummy")        // you should fetch the password keystroke
    securePassword.AppendChar(c);  // by keystroke

   result = await app.AcquireTokenByUsernamePassword(scopes,
                                                    "joe@contoso.com",
                                                    securePassword)
                    .ExecuteAsync();
  }
  catch (MsalUiRequiredException ex) when (ex.Message.Contains("AADSTS65001"))
  {
   // Here are the kind of error messages you could have, and possible mitigations

   // ------------------------------------------------------------------------
   // MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application
   // with ID '{appId}' named '{appName}'. Send an interactive authorization request for this user and resource.

   // Mitigation: you need to get user consent first. This can be done either statically (through the portal),
   /// or dynamically (but this requires an interaction with Azure AD, which is not possible with
   // the username/password flow)
   // Statically: in the portal by doing the following in the "API permissions" tab of the application registration:
   // 1. Click "Add a permission" and add all the delegated permissions corresponding to the scopes you want (for instance
   // User.Read and User.ReadBasic.All)
   // 2. Click "Grant/revoke admin consent for <tenant>") and click "yes".
   // Dynamically, if you are not using .NET Core (which does not have any Web UI) by
   // calling (once only) AcquireTokenInteractive.
   // remember that Username/password is for public client applications that is desktop/mobile applications.
   // If you are using .NET core or don't want to call AcquireTokenInteractive, you might want to:
   // - use device code flow (See https://aka.ms/msal-net-device-code-flow)
   // - or suggest the user to navigate to a URL to consent: https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={clientId}&response_type=code&scope=user.read
   // ------------------------------------------------------------------------

   // ------------------------------------------------------------------------
   // ErrorCode: invalid_grant
   // SubError: basic_action
   // MsalUiRequiredException: AADSTS50079: The user is required to use multi-factor authentication.
   // The tenant admin for your organization has chosen to oblige users to perform multi-factor authentication.
   // Mitigation: none for this flow
   // Your application cannot use the Username/Password grant.
   // Like in the previous case, you might want to use an interactive flow (AcquireTokenInteractive()),
   // or Device Code Flow instead.
   // Note this is one of the reason why using username/password is not recommended;
   // ------------------------------------------------------------------------

   // ------------------------------------------------------------------------
   // ex.ErrorCode: invalid_grant
   // subError: null
   // Message = "AADSTS70002: Error validating credentials.
   // AADSTS50126: Invalid username or password
   // In the case of a managed user (user from an Azure AD tenant opposed to a
   // federated user, which would be owned
   // in another IdP through ADFS), the user has entered the wrong password
   // Mitigation: ask the user to re-enter the password
   // ------------------------------------------------------------------------

   // ------------------------------------------------------------------------
   // ex.ErrorCode: invalid_grant
   // subError: null
   // MsalServiceException: ADSTS50034: To sign into this application the account must be added to
   // the {domainName} directory.
   // or The user account does not exist in the {domainName} directory. To sign into this application,
   // the account must be added to the directory.
   // The user was not found in the directory
   // Explanation: wrong username
   // Mitigation: ask the user to re-enter the username.
   // ------------------------------------------------------------------------
  }
  catch (MsalServiceException ex) when (ex.ErrorCode == "invalid_request")
  {
   // ------------------------------------------------------------------------
   // AADSTS90010: The grant type is not supported over the /common or /consumers endpoints.
   // Please use the /organizations or tenant-specific endpoint.
   // you used common.
   // Mitigation: as explained in the message from Azure AD, the authority you use in the application needs
   // to be tenanted or otherwise "organizations". change the
   // "Tenant": property in the appsettings.json to be a GUID (tenant Id), or domain name (contoso.com)
   // if such a domain is registered with your tenant
   // or "organizations", if you want this application to sign-in users in any Work and School accounts.
   // ------------------------------------------------------------------------

  }
  catch (MsalServiceException ex) when (ex.ErrorCode == "unauthorized_client")
  {
   // ------------------------------------------------------------------------
   // AADSTS700016: Application with identifier '{clientId}' was not found in the directory '{domain}'.
   // This can happen if the application has not been installed by the administrator of the tenant or consented
   // to by any user in the tenant.
   // You may have sent your authentication request to the wrong tenant
   // Cause: The clientId in the appsettings.json might be wrong
   // Mitigation: check the clientId and the app registration
   // ------------------------------------------------------------------------
  }
  catch (MsalServiceException ex) when (ex.ErrorCode == "invalid_client")
  {
   // ------------------------------------------------------------------------
   // AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.
   // Explanation: this can happen if your application was not registered as a public client application in Azure AD
   // Mitigation: in the Azure portal, edit the manifest for your application and set the `allowPublicClient` to `true`
   // ------------------------------------------------------------------------
  }
  catch (MsalServiceException)
  {
   throw;
  }

  catch (MsalClientException ex) when (ex.ErrorCode == "unknown_user_type")
  {
   // Message = "Unsupported User Type 'Unknown'. Please see https://aka.ms/msal-net-up"
   // The user is not recognized as a managed user, or a federated user. Azure AD was not
   // able to identify the IdP that needs to process the user
   throw new ArgumentException("U/P: Wrong username", ex);
  }
  catch (MsalClientException ex) when (ex.ErrorCode == "user_realm_discovery_failed")
  {
   // The user is not recognized as a managed user, or a federated user. Azure AD was not
   // able to identify the IdP that needs to process the user. That's for instance the case
   // if you use a phone number
   throw new ArgumentException("U/P: Wrong username", ex);
  }
  catch (MsalClientException ex) when (ex.ErrorCode == "unknown_user")
  {
   // the username was probably empty
   // ex.Message = "Could not identify the user logged into the OS. See https://aka.ms/msal-net-iwa for details."
   throw new ArgumentException("U/P: Wrong username", ex);
  }
  catch (MsalClientException ex) when (ex.ErrorCode == "parsing_wstrust_response_failed")
  {
   // ------------------------------------------------------------------------
   // In the case of a Federated user (that is owned by a federated IdP, as opposed to a managed user owned in an Azure AD tenant)
   // ID3242: The security token could not be authenticated or authorized.
   // The user does not exist or has entered the wrong password
   // ------------------------------------------------------------------------
  }
 }

 Console.WriteLine(result.Account.Username);
}

Zie AcquireTokenByUsernamePassword AcquireTokenByUsernamePasswordParameterBuildervoor meer informatie over alle modifiers die kunnen worden toegepast op .

Opdrachtregelprogramma zonder webbrowser

Stroom voor apparaatcode

Als u een opdrachtregelprogramma schrijft dat geen webbesturingselementen heeft en u de vorige stromen niet kunt of wilt gebruiken, gebruikt u de apparaatcodestroom.

Voor interactieve verificatie met Azure AD is een webbrowser vereist. Zie Gebruik van webbrowsers voor meer informatie. Als u gebruikers wilt verifiëren op apparaten of besturingssystemen die geen webbrowser bieden, kan de gebruiker met de apparaatcodestroom een ander apparaat, zoals een computer of een mobiele telefoon, gebruiken om zich interactief aan te melden. Met behulp van de apparaatcodestroom verkrijgt de toepassing tokens via een proces in twee stappen dat is ontworpen voor deze apparaten of besturingssystemen. Voorbeelden van dergelijke toepassingen zijn toepassingen die worden uitgevoerd op iOT of opdrachtregelprogramma's (CLI). Het idee is dat:

  1. Wanneer gebruikersverificatie is vereist, biedt de app een code voor de gebruiker. De gebruiker wordt gevraagd om een ander apparaat, zoals een smartphone met internetverbinding, te gebruiken om naar een URL te gaan, bijvoorbeeld https://microsoft.com/devicelogin . Vervolgens wordt de gebruiker gevraagd de code in te voeren. De webpagina leidt de gebruiker door een normale verificatie-ervaring, die indien nodig toestemmingsprompts en meervoudige verificatie bevat.

  2. Na een geslaagde verificatie ontvangt de opdrachtregel-app de vereiste tokens via een back-kanaal en gebruikt deze om de benodigde web-API-aanroepen uit te voeren.

Gebruik deze

IPublicClientApplicationbevat een methode met de naam AcquireTokenWithDeviceCode .

 AcquireTokenWithDeviceCode(IEnumerable<string> scopes,
                            Func<DeviceCodeResult, Task> deviceCodeResultCallback)

Deze methode heeft als parameters:

  • De scopes om een toegangs token voor aan te vragen.

  • Een callback die de DeviceCodeResult ontvangt.

    Eigenschappen van DeviceCodeResult

De volgende voorbeeldcode bevat de samenvatting van de meeste huidige gevallen, met uitleg over het soort uitzonderingen dat u kunt krijgen en de risicobeperking. Zie active-directory-dotnetcore-devicecodeflow-v2 op GitHub voor een volledig functionele codevoorbeeld.

private const string ClientId = "<client_guid>";
private const string Authority = "https://login.microsoftonline.com/contoso.com";
private readonly string[] scopes = new string[] { "user.read" };

static async Task<AuthenticationResult> GetATokenForGraph()
{
    IPublicClientApplication pca = PublicClientApplicationBuilder
            .Create(ClientId)
            .WithAuthority(Authority)
            .WithDefaultRedirectUri()
            .Build();

    var accounts = await pca.GetAccountsAsync();

    // All AcquireToken* methods store the tokens in the cache, so check the cache first
    try
    {
        return await pca.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException ex)
    {
        // No token found in the cache or AAD insists that a form interactive auth is required (e.g. the tenant admin turned on MFA)
        // If you want to provide a more complex user experience, check out ex.Classification

        return await AcquireByDeviceCodeAsync(pca);
    }
}

private static async Task<AuthenticationResult> AcquireByDeviceCodeAsync(IPublicClientApplication pca)
{
    try
    {
        var result = await pca.AcquireTokenWithDeviceCode(scopes,
            deviceCodeResult =>
            {
                    // This will print the message on the console which tells the user where to go sign-in using
                    // a separate browser and the code to enter once they sign in.
                    // The AcquireTokenWithDeviceCode() method will poll the server after firing this
                    // device code callback to look for the successful login of the user via that browser.
                    // This background polling (whose interval and timeout data is also provided as fields in the
                    // deviceCodeCallback class) will occur until:
                    // * The user has successfully logged in via browser and entered the proper code
                    // * The timeout specified by the server for the lifetime of this code (typically ~15 minutes) has been reached
                    // * The developing application calls the Cancel() method on a CancellationToken sent into the method.
                    //   If this occurs, an OperationCanceledException will be thrown (see catch below for more details).
                    Console.WriteLine(deviceCodeResult.Message);
                return Task.FromResult(0);
            }).ExecuteAsync();

        Console.WriteLine(result.Account.Username);
        return result;
    }

    // TODO: handle or throw all these exceptions depending on your app
    catch (MsalServiceException ex)
    {
        // Kind of errors you could have (in ex.Message)

        // AADSTS50059: No tenant-identifying information found in either the request or implied by any provided credentials.
        // Mitigation: as explained in the message from Azure AD, the authoriy needs to be tenanted. you have probably created
        // your public client application with the following authorities:
        // https://login.microsoftonline.com/common or https://login.microsoftonline.com/organizations

        // AADSTS90133: Device Code flow is not supported under /common or /consumers endpoint.
        // Mitigation: as explained in the message from Azure AD, the authority needs to be tenanted

        // AADSTS90002: Tenant <tenantId or domain you used in the authority> not found. This may happen if there are
        // no active subscriptions for the tenant. Check with your subscription administrator.
        // Mitigation: if you have an active subscription for the tenant this might be that you have a typo in the
        // tenantId (GUID) or tenant domain name.
    }
    catch (OperationCanceledException ex)
    {
        // If you use a CancellationToken, and call the Cancel() method on it, then this *may* be triggered
        // to indicate that the operation was cancelled.
        // See https://docs.microsoft.com/dotnet/standard/threading/cancellation-in-managed-threads
        // for more detailed information on how C# supports cancellation in managed threads.
    }
    catch (MsalClientException ex)
    {
        // Possible cause - verification code expired before contacting the server
        // This exception will occur if the user does not manage to sign-in before a time out (15 mins) and the
        // call to `AcquireTokenWithDeviceCode` is not cancelled in between
    }
}

Tokencache op basis van bestanden

In MSAL.NET wordt standaard een in-memory tokencache verstrekt.

Serialisatie kan worden aangepast in Windows-desktop-apps en web-apps of web-API's

In het geval van .NET Framework en .NET Core, als u niets extra's doet, duurt de cache van het in-memory token de duur van de toepassing. Als u wilt weten waarom serialisatie niet standaard wordt aangeboden, moet u er wel aan denken dat MSAL .NET Desktop- of .NET Core-toepassingen console- of Windows-toepassingen kunnen zijn (die toegang zouden hebben tot het bestandssysteem), maar ook webtoepassingen of web-API's. Deze web-apps en web-API's kunnen gebruikmaken van bepaalde specifieke cachemechanismen, zoals databases, gedistribueerde caches en Redis-caches. Als u een toepassing voor een permanente tokencache in .NET Desktop of .NET Core wilt hebben, moet u de serialisatie aanpassen.

Klassen en interfaces die betrokken zijn bij het serialiseren van tokencache zijn de volgende typen:

  • ITokenCache, die gebeurtenissen definieert om zich te abonneren op serialisatieaanvragen voor tokencache en methoden voor het serialiseren of deserialiseren van de cache in verschillende indelingen (ADAL v3.0, MSAL 2.x en MSAL 3.x = ADAL v5.0).

  • TokenCacheCallback is een callback die wordt doorgegeven aan de gebeurtenissen, zodat u de serialisatie kunt afhandelen. Ze worden aangeroepen met argumenten van het type TokenCacheNotificationArgs .

  • TokenCacheNotificationArgs biedt alleen de toepassing ClientId en een verwijzing naar de gebruiker waarvoor het token beschikbaar is.

    Serialisatiediagram van tokencache

Belangrijk

MSAL.NET maakt tokencaches voor u en biedt u de cache wanneer u de eigenschappen en IToken UserTokenCache aanroept van een AppTokenCache toepassing. U hoeft de interface niet zelf te implementeren. Wanneer u serialisatie van een aangepaste tokencache implementeert, is het volgende uw verantwoordelijkheid:

  • Reageren op BeforeAccess gebeurtenissen AfterAccess en, of hun Async-tegenhanger. De BeforeAccess gemachtigde is verantwoordelijk voor het deserialiseren van de cache. De AfterAccess gemachtigde is verantwoordelijk voor het serialiseren van de cache.
  • U moet weten dat een deel van deze gebeurtenissen blobs opgeslagen of geladen, die via het gebeurtenisargument worden doorgegeven aan de opslag die u wilt.

De strategieën verschillen, afhankelijk van of u een tokencacheseralisatie schrijft voor een openbare clienttoepassing, zoals een bureaublad of een vertrouwelijke clienttoepassing, zoals een web-app of web-API of een daemon-app.

Sinds MSAL v2.x hebt u verschillende opties. Uw keuze is afhankelijk van het feit of u de cache alleen wilt serialiseren naar de MSAL.NET-indeling. Dit is een uniforme indelingcache die gebruikelijk is voor MSAL, maar ook voor alle platformen. Of misschien wilt u ook ondersteuning bieden voor de serialisatie van verouderde tokencache van ADAL v3.

De aanpassing van de serialisatie van tokencache om de status van eenmalige aanmelding te delen tussen ADAL.NET 3.x, ADAL.NET 5.x en MSAL.NET wordt uitgelegd in een deel van het voorbeeld active-directory-dotnet-v1-to-v2.

Eenvoudige serialisatie van tokencache (alleen MSAL)

Het volgende voorbeeld is een naïve implementatie van aangepaste serialisatie van een tokencache voor desktoptoepassingen. Hier staat de gebruikerscache van het token in een bestand in dezelfde map als de toepassing of in een map per gebruiker per app in het geval dat de app een verpakte bureaubladtoepassing is. Zie het volgende voorbeeld voor de volledige code: active-directory-dotnet-desktop-msgraph-v2.

Nadat u de toepassing hebt gemaakt, kunt u de serialisatie inschakelen door de toepassing aan te roepen TokenCacheHelper.EnableSerialization() en door te UserTokenCache geven.

app = PublicClientApplicationBuilder.Create(ClientId)
    .Build();
TokenCacheHelper.EnableSerialization(app.UserTokenCache);

Deze helperklasse ziet eruit als het volgende codefragment:

static class TokenCacheHelper
 {
  public static void EnableSerialization(ITokenCache tokenCache)
  {
   tokenCache.SetBeforeAccess(BeforeAccessNotification);
   tokenCache.SetAfterAccess(AfterAccessNotification);
   try
   {
    // For packaged desktop apps (MSIX packages) the executing assembly folder is read-only. 
    // In that case we need to use Windows.Storage.ApplicationData.Current.LocalCacheFolder.Path + "\msalcache.bin" 
    // which is a per-app read/write folder for packaged apps.
    // See https://docs.microsoft.com/windows/msix/desktop/desktop-to-uwp-behind-the-scenes
    CacheFilePath = System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalCacheFolder.Path, "msalcache.bin3");
   }
   catch (System.InvalidOperationException)
   {
    // Fall back for an un-packaged desktop app
    CacheFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location + ".msalcache.bin";
   }
  }

  /// <summary>
  /// Path to the token cache
  /// </summary>
  public static string CacheFilePath { get; private set; }

  private static readonly object FileLock = new object();

  private static void BeforeAccessNotification(TokenCacheNotificationArgs args)
  {
   lock (FileLock)
   {
    args.TokenCache.DeserializeMsalV3(File.Exists(CacheFilePath)
            ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath),
                                      null,
                                      DataProtectionScope.CurrentUser)
            : null);
   }
  }

  private static void AfterAccessNotification(TokenCacheNotificationArgs args)
  {
   // if the access operation resulted in a cache update
   if (args.HasStateChanged)
   {
    lock (FileLock)
    {
     // reflect changesgs in the persistent store
     File.WriteAllBytes(CacheFilePath,
                         ProtectedData.Protect(args.TokenCache.SerializeMsalV3(),
                                                 null,
                                                 DataProtectionScope.CurrentUser)
                         );
    }
   }
  }
 }

Een preview van een op bestanden gebaseerde serializer voor het cacheken van een token van productkwaliteit voor openbare clienttoepassingen voor bureaubladtoepassingen die worden uitgevoerd op Windows, Mac en Linux is beschikbaar via de opensource-bibliotheek Microsoft.Identity.Client.Extensions.Msal. U kunt deze in uw toepassingen opnemen vanuit het volgende NuGet-pakket: Microsoft.Identity.Client.Extensions.Msal.

Notitie

Disclaimer: De bibliotheek Microsoft.Identity.Client.Extensions.Msal is een uitbreiding op MSAL.NET. Klassen in deze bibliotheken kunnen in de toekomst MSAL.NET, zoals of met belangrijke wijzigingen.

Dual token cache serialization (MSAL unified cache + ADAL v3)

Mogelijk wilt u serialisatie van tokencache implementeren met de Unified Cache-indeling. Deze indeling is gebruikelijk voor ADAL.NET 4.x en MSAL.NET 2.x, en met andere MSAL's van dezelfde generatie of ouder, op hetzelfde platform. Laat u inspireren door de volgende code:

string appLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location;
string cacheFolder = Path.GetFullPath(appLocation) + @"..\..\..\..");
string adalV3cacheFileName = Path.Combine(cacheFolder, "cacheAdalV3.bin");
string unifiedCacheFileName = Path.Combine(cacheFolder, "unifiedCache.bin");

IPublicClientApplication app;
app = PublicClientApplicationBuilder.Create(clientId)
                                    .Build();
FilesBasedTokenCacheHelper.EnableSerialization(app.UserTokenCache,
                                               unifiedCacheFileName,
                                               adalV3cacheFileName);

Deze keer ziet de helperklasse eruit als de volgende code:

using System;
using System.IO;
using System.Security.Cryptography;
using Microsoft.Identity.Client;

namespace CommonCacheMsalV3
{
 /// <summary>
 /// Simple persistent cache implementation of the dual cache serialization (ADAL V3 legacy
 /// and unified cache format) for a desktop applications (from MSAL 2.x)
 /// </summary>
 static class FilesBasedTokenCacheHelper
 {
  /// <summary>
  /// Get the user token cache
  /// </summary>
  /// <param name="adalV3CacheFileName">File name where the cache is serialized with the
  /// ADAL V3 token cache format. Can
  /// be <c>null</c> if you don't want to implement the legacy ADAL V3 token cache
  /// serialization in your MSAL 2.x+ application</param>
  /// <param name="unifiedCacheFileName">File name where the cache is serialized
  /// with the Unified cache format, common to
  /// ADAL V4 and MSAL V2 and above, and also across ADAL/MSAL on the same platform.
  ///  Should not be <c>null</c></param>
  /// <returns></returns>
  public static void EnableSerialization(ITokenCache cache, string unifiedCacheFileName, string adalV3CacheFileName)
  {
   UnifiedCacheFileName = unifiedCacheFileName;
   AdalV3CacheFileName = adalV3CacheFileName;

   cache.SetBeforeAccess(BeforeAccessNotification);
   cache.SetAfterAccess(AfterAccessNotification);
  }

  /// <summary>
  /// File path where the token cache is serialized with the unified cache format
  /// (ADAL.NET V4, MSAL.NET V3)
  /// </summary>
  public static string UnifiedCacheFileName { get; private set; }

  /// <summary>
  /// File path where the token cache is serialized with the legacy ADAL V3 format
  /// </summary>
  public static string AdalV3CacheFileName { get; private set; }

  private static readonly object FileLock = new object();

  public static void BeforeAccessNotification(TokenCacheNotificationArgs args)
  {
   lock (FileLock)
   {
    args.TokenCache.DeserializeAdalV3(ReadFromFileIfExists(AdalV3CacheFileName));
    try
    {
     args.TokenCache.DeserializeMsalV3(ReadFromFileIfExists(UnifiedCacheFileName));
    }
    catch(Exception ex)
    {
     // Compatibility with the MSAL v2 cache if you used one
     args.TokenCache.DeserializeMsalV2(ReadFromFileIfExists(UnifiedCacheFileName));
    }
   }
  }

  public static void AfterAccessNotification(TokenCacheNotificationArgs args)
  {
   // if the access operation resulted in a cache update
   if (args.HasStateChanged)
   {
    lock (FileLock)
    {
     WriteToFileIfNotNull(UnifiedCacheFileName, args.TokenCache.SerializeMsalV3());
     if (!string.IsNullOrWhiteSpace(AdalV3CacheFileName))
     {
      WriteToFileIfNotNull(AdalV3CacheFileName, args.TokenCache.SerializeAdalV3());
     }
    }
   }
  }

  /// <summary>
  /// Read the content of a file if it exists
  /// </summary>
  /// <param name="path">File path</param>
  /// <returns>Content of the file (in bytes)</returns>
  private static byte[] ReadFromFileIfExists(string path)
  {
   byte[] protectedBytes = (!string.IsNullOrEmpty(path) && File.Exists(path))
       ? File.ReadAllBytes(path) : null;
   byte[] unprotectedBytes = encrypt ?
       ((protectedBytes != null) ? ProtectedData.Unprotect(protectedBytes, null, DataProtectionScope.CurrentUser) : null)
       : protectedBytes;
   return unprotectedBytes;
  }

  /// <summary>
  /// Writes a blob of bytes to a file. If the blob is <c>null</c>, deletes the file
  /// </summary>
  /// <param name="path">path to the file to write</param>
  /// <param name="blob">Blob of bytes to write</param>
  private static void WriteToFileIfNotNull(string path, byte[] blob)
  {
   if (blob != null)
   {
    byte[] protectedBytes = encrypt
      ? ProtectedData.Protect(blob, null, DataProtectionScope.CurrentUser)
      : blob;
    File.WriteAllBytes(path, protectedBytes);
   }
   else
   {
    File.Delete(path);
   }
  }

  // Change if you want to test with an un-encrypted blob (this is a json format)
  private static bool encrypt = true;
 }
}

(Geavanceerd) Toegang tot de tokens in de cache van de gebruiker in achtergrond-apps en -services

U kunt de implementatie van de token cache van MSAL gebruiken om achtergrond-apps, Api's en services toe te staan de toegangs token cache te gebruiken om namens gebruikers in hun afwezigheid te blijven handelen. Dit is vooral nuttig als de achtergrond-apps en-services moeten blijven werken namens de gebruiker nadat de gebruiker de front-end-web-app heeft afgesloten.

De meeste achtergrond processen gebruiken nu toepassings machtigingen wanneer ze met de gegevens van een gebruiker moeten werken zonder dat ze zich hoeven te verifiëren of opnieuw te verifiëren. Omdat voor toepassings machtigingen vaak een beheerders toestemming vereist is, waarvoor uitbrei ding van bevoegdheden nodig is, wordt onnodig frictie aangetroffen, omdat de ontwikkelaar geen toestemming heeft gekregen te verkrijgen dan de gebruiker die oorspronkelijk heeft gestemd met de app.

Dit code voorbeeld in GitHub laat zien hoe u deze niet-vereiste wrijving kunt voor komen door de token cache van MSAL te openen vanaf de achtergrond-apps:

De token cache van de aangemelde gebruiker openen vanaf de achtergrond-apps, Api's en services

Volgende stappen

Ga verder met het volgende artikel in dit scenario: Een web-API aanroepen vanuit de bureaublad-app.