Schützen von serverlosen APIs mit Azure API Management und Azure AD B2C für den Verbrauch aus einem SPA
GILT FÜR: Alle API Management-Ebenen
In diesem Szenario wird gezeigt, wie Sie Ihre Azure API Management-Instanz zum Schutz einer API konfigurieren. Wir werden den Azure AD B2C SPA-Fluss (Authentifizierungscode + PKCE) verwenden, um ein Token zu erwerben, zusammen mit API Management, um ein Azure Functions-Back-End mit EasyAuth zu sichern.
Eine Konzept-Übersicht über die API-Autorisierung finden Sie unter Authentifizierung und Autorisierung an APIs im API-Management.
Ziele
Erfahren Sie, wie Sie API Management in einem vereinfachten Szenario mit Azure Functions und Azure AD B2C verwenden können. Sie erstellen eine JavaScript-App (JS), die eine API aufruft, die Benutzer mit Azure AD B2C anmeldet. Anschließend verwenden Sie die Funktionen der API Management-Richtlinie „validate-jwt“ CORS und „Ratenbegrenzung nach Schlüssel“, um die Back-End-API zu schützen.
Für eine umfassende Verteidigung verwenden wir dann EasyAuth, um das Token in der Back-End-API erneut zu validieren und sicherzustellen, dass API Management der einzige Dienst ist, der das Azure Functions-Back-End aufrufen kann.
Lernziele
- Einrichten einer Single-Page-App und Back-End-API in Azure Active Directory B2C
- Erstellen einer Azure Functions-Back-End-API
- Importieren einer Azure Functions-API in Azure API Management
- Sichern der API in Azure API Management
- Aufrufen der Azure Active Directory B2C-Autorisierung endpunkte über die Microsoft Identity Platform-Bibliotheken (MSAL.js)
- Speichern einer HTML-/Vanilla-JS-Single-Page-Anwendung und Bedienen derselben über einen Azure Blob Storage-Endpunkt
Voraussetzungen
Damit Sie den Schritten in diesem Artikel folgen können, benötigen Sie folgende Komponenten:
- Ein Azure (StorageV2) General Purpose V2-Speicherkonto zum Hosten der Front-End-JS-Single-Page-App.
- Eine Azure API Management-Instanz (Jeder Tarif funktioniert, einschließlich „Verbrauch“ (Consumption), jedoch sind bestimmte Funktionen, die für das vollständige Szenario gelten, in diesem Tarif nicht verfügbar („Ratenbegrenzung nach Schlüssel“ und dedizierte virtuelle IP). Diese Einschränkungen werden unten im Artikel an entsprechender Stelle genannt.).
- Eine leere Azure Functions-App (die die V3.1 .NET Core-Laufzeit in einem Verbrauchstarif ausführt), um die aufgerufene API zu hosten.
- Einen Azure AD B2C-Mandanten, der mit einem Abonnement verknüpft ist.
Obwohl Sie in der Praxis Ressourcen in derselben Region in Produktionsworkloads verwenden, ist die Bereitstellungsregion in diesem Artikel nicht wichtig.
Übersicht
Hier sehen Sie eine Abbildung der verwendeten Komponenten und des Flusses zwischen ihnen, wenn dieser Prozess abgeschlossen ist.
Hier sehen Sie eine kurze Übersicht der Schritte:
Erstellen des Azure AD B2C-Aufrufs (Front-End, API Management) und der API-Anwendungen mit Bereichen sowie Gewähren des API-Zugriffs
Erstellen der Registrierungs- und Anmeldungsrichtlinie, um Benutzern die Anmeldung mit Azure AD B2C zu ermöglichen
Konfigurieren von API Management mit den neuen Azure AD B2C-Client-IDs und -schlüsseln zum Aktivieren der OAuth2-Benutzerautorisierung in der Entwicklerkonsole
Erstellen der Funktions-API
Konfigurieren der Funktions-API zum Aktivieren von EasyAuth mit den neuen Azure AD B2C-Client-IDs und -schlüsseln und Sperren der APIM-VIP
Erstellen der API-Definition in API Management
Einrichten von Oauth2 für die API Management-API-Konfiguration
Einrichten der CORS-Richtlinie und Hinzufügen der validate-jwt-Richtlinie zum Validieren des OAuth-Tokens für jede eingehende Anforderung
Erstellen der aufrufenden Anwendung für die Nutzung der API
Hochladen der JS-Beispiel-SPA
Konfigurieren der JS-Client-Beispiel-App mit den neuen Azure AD B2C-Client-IDs und -schlüsseln
Testen der Clientanwendung
Tipp
Da wir im Laufe dieses Dokuments eine ganze Reihe von Informationen und Schlüsseln usw. erfassen werden, ist es vielleicht praktisch, wenn Sie einen Text-Editor geöffnet haben, um die folgenden Konfigurationselemente vorübergehend zu speichern.
B2C BACKEND CLIENT ID: B2C BACKEND CLIENT SECRET KEY: B2C BACKEND API SCOPE URI: B2C FRONTEND CLIENT ID: B2C USER FLOW ENDPOINT URI: B2C WELL-KNOWN OPENID ENDPOINT: B2C POLICY NAME: Frontendapp_signupandsignin FUNCTION URL: APIM API BASE URL: STORAGE PRIMARY ENDPOINT URL:
Konfigurieren der Back-End-Anwendung
Öffnen Sie das Blatt „Azure AD B2C“ im Portal, und führen Sie die folgenden Schritte aus.
Wählen Sie die Registerkarte App-Registrierungen aus.
Klicken Sie auf die Schaltfläche „Neue Registrierung“.
Wählen Sie im Auswahlfeld „Umleitungs-URI“ die Option „Web“ aus.
Legen Sie nun den „Anzeigenamen“ fest. Wählen Sie hierbei einen eindeutigen und relevanten Namen für den zu erstellenden Dienst aus. In diesem Beispiel verwenden wir den Namen „Back-End-Anwendung“.
Verwenden Sie Platzhalter für die Antwort-URLs, z. B.“https://jwt.ms“ (eine Tokendecodierungssite im Besitz von Microsoft). Diese URLs werden wir später aktualisieren.
Stellen Sie sicher, dass Sie die Option „Konten in einem Organisationsverzeichnis oder ein beliebiger Identitätsanbieter“ (zur Authentifizierung von Benutzern mit Benutzerflows) ausgewählt haben.
Deaktivieren Sie für dieses Beispiel das Kontrollkästchen „Administratoreinwilligung erteilen“, da wir derzeit keine offline_access-Berechtigungen benötigen.
Klicken Sie auf „Registrieren“.
Notieren Sie die Client-ID der Back-End-Anwendung für die spätere Verwendung (wird unter „Anwendungs-ID (Client) „ angezeigt).
Wählen Sie die Registerkarte Zertifikate und Geheimnisse (unter „Verwalten“) aus, und klicken Sie dann auf „Neuer geheimer Clientschlüssel“, um einen Authentifizierungsschlüssel zu generieren (Übernehmen Sie die Standardeinstellungen, und klicken Sie auf „Hinzufügen“).
Nachdem Sie auf „Hinzufügen“ geklickt haben, kopieren Sie den Schlüssel (unter „Wert“) an einen sicheren Ort, um ihn später als „Geheimer Clientschlüssel für Back-End“ zu verwenden – beachten Sie, dass dieses Dialogfeld die EINZIGE Möglichkeit ist, um diesen Schlüssel zu kopieren.
Wählen Sie nun die Registerkarte Eine API verfügbar machen (unter „Verwalten“) aus.
Sie werden aufgefordert, den AppID-URI festzulegen. Wählen Sie Standardwert aus, und notieren Sie ihn.
Erstellen und benennen Sie den Bereich „Hello“ für Ihre Funktions-API. Sie können die Phrase „Hello“ für alle eingebbaren Optionen verwenden, wobei Sie den ausgefüllten URI von „Vollständiger Bereichswert“ notieren und dann auf „Bereich hinzufügen“ klicken.
Kehren Sie zum Stamm des Azure AD B2C-Blatts zurück, indem Sie das Breadcrumb „Azure AD B2C“ oben links im Portal auswählen.
Hinweis
Azure AD B2C-Bereiche sind letztlich Berechtigungen innerhalb Ihrer API, auf die andere Anwendungen Zugriff über das Blatt „API-Zugriff“ der Anwendungen anfordern können. Sie haben damit praktisch Anwendungsberechtigungen für Ihre aufgerufene API erstellt.
Konfigurieren der Front-End-Anwendung
- Wählen Sie die Registerkarte App-Registrierungen aus.
- Klicken Sie auf die Schaltfläche „Neue Registrierung“.
- Wählen Sie im Auswahlfeld „Umleitungs-URI“ die Option „Single-Page-Application (SPA)“ aus.
- Legen Sie nun den Anzeigenamen und den AppID-URI fest. Wählen Sie hierbei einen eindeutigen und für die Front-End-Anwendung relevanten Namen aus, die diese Azure Active Directory B2C-App-Registrierung verwenden wird. In diesem Beispiel können Sie „Front-End-Anwendung“ (Frontend Application) verwenden.
- Lassen Sie, wie bei der ersten App-Registrierung, die Auswahl der unterstützten Kontotypen auf der Standardeinstellung (Authentifizierung von Benutzern mit Benutzerflows).
- Verwenden Sie Platzhalter für die Antwort-URLs, z. B.“https://jwt.ms“ (eine Tokendecodierungssite im Besitz von Microsoft). Diese URLs werden wir später aktualisieren.
- Lassen Sie das Kontrollkästchen „Administratoreinwilligung erteilen“ aktiviert.
- Klicken Sie auf „Registrieren“.
- Notieren Sie die Client-ID der Front-End-Anwendung für die spätere Verwendung (wird unter „Anwendungs-ID (Client)“ angezeigt).
- Wechseln Sie zur Registerkarte API-Berechtigungen.
- Gewähren Sie Zugriff auf die Back-End-Anwendung, indem Sie auf „Berechtigung hinzufügen“ und dann auf „Meine APIs“ klicken. Wählen Sie die „Back-End-Anwendung“, dann „Berechtigungen“ und schließlich den Bereich aus, den Sie im vorherigen Abschnitt erstellt haben, und klicken Sie auf „Berechtigungen erstellen“.
- Klicken Sie auf „Administratoreinwilligung für {Mandanten} erteilen“, und klicken Sie im Popupdialogfeld auf „Ja“. Dieses Popup erteilt der „Front-End-Anwendung“ die Erlaubnis, in der zuvor erstellten „Back-End-Anwendung“ definierte Berechtigung „Hello“ zu verwenden.
- Unter der Spalte „Status“ sollten jetzt alle Berechtigungen für die App mit grünen Häkchen angezeigt werden.
Erstellen eines Benutzer-Flows „Registrierung und Anmeldung“
Kehren Sie zum Stamm des B2C-Blatts zurück, indem Sie das Breadcrumb „Azure AD B2C“ auswählen.
Wechseln Sie zur Registerkarte „Benutzerflows“ (unter „Richtlinien“).
Klicken Sie auf „Neuer Benutzerflow“.
Wählen Sie den Benutzer-Flow-Typ ‚Registrierung und Anmeldung‘ und wählen Sie ‚Empfohlen‘ und dann ‚Erstellen‘ aus
Benennen Sie die Richtlinie, und notieren Sie den Namen für die spätere Verwendung. Für dieses Beispiel können Sie „Frontendapp_signupandsignin“ verwenden. Beachten Sie, dass diesem das Präfix „B2C_1_“ vorangestellt wird, sodass „B2C_1_Frontendapp_signupandsignin“ entsteht.
Aktivieren Sie unter „Identitätsanbieter“ und „Lokale Konten“ die Option „E-Mail-Registrierung“ (oder „Benutzer-ID-Registrierung“, je nach der Konfiguration Ihres B2C-Mandanten), und klicken Sie auf „OK“. Der Grund für diese Konfiguration ist, dass wir lokale B2C-Konten registrieren und nicht an einen anderen Identitätsanbieter (so wie einen Anbieter für soziale Netzwerkidentitäten) verweisen, der das vorhandene Social Media-Konto eines Benutzers verwendet.
Belassen Sie die Einstellungen für MFA und bedingten Zugriff auf den Standardwerten.
Klicken Sie unter „Benutzerattribute und -ansprüche“ auf „Mehr anzeigen“, und wählen Sie die Anspruchsoptionen aus, die von den Benutzern eingegeben und im Token zurückgegeben werden sollen. Aktivieren Sie mindestens „Anzeigename“ und „E-Mail-Adresse“, die erfasst werden sollen, sowie „Anzeigename“ und „E-Mail-Adressen“, die zurückgegeben werden sollen (achten Sie sorgfältig darauf, dass Sie eine E-Mail-Adresse, Singular, erfassen, und darum bitten, E-Mail-Adressen, mehrere, zurückzugeben), und klicken Sie auf „OK“, dann auf „Erstellen“.
Klicken Sie auf den Benutzerflow, den Sie in der Liste erstellt haben, und dann auf die Schaltfläche „Benutzerflow ausführen“.
Mit dieser Aktion wird das Blatt „Benutzerflow ausführen“ geöffnet. Wählen Sie die Front-End-Anwendung aus, kopieren Sie den Benutzerflowendpunkt, und speichern Sie ihn für später.
Kopieren und speichern Sie den Link ganz oben, den Sie als „bekannten OpenID-Konfigurationsendpunkt“ für die spätere Verwendung notieren.
Hinweis
B2C-Richtlinien ermöglichen Ihnen, die Azure AD B2C-Anmeldeendpunkte verfügbar zu machen, um unterschiedliche Datenkomponenten zu erfassen und Benutzer auf unterschiedliche Weise anzumelden.
In diesem Fall haben wir einen Registrierungs- oder Anmeldungs-Flow (Richtlinie) konfiguriert. Auch hier wurde ein bekannter Konfigurationsendpunkt verfügbar gemacht. In beiden Fällen wurde unsere erstellte Richtlinie in der URL durch den Abfragezeichenfolgenparameter „p=“ identifiziert.
Sobald dies erledigt ist, haben Sie nun eine funktionale Business-to-Consumer-Identitätsplattform (B2C), die Benutzer bei mehreren Anwendungen anmeldet.
Erstellen der Funktions-API
Wechseln Sie zurück zu Ihrem Azure AD-Standardmandanten im Azure-Portal, damit wir wieder Elemente in Ihrem Abonnement konfigurieren können.
Wechseln Sie zum Blatt „Funktions-Apps“ im Azure-Portal, öffnen Sie Ihre leere Funktions-App, und klicken Sie dann auf „Funktionen“ und auf „Hinzufügen“.
Im angezeigten Flyout wählen Sie „Im Portal entwickeln“ unter „Vorlage auswählen“ aus. Wählen Sie dann „HTTP-Trigger“ unter „Vorlagendetails“ aus, benennen Sie sie mit „Hello“ mit der Autorisierungsstufe „Funktion“, und wählen Sie dann „Hinzufügen“ aus.
Wechseln Sie zum Blatt „Programmieren + Testen“, kopieren Sie unten den Beispielcode, und fügen Sie ihn über dem vorhandenen Code ein, der angezeigt wird.
Wählen Sie „Speichern“ aus.
using System.Net; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; public static async Task<IActionResult> Run(HttpRequest req, ILogger log) { log.LogInformation("C# HTTP trigger function processed a request."); return (ActionResult)new OkObjectResult($"Hello World, time and date are {DateTime.Now.ToString()}"); }
Tipp
Der Code der C#-Skriptfunktion, den Sie soeben eingefügt haben, protokolliert lediglich eine Zeile in den Funktionsprotokollen und gibt den Text „Hello World“ mit einigen dynamischen Daten (Datum und Uhrzeit) zurück.
Wählen Sie „Integration“ im linken Blatt aus, und klicken Sie dann auf den Link HTTP-Link (req) im Feld „Trigger“.
Deaktivieren Sie in der Dropdownliste „Ausgewählte HTTP-Methoden“ die HTTP-Methode POST, sodass nur noch GET ausgewählt ist, und klicken Sie dann auf „Speichern“.
Wechseln Sie zurück zur Registerkarte „Programmieren + Testen“, klicken Sie auf „Funktions-URL abrufen“, kopieren Sie dann die angezeigte URL, und speichern Sie sie für später.
Hinweis
Die Bindungen, die Sie gerade erstellt haben, teilen Functions einfach mit, dass es auf anonyme GET-HTTP-Anforderungen an die URL reagieren sollen, die Sie gerade kopiert haben (
https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey
). Jetzt haben wir eine skalierbare, serverlose HTTPS-API, die in der Lage ist, eine sehr einfache Nutzlast zurückzugeben.Sie können nun testen, ob Sie diese API aus einem Webbrowser aufrufen können, indem Sie Ihre Version der obigen URL verwenden, die Sie gerade kopiert und gespeichert haben. Sie können auch den Abfragezeichenfolgenparameter-Teil „?code=secretkey“ der URL entfernen und erneut testen, um zu beweisen, dass Azure Functions einen 401-Fehler zurückgibt.
Konfigurieren und Schützen der Funktions-API
In der Funktions-App müssen zwei zusätzliche Bereiche konfiguriert werden (Autorisierung und Netzwerkeinschränkungen).
Lassen Sie uns zunächst die Authentifizierung/Autorisierung konfigurieren. Also navigieren Sie über das Breadcrumb zurück zum Stammblatt der Funktions-App.
Wählen Sie dann „Authentifizierung“ aus (unter „Einstellungen“).
Klicken Sie auf „Identitätsanbieter hinzufügen“.
Wählen Sie in der Dropdownliste der Identitätsanbieter „Microsoft“ aus.
Wählen Sie für die App-Registrierung die Option „Details einer vorhandenen App-Registrierung angeben“ aus.
Fügen Sie im Feld „Anwendungs-ID (Client)“ die Client-ID der Back-End-Anwendung (aus Azure AD B2C) ein (diese Konfiguration wurde zuvor aufgezeichnet).
Fügen Sie den bekannten Open-ID-Konfigurationsendpunkt aus der Registrierungs- und Anmeldungsrichtlinie in das Feld URL-Zertifikataussteller ein (wir haben diese Konfiguration zuvor aufgezeichnet).
Fügen Sie den Clientschlüssel der Back-End-Anwendung in das entsprechende Feld ein (diese Konfiguration wurde zuvor aufgezeichnet).
Wählen Sie für „Nicht authentifizierte Anforderungen“ die Option „HTTP 401 Nicht autorisiert: empfohlen für APIs“ aus.
Lassen Sie die Option Tokenspeicher aktiviert (Standardeinstellung).
Klicken Sie auf „Speichern“ (oben links auf dem Blatt).
Wichtig
Ihre Funktions-API ist nun bereitgestellt. Bei Anforderungen ohne Angabe des korrekten JWT als „Authorization: Bearer“-Headers sollte sie Antworten vom Typ 401 zurückgeben. Bei gültigen Anforderungen sollten Daten zurückgegeben werden. Sie haben die Sicherheit in EasyAuth durch zusätzliche Defense-in-Depth-Maßnahmen verbessert, indem Sie für nicht authentifizierte Anforderungen die Option „Mit Azure AD anmelden“ konfiguriert haben.
Sie verfügen damit allerdings immer noch nicht über IP-Sicherheit. Mit einem gültigen Schlüssel und OAuth2-Token sind Aufrufe von überall aus möglich. Im Idealfall sollten jedoch alle Anforderungen über API Management erzwungen werden.
Wenn Sie den API Management Consumption-, Basic v2- und Standard v2-Tarif verwenden, gibt es keine dedizierte virtuelle Azure API Management-IP, die in die Zulassungsliste aufgenommen werden könnte, mit den Funktionszugriffseinschränkungen. In den klassischen (dedizierten) Azure API Management-Ebenen ist die VIP ein einzelner Mandant und für die Lebensdauer der Ressource. Für die Tarife, die auf gemeinsamer Infrastruktur ausgeführt werden, können Sie Ihre API-Aufrufe über den Funktionsschlüssel des gemeinsamen Geheimnisses in dem Teil des URI, den Sie oben kopiert haben, sperren. Außerdem gelten für diese Tarife die nachstehenden Schritte 12-17 nicht.
Schließen Sie das Blatt „Authentifizierung“ im App Service/Functions-Portal.
Öffnen Sie das Blatt „API Management“ im Portal, und öffnen Sie dann Ihre Instanz.
Notieren Sie die „Private VIP“, die auf der Registerkarte „Übersicht“ angezeigt wird.
Kehren Sie zum Blatt „Azure Functions“ im Portal zurück, und öffnen Sie erneut Ihre Instanz.
Wählen Sie „Netzwerk“ und dann „Zugriffseinschränkungen konfigurieren“ aus.
Klicken Sie auf „Regel hinzufügen“, und geben Sie die oben in Schritt 3 kopierte VIP im Format „xx.xx.xx.xx/32“ ein.
Wenn Sie weiterhin mit dem Functions-Portal interagieren und die unten aufgeführten optionalen Schritte ausführen möchten, sollten Sie auch hier eine eigene öffentliche IP-Adresse oder einen CIDR-Bereich hinzufügen.
Nachdem ein Zulassungseintrag in der Liste vorhanden ist, fügt Azure eine implizite Ablehnungsregel hinzu, um alle anderen Adressen zu blockieren.
Sie müssen dem Bereich mit IP-Einschränkungen CIDR-formatierte Adressblöcke hinzufügen. Wenn Sie eine einzelne Adresse (z. B. die VIP von API Management) hinzufügen möchten, müssen Sie sie im Format xx.xx.xx.xx/32 hinzufügen.
Hinweis
Ihre Funktions-API sollte nun nur noch von API Management oder über Ihre Adresse aufgerufen werden können.
Öffnen Sie das Blatt API Management und anschließend Ihre Instanz.
Wählen Sie das Blatt „APIs“ (unter „APIs“) aus.
Wählen Sie im Bereich „Neue API hinzufügen“ die Option „Funktions-App“ und dann oben im Popupfenster „Vollständig“ aus.
Klicken Sie auf „Durchsuchen“, wählen Sie die Funktions-App aus, in der Sie die API hosten, und klicken Sie auf „Auswählen“. Klicken Sie anschließend erneut auf „Auswählen“.
Weisen Sie der API einen Namen und eine Beschreibung für die interne Verwendung durch API Management zu, und fügen Sie sie dem Produkt „Unbegrenzt“ hinzu.
Kopieren und notieren Sie die „Basis-URL“ der API, und klicken Sie auf „Erstellen“.
Klicken Sie auf die Registerkarte „Einstellungen“, und deaktivieren Sie dann unter „Abonnement“ das Kontrollkästchen „Abonnement erforderlich“, da wir in diesem Fall das Oauth-JWT-Token als Ratenbegrenzung verwenden. Beachten Sie, dass dies auch in einer Produktionsumgebung erforderlich ist, wenn Sie den Verbrauchstarif verwenden.
Tipp
Wenn Sie den Verbrauchstarif von APIM verwenden, ist das unbegrenzte Produkt nicht als vorgefertigte Version verfügbar. Navigieren Sie stattdessen zu „Produkte“ unter „APIs“, und klicken Sie auf „Hinzufügen“. Geben Sie „Unlimited“ (Unbegrenzt) als Produktnamen und Beschreibung ein, und wählen Sie unten links im Bildschirm die API aus, die Sie soeben über das APIs-Feld „+“ hinzugefügt haben. Aktivieren Sie das Kontrollkästchen „Veröffentlicht“. Belassen Sie bei dem Rest die Standardeinstellungen. Klicken Sie schließlich auf die Schaltfläche „Erstellen“. Dadurch wurde das „Unlimited“-Produkt erstellt und Ihrer API zugewiesen. Sie können Ihr neues Produkt später anpassen.
Konfigurieren und Erfassen der richtigen Speicherendpunkteinstellungen
Öffnen Sie das Blatt „Speicherkonten“ im Azure-Portal.
Wählen Sie das Konto aus, das Sie erstellt haben, und wählen Sie im Abschnitt „Einstellungen“ das Blatt „Statische Website“ aus. (Wenn die Option „Statische Website“ nicht angezeigt wird, überprüfen Sie, ob Sie ein V2-Konto erstellt haben.)
Legen Sie die Funktion für das statische Webhosting auf „aktiviert“ und den Namen des Indexdokuments auf „index.html“ fest, und klicken Sie dann auf „Speichern“.
Notieren Sie den Inhalt von „Primärer Endpunkt“ für später, da an diesem Speicherort die Front-End-Site gehostet wird.
Tipp
Sie können entweder Azure Blob Storage und die CDN-Neuschreibung oder Azure App Service verwenden, um die SPA zu hosten. Das Feature zum Hosten der statischen Website von Blob Storage stellt jedoch einen Standardcontainer für statische Webinhalte/HTML/JS/CSS aus Azure Storage bereit und leitet ohne weiteres Zutun eine Standardseite ab.
Einrichten der Richtlinien CORS und validate-jwt
Die folgenden Abschnitte sollten unabhängig von der APIM-Dienstebene befolgt werden. Die Speicherkonto-URL stammt aus dem Speicherkonto, das Sie unter den „Voraussetzungen“ oben in diesem Artikel zur Verfügung gestellt haben.
Wechseln Sie zum Blatt „API Management“ des Portals, und öffnen Sie Ihre Instanz.
Wählen Sie „APIs“ und dann „Alle APIs“ aus.
Klicken Sie unter "Eingehende Verarbeitung" auf die Codeansichtsschaltfläche "</>", um den Richtlinieneditor anzuzeigen.
Bearbeiten Sie den eingehenden Abschnitt, und fügen Sie den folgenden XML-Code ein, sodass er wie folgt aussieht.
Ersetzen Sie die folgenden Parameter in der Richtlinie
{PrimaryStorageEndpoint} (Der „Primäre Speicherendpunkt“, den Sie im vorherigen Abschnitt kopiert haben.), {b2cpolicy-well-known-openid} (Der „bekannte OpenID-Konfigurationsendpunkt“, den Sie zuvor kopiert haben.) und {backend-api-application-client-id} (Die B2C-Anwendungs-/Client-ID für die Back-End-API) durch die richtigen, zuvor gespeicherten Werte.
Wenn Sie den Verbrauchstarif von API Management verwenden, sollten Sie die „Ratenbegrenzung nach Schlüssel“-Richtlinie entfernen, da diese Richtlinie bei Verwendung des Verbrauchstarifs von Azure API Management nicht verfügbar ist.
<inbound> <cors allow-credentials="true"> <allowed-origins> <origin>{PrimaryStorageEndpoint}</origin> </allowed-origins> <allowed-methods preflight-result-max-age="120"> <method>GET</method> </allowed-methods> <allowed-headers> <header>*</header> </allowed-headers> <expose-headers> <header>*</header> </expose-headers> </cors> <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid." require-expiration-time="true" require-signed-tokens="true" clock-skew="300"> <openid-config url="{b2cpolicy-well-known-openid}" /> <required-claims> <claim name="aud"> <value>{backend-api-application-client-id}</value> </claim> </required-claims> </validate-jwt> <rate-limit-by-key calls="300" renewal-period="120" counter-key="@(context.Request.IpAddress)" /> <rate-limit-by-key calls="15" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization","").AsJwt()?.Subject)" /> </inbound>
Hinweis
API Management ist nun in der Lage, auf ursprungsübergreifende Anforderungen von Ihren JavaScript-SPA-Apps zu reagieren. Der Dienst führt Drosselung, Ratenbegrenzung und Vorabvalidierung des JWT-Authentifizierungstokens VOR dem Weiterleiten der Anforderung an die Funktions-API durch.
Herzlichen Glückwunsch! Azure AD B2C, API Management und Azure Functions arbeiten nun zusammen, um eine API zu veröffentlichen, zu sichern UND zu verwenden.
Tipp
Wenn Sie den Verbrauchstarif von API Management verwenden, können Sie statt der Ratenbegrenzung nach dem JWT-Betreff oder der eingehenden IP-Adresse (die Richtlinie „Ratenbegrenzung nach Schlüssel“ wird derzeit für den „Verbrauchstarif“ nicht unterstützt) eine Begrenzung nach der Aufrufquote nach Kontingent festlegen, siehe hier. Da es sich bei diesem Beispiel um eine Single-Page-Webanwendung in JavaScript handelt, wird der API Management-Schlüssel nur für die Ratenbegrenzung und Abrechnungsaufrufe verwendet. Die tatsächliche Autorisierung und Authentifizierung wird von Azure AD B2C verarbeitet und im JWT gekapselt. Dieses JSON Web Token wird zweimal überprüft: einmal durch API Management und dann durch Azure Functions im Back-End.
Hochladen des JavaScript SPA-Beispiels in den statischen Speicher
Während Sie noch auf dem Blatt „Speicherkonto“ sind, wählen Sie das Blatt „Container“ aus dem Abschnitt „Blob-Dienst“ aus, und klicken Sie auf den Container „$web“, der im rechten Fensterbereich angezeigt wird.
Speichern Sie den unten stehenden Code in einer Datei lokal auf Ihrem Computer als „index.html“, und laden Sie dann die Datei „index.html“ in den Container „$web“ hoch.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous"> <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.11.1/js/msal-browser.min.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container-fluid"> <a class="navbar-brand" href="#">Azure Active Directory B2C with Azure API Management</a> <div class="navbar-nav"> <button class="btn btn-success" id="signinbtn" onClick="login()">Sign In</a> </div> </div> </nav> </div> </div> <div class="row"> <div class="col-md-12"> <div class="card" > <div id="cardheader" class="card-header"> <div class="card-text"id="message">Please sign in to continue</div> </div> <div class="card-body"> <button class="btn btn-warning" id="callapibtn" onClick="getAPIData()">Call API</a> <div id="progress" class="spinner-border" role="status"> <span class="visually-hidden">Loading...</span> </div> </div> </div> </div> </div> </div> <script lang="javascript"> // Just change the values in this config object ONLY. var config = { msal: { auth: { clientId: "{CLIENTID}", // This is the client ID of your FRONTEND application that you registered with the SPA type in Azure Active Directory B2C authority: "{YOURAUTHORITYB2C}", // Formatted as https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantguid or full tenant name including onmicrosoft.com}/{signuporinpolicyname} redirectUri: "{StoragePrimaryEndpoint}", // The storage hosting address of the SPA, a web-enabled v2 storage account - recorded earlier as the Primary Endpoint. knownAuthorities: ["{B2CTENANTDOMAIN}"] // {b2ctenantname}.b2clogin.com }, cache: { cacheLocation: "sessionStorage", storeAuthStateInCookie: false } }, api: { scopes: ["{BACKENDAPISCOPE}"], // The scope that we request for the API from B2C, this should be the backend API scope, with the full URI. backend: "{APIBASEURL}/hello" // The location that we'll call for the backend api, this should be hosted in API Management, suffixed with the name of the API operation (in the sample this is '/hello'). } } document.getElementById("callapibtn").hidden = true; document.getElementById("progress").hidden = true; const myMSALObj = new msal.PublicClientApplication(config.msal); myMSALObj.handleRedirectPromise().then((tokenResponse) => { if(tokenResponse !== null){ console.log(tokenResponse.account); document.getElementById("message").innerHTML = "Welcome, " + tokenResponse.account.name; document.getElementById("signinbtn").hidden = true; document.getElementById("callapibtn").hidden = false; }}).catch((error) => {console.log("Error Signing in:" + error); }); function login() { try { myMSALObj.loginRedirect({scopes: config.api.scopes}); } catch (err) {console.log(err);} } function getAPIData() { document.getElementById("progress").hidden = false; document.getElementById("message").innerHTML = "Calling backend ... " document.getElementById("cardheader").classList.remove('bg-success','bg-warning','bg-danger'); myMSALObj.acquireTokenSilent({scopes: config.api.scopes, account: getAccount()}).then(tokenResponse => { const headers = new Headers(); headers.append("Authorization", `Bearer ${tokenResponse.accessToken}`); fetch(config.api.backend, {method: "GET", headers: headers}) .then(async (response) => { if (!response.ok) { document.getElementById("message").innerHTML = "Error: " + response.status + " " + JSON.parse(await response.text()).message; document.getElementById("cardheader").classList.add('bg-warning'); } else { document.getElementById("cardheader").classList.add('bg-success'); document.getElementById("message").innerHTML = await response.text(); } }).catch(async (error) => { document.getElementById("cardheader").classList.add('bg-danger'); document.getElementById("message").innerHTML = "Error: " + error; }); }).catch(error => {console.log("Error Acquiring Token Silently: " + error); return myMSALObj.acquireTokenRedirect({scopes: config.api.scopes, forceRefresh: false}) }); document.getElementById("progress").hidden = true; } function getAccount() { var accounts = myMSALObj.getAllAccounts(); if (!accounts || accounts.length === 0) { return null; } else { return accounts[0]; } } </script> </body> </html>
Navigieren Sie zum primären Endpunkt der statischen Website, den Sie im letzten Abschnitt gespeichert haben.
Hinweis
Herzlichen Glückwunsch! Sie haben gerade eine JavaScript-Single-Page-App im Hosting statischer Inhalte von Azure Storage bereitgestellt. Da wir die JS-App noch nicht mit Ihren Azure AD B2C-Details konfiguriert haben, wird die Seite noch nicht funktionieren, wenn Sie sie öffnen.
Konfigurieren der JavaScript-SPA für Azure AD B2C
- Da Sie nun wissen, wo sich alles befindet, können Sie die SPA mit der entsprechenden Adresse der API Management-API und den richtigen Anwendungs-/Client-IDs aus Azure AD B2C konfigurieren.
- Wechseln Sie zurück zum Azure-Portal-Blatt „Speicher“.
- Wählen Sie „Container“ (unter „Einstellungen“) aus.
- Wählen Sie den Container „$web“ aus der Liste aus.
- Wählen Sie in der Liste den Blob „index.html“ aus.
- Klicken Sie auf „Bearbeiten“.
- Aktualisieren Sie die Authentifizierungswerte im Abschnitt „msal config“ so, dass sie mit Ihrer Front-End-Anwendung übereinstimmen, die Sie zuvor in B2C registriert haben. Verwenden Sie die Codekommentare, um Hinweise darauf zu erhalten, wie die Konfigurationswerte aussehen sollen. Der Wert für authority (Autorität) muss das Format „https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantname}.onmicrosoft.com}/{signupandsigninpolicyname}“ haben. Wenn Sie unsere Beispielnamen verwendet haben und Ihr b2c-Mandant „contoso“ heißt, würden Sie erwarten, dass „authority“ den Wert https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com/Frontendapp_signupandsignin hat.
- Legen Sie die API-Werte so fest, dass sie mit Ihrer Back-End-Adresse übereinstimmen (Die API-Basis-URL, die Sie zuvor notiert haben, und die „b2cScopes“-Werte wurden zuvor für die Back-End-Anwendung notiert.).
- Klicken Sie auf Speichern.
Festlegen der Umleitungs-URIs für die Azure AD B2C-Front-End-App
Öffnen Sie das Blatt „Azure AD B2C“, und navigieren Sie zur Anwendungsregistrierung für die JavaScript-Front-End-Anwendung.
Klicken Sie auf „Umleitungs-URIs“, und löschen Sie den zuvor eingegebenen Platzhalter „https://jwt.ms“.
Fügen Sie einen neuen URI für den primären (Speicher-)Endpunkt hinzu (ohne den Schrägstrich am Ende).
Hinweis
Diese Konfiguration führt dazu, dass ein Client der Front-End-Anwendung ein Zugriffstoken mit entsprechenden Ansprüchen von Azure AD B2C erhält. Die SPA kann dieses als Bearertoken im HTTPS-Header im Aufruf der Back-End-API hinzufügen.
API Management validiert das Token vorab, begrenzt die Aufrufraten an den Endpunkt sowohl nach dem Betreff des von Azure ID (dem Benutzer) ausgestellten JWT, als auch nach der IP-Adresse des Aufrufers (je nach Dienstebene/Tarif von API Management, siehe der Hinweis oben), bevor die Anforderung an die empfangende Azure Functions-API durchgeleitet wird, wobei der Functions-Sicherheitsschlüssel hinzugefügt wird. Die SPA rendert die Antwort im Browser.
Herzlichen Glückwunsch! Sie haben Azure AD B2C, Azure API Management, Azure Functions und die Azure App Service-Autorisierung so konfiguriert, dass diese Funktionen perfekt zusammenarbeiten.
Sie verfügen nun über eine einfache App mit einer einfachen geschützten API. Testen Sie sie nun.
Testen der Clientanwendung
- Öffnen Sie die Beispiel-App-URL, die Sie sich aus dem zuvor erstellten Speicherkonto notiert haben.
- Klicken Sie in der rechten oberen Ecke auf „Anmelden“. Dadurch wird das Azure Active Directory B2C-Registrierungs- oder -Anmeldeprofil angezeigt.
- Die App sollte Sie mit Ihrem B2C-Profilnamen begrüßen.
- Klicken Sie nun auf „API aufrufen“, und die Seite sollte mit den von Ihrer gesicherten API zurückgesendeten Werten aktualisiert werden.
- Wenn Sie wiederholt auf die Schaltfläche „API aufrufen“ klicken und Sie im Entwicklertarif (Developer) oder höher von API Management arbeiten, sollten Sie beachten, dass Ihre Lösung beginnt, die Aufrufrate der API zu begrenzen, wobei diese Funktion in der App mit einer entsprechenden Meldung gemeldet werden sollte.
Fertig.
Die obigen Schritte können angepasst und bearbeitet werden, um viele verschiedene Anwendungsfälle von Azure AD B2C mit API Management zu ermöglichen.
Nächste Schritte
- Erfahren Sie mehr über Microsoft Entra ID und OAuth2.0.
- Hier finden Sie weitere Videos zu API Management.
- Weitere Methoden zum Sichern Ihres Back-End-Diensts finden Sie unter Sichern von Back-End-Diensten über eine Clientzertifikatauthentifizierung in Azure API Management.
- Erstellen einer API Management-Dienstinstanz
- Verwalten Ihrer ersten API