Ausführen automatischer Integrationstests

Als Entwickler möchten Sie automatisierte Integrationstests für die von Ihnen entwickelten Apps ausführen. Das Aufrufen Ihrer durch Microsoft Identity Platform geschützten API (oder anderer geschützter APIs wie Microsoft Graph) in automatisierten Integrationstests ist eine Herausforderung. Microsoft Entra ID erfordert häufig interaktive Benutzeranweisungen, die schwer zu automatisieren sind. In diesem Artikel wird beschrieben, wie Sie einen nicht interaktiven Flow namens Resource Owner Password Credential Grant (ROPC)verwenden können, um Benutzer automatisch zu Testzwecken anzumelden.

Um sich auf Ihre automatisierten Integrationstests vorzubereiten, erstellen Sie einige Testbenutzer, erstellen und konfigurieren Sie eine App-Registrierung, und nehmen Sie möglicherweise einige Konfigurationsänderungen an Ihrem Mandanten vor. Einige dieser Schritte erfordern Administratorrechte. Außerdem empfiehlt Microsoft, den ROPC-Flow nicht in einer Produktionsumgebung zu verwenden. Erstellen Sie einen separaten Testmandanten, bei dem Sie Administrator sind, damit Sie Ihre automatisierten Integrationstests sicher und effektiv ausführen können.

Warnung

Außerdem empfiehlt Microsoft, den ROPC-Flow nicht in einer Produktionsumgebung zu verwenden. In den meisten Produktionsszenarien sind sicherere Alternativen verfügbar und werden daher empfohlen. Dieser ROPC-Flow erfordert ein sehr hohes Maß an Vertrauen in die Anwendung und birgt Risiken, die in anderen Authentifizierungsflows nicht vorhanden sind. Sie sollten diesen Flow nur für Testzwecke in einem separaten Testmandantenund nur für Testbenutzer verwenden.

Wichtig

  • Microsoft Identity Platform unterstützt ROPC nur bei Microsoft Entra-Mandanten, nicht für persönliche Konten. Das bedeutet, Sie müssen einen mandantenspezifischen Endpunkt (https://login.microsoftonline.com/{TenantId_or_Name}) oder den Endpunkt organizations verwenden.
  • Persönliche Konten, die zu einem Microsoft Entra-Mandanten eingeladen werden, können ROPC nicht verwenden.
  • Konten ohne Kennwörter können sich nicht mit ROPC anmelden. Dies bedeutet, dass Features wie SMS-Anmeldung, FIDO und die Authenticator-App bei diesem Flow nicht funktionieren.
  • Wenn Benutzer die mehrstufige Authentifizierung (Multi-Factor Authentication, MFA) verwenden müssen, um sich bei der Anwendung anzumelden, werden Sie stattdessen blockiert.
  • ROPC wird in Szenarien mit Hybrididentitätsverbund, beispielsweise bei Verwendung von Microsoft Entra ID und Active Directory Federation Services (AD FS) für die Authentifizierung lokaler Konten, nicht unterstützt. Wenn Benutzer*innen vollständig auf eine Seite eines lokalen Identitätsanbieters weitergeleitet werden, kann Microsoft Entra ID den Benutzernamen und das Kennwort nicht anhand dieses Identitätsanbieters testen. Die Passthrough-Authentifizierung wird mit ROPC allerdings unterstützt.
  • Eine Ausnahme für ein Szenario mit Hybrididentitätsverbund wäre: Durch Festlegen von AllowCloudPasswordValidation auf „TRUE“ für die Richtlinie zur Startbereichsermittlung kann der ROPC-Flow für Verbundbenutzer verwendet werden, wenn das lokale Kennwort mit der Cloud synchronisiert wird. Weitere Informationen finden Sie unter Aktivieren der direkten ROPC-Authentifizierung von Verbundbenutzern für Legacyanwendungen.

Erstellen Sie einen separaten Testmandanten

Die Verwendung des ROPC-Authentifizierungsablaufs ist in einer Produktionsumgebung riskant. Erstellen Sie daher einen separaten Mandanten, um Ihre Anwendungen zu testen. Sie können einen vorhandenen Testmandanten verwenden, aber Sie müssen Administrator im Mandanten sein, da einige der folgenden Schritte Administratorrechte erfordern.

Erstellen und Konfigurieren eines Schlüsseltresors

Es wird empfohlen, die Testbenutzernamen und Kennwörter sicher als Geheimnisse in Azure Key Vault zu speichern. Wenn Sie die Tests später ausführen, werden die Tests im Kontext eines Sicherheitsprinzipals ausgeführt. Der Sicherheitsprinzipal ist ein/e Microsoft Entra-Benutzer*in, wenn Sie Tests lokal ausführen (z. B. in Visual Studio oder Visual Studio Code), oder ein Dienstprinzipal oder eine verwaltete Identität, wenn Sie Tests in Azure Pipelines oder einer anderen Azure-Ressource ausführen. Der Sicherheitsprinzipal muss über die Berechtigungen Lesen und Auflisten von Geheimnissen verfügen, damit der Test Runner die Testbenutzernamen und Kennwörter aus Ihrem Schlüsseltresor abrufen kann. Weitere Informationen finden Sie unter Authentifizierung in Azure Key Vault.

  1. Erstellen Sie einen neuen Schlüsseltresor, wenn Sie noch keinen besitzen.
  2. Notieren Sie sich den Tresor-URI-Eigenschaftswert (ähnlich wie https://<your-unique-keyvault-name>.vault.azure.net/), der im Beispieltest weiter unten in diesem Artikel verwendet wird.
  3. Weisen Sie eine Zugriffsrichtlinie für den Sicherheitsprinzipal zu, der die Tests ausführt. Erteilen Sie dem Benutzer, Dienstprinzipal oder der verwalteten Identität Berechtigungen zum Abrufen und Auflisten von Geheimnissen im Schlüsseltresor.

Erstellen von Testbenutzern

Tipp

Die Schritte in diesem Artikel können je nach dem Portal, mit dem Sie beginnen, geringfügig variieren.

Erstellen Sie einige Testbenutzer in Ihrem Mandanten zu Testzwecken. Da es sich bei den Testbenutzern nicht um echte Menschen handelt, empfiehlt es sich, komplexe Kennwörter zuzuweisen und diese Kennwörter sicher als Geheimnisse in Azure Key Vault zu speichern.

  1. Melden Sie sich beim Microsoft Entra Admin Center mindestens als Cloudanwendungsadministrator an.
  2. Browsen Sie zu Identität>Benutzer>Alle Benutzer.
  3. Wählen Sie Neuer Benutzer aus, und erstellen Sie mindestens ein Testbenutzerkonto in Ihrem Verzeichnis.
  4. Im Beispieltest weiter unten in diesem Artikel wird ein einzelner Testbenutzer verwendet. Fügen Sie den Testbenutzernamen und das Kennwort als Geheimnisse in den Schlüsseltresor ein, den Sie zuvor erstellt haben. Fügen Sie den Benutzernamen als Geheimnis namens "TestUserName" und das Kennwort als Geheimnis mit dem Namen "TestPassword" hinzu.

Erstellen und konfigurieren Sie eine App-Registrierung

Registrieren Sie eine Anwendung, die beim Aufrufen von APIs während des Tests als Client-App fungiert. Dies sollte nicht die gleiche Anwendung sein, die Sie möglicherweise bereits in der Produktion haben. Sie sollten über eine separate App verfügen, die nur zu Testzwecken verwendet werden kann.

Registrieren einer Anwendung

Erstellen Sie eine App-Registrierung. Sie können die Schritte in der Schnellstartanleitung für die App-Registrierung ausführen. Sie müssen keinen Umleitungs-URI oder Anmeldeinformationen hinzufügen, damit Sie diese Abschnitte überspringen können.

Notieren Sie sich die Anwendungs-(Client-)ID, die im Beispieltest weiter unten in diesem Artikel verwendet wird.

Aktivieren Ihrer App für öffentliche Clientflows

ROPC ist ein öffentlicher Clientflow, daher müssen Sie Ihre App für öffentliche Clientflows aktivieren. Wechseln Sie in Ihrer App-Registrierung im Microsoft Entra Admin Center zu Authentifizierung>Erweiterte Einstellungen>Öffentliche Clientflows zulassen. Legen Sie die Umschaltfläche auf Jafest.

Da ROPC kein interaktiver Flow ist, werden Sie nicht mit einem Zustimmungsbildschirm aufgefordert, diesen zur Laufzeit zuzustimmen. Stimmen Sie den Berechtigungen vorab zu, um Fehler beim Abrufen von Token zu vermeiden.

Hinzufügen von Berechtigungen für Ihre App Fügen Sie der App keine sensiblen oder hoch privilegierten Berechtigungen hinzu. Es wird empfohlen, Ihre Testszenarien auf grundlegende Integrationsszenarien für die Integration in Microsoft Entra ID zu beschränken.

Wechseln Sie in Ihrer App-Registrierung im Microsoft Entra Admin Center zu API-Berechtigungen>Berechtigung hinzufügen. Fügen Sie die Berechtigungen hinzu, die Sie zum Aufrufen der APIs benötigen, die Sie verwenden. In einem weiteren Testbeispiel in diesem Artikel werden die Berechtigungen https://graph.microsoft.com/User.Read und https://graph.microsoft.com/User.ReadBasic.All verwendet.

Nachdem die Berechtigungen hinzugefügt wurden, müssen Sie ihnen zustimmen. Die Art und Weise, wie Sie den Berechtigungen zustimmen, hängt davon ab, ob sich Ihre Test-App im selben Mandanten wie die App-Registrierung befindet und ob Sie ein Administrator im Mandanten sind.

App- und App-Registrierung befinden sich im selben Mandanten, und Sie sind Administrator.

Wenn Sie Ihre App im selben Mandanten testen möchten, in dem Sie sie registriert haben, und Sie in diesem Mandanten als Administrator*in fungieren, können Sie den Berechtigungen über das Microsoft Entra Admin Center zustimmen. Wechseln Sie in Ihrer App-Registrierung im Azure-Portal zu API-Berechtigungen und wählen Sie die Schaltfläche Administratoreinwilligung für <your_tenant_name> erteilen neben Berechtigung hinzufügen und dann zur Bestätigung Ja.

App- und App-Registrierungen befinden sich in unterschiedlichen Mandanten, oder Sie sind kein Administrator.

Wenn Sie Ihre App nicht im selben Mandanten testen möchten, in dem Sie sie registriert haben, oder Sie in diesem Mandanten nicht als Administrator*in fungieren, können Sie den Berechtigungen nicht über das Microsoft Entra Admin Center zustimmen. Sie können einigen Berechtigungen jedoch weiterhin zustimmen, indem Sie eine Anmeldeaufforderung in einem Webbrowser auslösen.

Wechseln Sie in Ihrer App-Registrierung im Microsoft Entra Admin Center zu Authentifizierung>Plattformkonfigurationen>Plattform hinzufügen>Web. Fügen Sie den Umleitungs-URI "https://localhost"" hinzu und wählen Sie Konfigurieren aus.

Es gibt keine Möglichkeit für Benutzer ohne Administratorrechte, über die Azure-Portal vorab zuzustimmen. Senden Sie daher die folgende Anforderung in einem Browser. Wenn Sie zur Eingabe des Anmeldebildschirms aufgefordert werden, melden Sie sich mit einem Testkonto an, das Sie in einem vorherigen Schritt erstellt haben. Stimmen Sie den Berechtigungen zu, zu denen Sie aufgefordert werden. Möglicherweise müssen Sie diesen Schritt für jede API wiederholen, die Sie aufrufen und den Benutzer testen möchten, den Sie verwenden möchten.

// Line breaks for legibility only

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id={your_client_ID}
&response_type=code
&redirect_uri=https://localhost
&response_mode=query
&scope={resource_you_want_to_call}/.default
&state=12345

Ersetzen Sie {tenant} durch Ihre Mandanten-ID, {your_client_ID} durch die Client-ID Ihrer Anwendung und {resource_you_want_to_call} durch die ID-URI (z. B. "https://graph.microsoft.com") oder App-ID der API, auf die Sie zugreifen möchten.

Ausschließen von Test-Apps und -Benutzern aus Ihrer MFA-Richtlinie

Ihr Mandant verfügt wahrscheinlich über eine Richtlinie für bedingten Zugriff, die eine Multi-Faktor-Authentifizierung (MFA) für alle Benutzer erfordert, wie von Microsoft empfohlen. MFA funktioniert nicht mit ROPC, daher müssen Sie Ihre Testanwendungen und Testbenutzer von dieser Anforderung ausschließen.

So schließen Sie Benutzerkonten aus:

  1. Melden Sie sich beim Microsoft Entra Admin Center mindestens als Cloudanwendungsadministrator an.
  2. Wechseln Sie im linken Navigationsbereich zu Identität>Security Center, und wählen Sie dann Bedingter Zugriff aus.
  3. Wählen Sie unter Richtlinien die Richtlinie für bedingten Zugriff aus, die MFA erfordert.
  4. Wählen Sie Benutzer- oder Workloadidentitäten aus.
  5. Wählen Sie die Registerkarte Ausschließen und dann das Kontrollkästchen Nutzer und Gruppen aus.
  6. Wählen Sie unter Ausgeschlossene Benutzer auswählen die auszuschließende/n Benutzerkonten aus.
  7. Wählen Sie die Schaltfläche Auswählen und dann Speichern.

So schließen Sie eine Testanwendung aus:

  1. Wählen Sie unter Richtlinien die Richtlinie für bedingten Zugriff aus, die MFA erfordert.
  2. Wählen Sie Cloud-Apps oder -aktionen aus.
  3. Wählen Sie die Registerkarte Ausschließen und dann Ausgeschlossene Cloud-Apps auswählen.
  4. Wählen Sie unter Ausgeschlossene Cloud-Apps auswählen die Apps aus, die Sie ausschließen möchten.
  5. Wählen Sie die Schaltfläche Auswählen und dann Speichern.

Schreiben der Anwendung in Tests

Nachdem Sie nun eingerichtet sind, können Sie Ihre automatisierten Tests schreiben. Die folgenden Tests sind für:

  1. Der .NET-Beispielcode verwendet Microsoft Authentication Library (MSAL) und xUnit, ein allgemeines Testframework.
  2. Der JavaScript-Beispielcode verwendet Microsoft Authentication Library (MSAL) und Playwright, ein allgemeines Testframework.

Einrichten der Datei „appsettings.json“

Fügen Sie der Datei appsettings.json Ihres Testprojekts die Client-ID der zuvor erstellten Test-App, die erforderlichen Bereiche und den Schlüsseltresor-URI hinzu.

{
  "Authentication": {
    "AzureCloudInstance": "AzurePublic", //Will be different for different Azure clouds, like US Gov
    "AadAuthorityAudience": "AzureAdMultipleOrgs",
    "ClientId": <your_client_ID>
  },

  "WebAPI": {
    "Scopes": [
      //For this Microsoft Graph example.  Your value(s) will be different depending on the API you're calling
      "https://graph.microsoft.com/User.Read",
      //For this Microsoft Graph example.  Your value(s) will be different depending on the API you're calling
      "https://graph.microsoft.com/User.ReadBasic.All"
    ]
  },

  "KeyVault": {
    "KeyVaultUri": "https://<your-unique-keyvault-name>.vault.azure.net//"
  }
}

Einrichten des Clients für die Verwendung in allen Testklassen

Verwenden Sie SecretClient(), um den geheimen Benutzernamen und das Kennwort für den Test von Azure Key Vault abzurufen. Darüber hinaus wird im Code das exponentielle Backoff für Wiederholungen verwendet, falls Key Vault gedrosselt wird.

DefaultAzureCredential() authentifiziert sich mit Azure Key Vault durch Abrufen eines Zugriffstokens von einem Dienstprinzipal, der von Umgebungsvariablen oder einer verwalteten Identität konfiguriert wurde (wenn der Code auf einer Azure-Ressource mit einer verwalteten Identität ausgeführt wird). Wenn der Code lokal ausgeführt wird, DefaultAzureCredentialverwendet die Anmeldeinformationen des lokalen Benutzers. Weitere Informationen finden Sie im Inhalt der Azure Identity-Clientbibliothek.

Verwenden Sie die Microsoft Authentication Library (MSAL), um sich mithilfe des ROPC-Flows zu authentifizieren und ein Zugriffstoken abzurufen. Das Zugriffstoken wird als Bearertoken in der HTTP-Anforderung übergeben.

using Xunit;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using System.Security;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.Extensions.Configuration;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Azure.Core;
using System;

public class ClientFixture : IAsyncLifetime
{
    public HttpClient httpClient;

    public async Task InitializeAsync()
    {
        var builder = new ConfigurationBuilder().AddJsonFile("<path-to-json-file>");

        IConfigurationRoot Configuration = builder.Build();

        var PublicClientApplicationOptions = new PublicClientApplicationOptions();
        Configuration.Bind("Authentication", PublicClientApplicationOptions);
        var app = PublicClientApplicationBuilder.CreateWithApplicationOptions(PublicClientApplicationOptions)
            .Build();

        SecretClientOptions options = new SecretClientOptions()
        {
            Retry =
                {
                    Delay= TimeSpan.FromSeconds(2),
                    MaxDelay = TimeSpan.FromSeconds(16),
                    MaxRetries = 5,
                    Mode = RetryMode.Exponential
                 }
        };

        string keyVaultUri = Configuration.GetValue<string>("KeyVault:KeyVaultUri");
        var client = new SecretClient(new Uri(keyVaultUri), new DefaultAzureCredential(), options);

        KeyVaultSecret userNameSecret = client.GetSecret("TestUserName");
        KeyVaultSecret passwordSecret = client.GetSecret("TestPassword");

        string password = passwordSecret.Value;
        string username = userNameSecret.Value;
        string[] scopes = Configuration.GetSection("WebAPI:Scopes").Get<string[]>();
        SecureString securePassword = new NetworkCredential("", password).SecurePassword;

        AuthenticationResult result = null;
        httpClient = new HttpClient();

        try
        {
            result = await app.AcquireTokenByUsernamePassword(scopes, username, securePassword)
                .ExecuteAsync();
        }
        catch (MsalException) { }

        string accessToken = result.AccessToken;
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
    }

    public Task DisposeAsync() => Task.CompletedTask;
}

Verwenden in Ihren Testklassen

Das folgende Beispiel ist ein Test, der Microsoft Graph aufruft. Ersetzen Sie diesen Test durch das, was Sie in Ihrer eigenen Anwendung oder API testen möchten.

public class ApiTests : IClassFixture<ClientFixture>
{
    ClientFixture clientFixture;

    public ApiTests(ClientFixture clientFixture)
    {
        this.clientFixture = clientFixture;
    }

    [Fact]
    public async Task GetRequestTest()
    {
        var testClient = clientFixture.httpClient;
        HttpResponseMessage response = await testClient.GetAsync("https://graph.microsoft.com/v1.0/me");
        var responseCode = response.StatusCode.ToString();
        Assert.Equal("OK", responseCode);
    }
}