Skydda SPA-backend med OAuth 2,0, Azure Active Directory B2C och Azure API ManagementProtect SPA backend with OAuth 2.0, Azure Active Directory B2C and Azure API Management

Det här scenariot visar hur du konfigurerar Azure API Management-instansen för att skydda ett API.This scenario shows you how to configure your Azure API Management instance to protect an API. Vi använder Azure AD B2C SPA (auth Code + PKCE)-flödet för att hämta en token, tillsammans med API Management för att skydda en Azure Functions Server del med EasyAuth.We'll use the Azure AD B2C SPA (Auth Code + PKCE) flow to acquire a token, alongside API Management to secure an Azure Functions backend using EasyAuth.

SyftarAims

Vi ska se hur API Management kan användas i ett förenklat scenario med Azure Functions och Azure AD B2C.We're going to see how API Management can be used in a simplified scenario with Azure Functions and Azure AD B2C. Du ska skapa en JavaScript-app (JS) som anropar en API, som loggar in användare med Azure AD B2C.You'll create a JavaScript (JS) app calling an API, that signs in users with Azure AD B2C. Sedan använder du API Management validera-JWT-, CORS-och Rate-begränsningar med hjälp av nyckel princip funktioner för att skydda Server dels-API: et.Then you'll use API Management's validate-jwt, CORS, and Rate Limit By Key policy features to protect the Backend API.

För att få skydd i djupet använder vi EasyAuth för att validera token igen inuti Server dels-API: et och se till att API Management är den enda tjänst som kan anropa den Azure Functions Server delen.For defense in depth, we then use EasyAuth to validate the token again inside the back-end API and ensure that API management is the only service that can call the Azure Functions backend.

Vad kommer du att lära digWhat will you learn

  • Installation av en enda sida-app och Server dels-API i Azure Active Directory B2CSetup of a Single Page App and backend API in Azure Active Directory B2C
  • Skapa en Azure Functions Server dels-APICreation of an Azure Functions Backend API
  • Importera ett Azure Functions-API till Azure API ManagementImport of an Azure Functions API into Azure API Management
  • Skydda API: et i Azure API ManagementSecuring the API in Azure API Management
  • Anropar slut punkterna för Azure Active Directory B2C-auktorisering via biblioteken för Microsoft Identity Platform (MSAL.js)Calling the Azure Active Directory B2C Authorization Endpoints via the Microsoft Identity Platform Libraries (MSAL.js)
  • Lagra ett program med en HTML/vanilj JS-sida och betjäna det från en Azure Blob Storage-slutpunktStoring a HTML / Vanilla JS Single Page Application and serving it from an Azure Blob Storage Endpoint

FörutsättningarPrerequisites

För att följa stegen i den här artikeln måste du ha:To follow the steps in this article, you must have:

  • Ett Azure-Generell användning (StorageV2) v2-lagrings konto som värd för frontend JS-appen med en sida.An Azure (StorageV2) General Purpose V2 Storage Account to host the frontend JS Single Page App.
  • En Azure API Management-instans (vilken nivå som helst fungerar, inklusive "förbrukning", men vissa funktioner som är tillämpliga för det fullständiga scenariot är inte tillgängliga i den här nivån (hastighets begränsning och dedikerad virtuell IP), dessa begränsningar benämns nedan i artikeln där det är lämpligt).An Azure API Management instance (Any tier will work, including 'Consumption', however certain features applicable to the full scenario are not available in this tier (rate-limit-by-key and dedicated Virtual IP), these restrictions are called out below in the article where appropriate).
  • En tom Azure Function-app (som kör V 3.1 .NET Core runtime, i en förbruknings plan) som värd för den anropade API: nAn empty Azure Function app (running the V3.1 .NET Core runtime, on a Consumption Plan) to host the called API
  • En Azure AD B2C klient, som är länkad till en prenumeration.An Azure AD B2C tenant, linked to a subscription.

Även om du i praktiken använder resurser i samma region i produktions arbets belastningar, för den här instruktions artikeln är distributions området inte viktigt.Although in practice you would use resources in the same region in production workloads, for this how-to article the region of deployment isn't important.

ÖversiktOverview

Här är en illustration av de komponenter som används och flödet mellan dem när den här processen har slutförts.Here's an illustration of the components in use and the flow between them once this process is complete. Komponenter som används och FlowComponents in use and flow

Här är en snabb översikt över stegen:Here's a quick overview of the steps:

  1. Skapa Azure AD B2C anropa (frontend, API Management) och API-program med omfattningar och bevilja API-åtkomstCreate the Azure AD B2C Calling (Frontend, API Management) and API Applications with scopes and grant API Access

  2. Skapa registrerings-och inloggnings principer så att användarna kan logga in med Azure AD B2CCreate the sign up and sign in policies to allow users to sign in with Azure AD B2C

  3. Konfigurera API Management med de nya Azure AD B2C-klient-ID: na och nycklarna för att aktivera OAuth2-användarauktorisering i Developer-konsolenConfigure API Management with the new Azure AD B2C Client IDs and keys to Enable OAuth2 user authorization in the Developer Console

  4. Bygg funktions-API: etBuild the Function API

  5. Konfigurera funktions-API: et för att aktivera EasyAuth med de nya Azure AD B2C klient-ID: n och nycklarna och lås till APIM VIPConfigure the Function API to enable EasyAuth with the new Azure AD B2C Client ID’s and Keys and lock down to APIM VIP

  6. Bygg API-definitionen i API ManagementBuild the API Definition in API Management

  7. Konfigurera OAuth2 för API-konfigurationen för API ManagementSet up Oauth2 for the API Management API configuration

  8. Konfigurera CORS -principen och Lägg till validate-JWT- principen för att verifiera OAuth-token för varje inkommande begäranSet up the CORS policy and add the validate-jwt policy to validate the OAuth token for every incoming request

  9. Bygg det anropande programmet för att använda API: etBuild the calling application to consume the API

  10. Överför SPA-exemplet för JSUpload the JS SPA Sample

  11. Konfigurera exempel-Client-appen med de nya Azure AD B2C-klient-ID: n och nycklarnaConfigure the Sample JS Client App with the new Azure AD B2C Client ID’s and keys

  12. Testa klient programmetTest the Client Application

    Tips

    Vi kommer att samla in några få informations-och nyckel uppgifter när vi vägleder det här dokumentet. det kan vara praktiskt att ha en text redigerare öppen för att lagra följande konfigurations objekt tillfälligt.We're going to capture quite a few pieces of information and keys etc as we walk this document, you might find it handy to have a text editor open to store the following items of configuration temporarily.

    KLIENT-ID FÖR B2C-SERVER:B2C BACKEND CLIENT ID:
    HEMLIG NYCKEL FÖR B2C-BACKEND-KLIENT:B2C BACKEND CLIENT SECRET KEY:
    URI FÖR B2C BACKEND API-OMFATTNING:B2C BACKEND API SCOPE URI:
    KLIENT-ID FÖR B2C-KLIENT:B2C FRONTEND CLIENT ID:
    SLUT PUNKTS-URI FÖR ANVÄNDAR FLÖDE FÖR B2C:B2C USER FLOW ENDPOINT URI:
    B2C-VÄLKÄND OPENID-SLUTPUNKT:B2C WELL-KNOWN OPENID ENDPOINT:
    B2C-princip namn: URL för Frontendapp_signupandsignin funktion:B2C POLICY NAME: Frontendapp_signupandsignin FUNCTION URL:
    APIM API-BAS-URL: URL FÖR PRIMÄR SLUT PUNKT FÖR LAGRING:APIM API BASE URL: STORAGE PRIMARY ENDPOINT URL:

Konfigurera Server dels programmetConfigure the backend application

Öppna bladet Azure AD B2C på portalen och utför följande steg.Open the Azure AD B2C blade in the portal and do the following steps.

  1. Välj fliken registrerings programSelect the App Registrations tab

  2. Klicka på knappen ny registrering.Click the 'New Registration' button.

  3. Välj webb från val rutan omdirigerings-URI.Choose 'Web' from the Redirect URI selection box.

  4. Ange nu visnings namnet och välj något unikt och relevant för den tjänst som skapas.Now set the Display Name, choose something unique and relevant to the service being created. I det här exemplet kommer vi att använda namnet "backend-program".In this example, we will use the name "Backend Application".

  5. Använd plats hållare för svars-URL: er, t. ex. https://jwt.ms (en underkodad token från Microsoft som ägs av Microsoft), och uppdatera dessa URL: er senare.Use placeholders for the reply urls, like 'https://jwt.ms' (A Microsoft owned token decoding site), we’ll update those urls later.

  6. Se till att du har valt alternativet "konton i valfri identitets leverantör eller organisations katalog (för att autentisera användare med användar flöden)"Ensure you have selected the "Accounts in any identity provider or organizational directory (for authenticating users with user flows)" option

  7. I det här exemplet avmarkerar du kryss rutan "bevilja administrativt medgivande", eftersom vi inte behöver offline_access behörigheter idag.For this sample, uncheck the "Grant admin consent" box, as we won't require offline_access permissions today.

  8. Klicka på Registrera.Click 'Register'.

  9. Registrera klient-ID för backend-programmet för senare användning (visas under program (klient) ID).Record the Backend Application Client ID for later use (shown under 'Application (client) ID').

  10. Välj fliken certifikat och hemligheter (under hantera) och klicka sedan på ny klient hemlighet för att generera en auth-nyckel (acceptera standardinställningarna och klicka på Lägg till).Select the Certificates and Secrets tab (under Manage) then click 'New Client Secret' to generate an auth key (Accept the default settings and click 'Add').

  11. När du klickar på "Lägg till" kopierar du nyckeln (under "värde") någon säker för senare användning som "backend-klientens hemlighet" – Observera att den här dialog rutan är den enda chansen att du måste kopiera den här nyckeln.Upon clicking 'Add', copy the key (under 'value') somewhere safe for later use as the 'Backend client secret' - note that this dialog is the ONLY chance you'll have to copy this key.

  12. Välj nu fliken exponera en API (under hantera).Now select the Expose an API Tab (Under Manage).

  13. Du uppmanas att ange AppID URI, välja och registrera standardvärdet.You will be prompted to set the AppID URI, select and record the default value.

  14. Skapa och namnge omfånget "Hello" för funktions-API: et. du kan använda frasen "Hej" för alla alternativ som kan väljas, registrera det ifyllda fullständiga scope-värdet URI och klicka på Lägg till omfång.Create and name the scope "Hello" for your Function API, you can use the phrase 'Hello' for all of the enterable options, recording the populated Full Scope Value URI, then click 'Add Scope'.

  15. Gå tillbaka till roten för bladet Azure AD B2C genom att välja "Azure AD B2C"-spåret överst till vänster i portalen.Return to the root of the Azure AD B2C blade by selecting the 'Azure AD B2C' breadcrumb at the top left of the portal.

    Anteckning

    Azure AD B2C omfattningar är effektiva behörigheter inom ditt API som andra program kan begära åtkomst till via bladet för API-åtkomst från sina program, vilket effektivt precis har skapat program behörigheter för ditt anropade API.Azure AD B2C scopes are effectively permissions within your API that other applications can request access to via the API access blade from their applications, effectively you just created application permissions for your called API.

Konfigurera klient dels programmetConfigure the frontend application

  1. Välj fliken registrerings programSelect the App Registrations tab
  2. Klicka på knappen ny registrering.Click the 'New Registration' button.
  3. Välj "enskild sida" (SPA) "från val rutan omdirigerings-URI.Choose 'Single Page Application (SPA)' from the Redirect URI selection box.
  4. Ange nu visnings namnet och AppID URI och välj något unikt och relevant för klient dels programmet som ska använda den här AAD B2C app-registreringen.Now set the Display Name and AppID URI, choose something unique and relevant to the Frontend application that will use this AAD B2C app registration. I det här exemplet kan du använda "frontend-program"In this example, you can use "Frontend Application"
  5. När du har registrerat den första appen lämnar du valet av konto typer som stöds till standard (autentisera användare med användar flöden)As per the first app registration, leave the supported account types selection to default (authenticating users with user flows)
  6. Använd plats hållare för svars-URL: er, t. ex. https://jwt.ms (en underkodad token från Microsoft som ägs av Microsoft), och uppdatera dessa URL: er senare.Use placeholders for the reply urls, like 'https://jwt.ms' (A Microsoft owned token decoding site), we’ll update those urls later.
  7. Lämna rutan bevilja administratörs medgivandeLeave the grant admin consent box ticked
  8. Klicka på Registrera.Click 'Register'.
  9. Registrera klient-ID för klient dels programmet för senare användning (visas under program (klient) ID).Record the Frontend Application Client ID for later use (shown under 'Application (client) ID').
  10. Växla till fliken API-behörigheter .Switch to the API Permissions tab.
  11. Bevilja åtkomst till backend-programmet genom att klicka på Lägg till en behörighet, sedan på mina API: er, Välj backend-program, Välj behörigheter, Välj det omfång som du skapade i föregående avsnitt och klicka på Lägg till behörigheterGrant access to the backend application by clicking 'Add a permission', then 'My APIs', select the 'Backend Application', select 'Permissions', select the scope you created in the previous section, and click 'Add permissions'
  12. Klicka på bevilja administrativt medgivande för {Tenant} och klicka på Ja i popup-dialog rutan.Click 'Grant admin consent for {tenant} and click 'Yes' from the popup dialog. Den här popup-rutan skickar "klient dels programmet" för att använda behörigheten "Hello" som definieras i "backend-programmet" som skapades tidigare.This popup consents the "Frontend Application" to use the permission "hello" defined in the "Backend Application" created earlier.
  13. Alla behörigheter ska nu visas för appen som ett grönt skal under kolumnen StatusAll Permissions should now show for the app as a green tick under the status column

Skapa ett användar flöde för "Registrera dig och logga in"Create a "Sign up and Sign in" user flow

  1. Gå tillbaka till roten för bladet B2C genom att välja Azure AD B2C dynamiska länkar.Return to the root of the B2C blade by selecting the Azure AD B2C breadcrumb.

  2. Växla till fliken Användarflöden (under principer).Switch to the 'User Flows' (Under Policies) tab.

  3. Klicka på "nytt användar flöde"Click "New user flow"

  4. Välj användar flödes typen "Registrera dig och logga in" och välj "rekommenderas" och sedan ' skapa 'Choose the 'Sign up and sign in' user flow type, and select 'Recommended' and then 'Create'

  5. Ge principen ett namn och registrera den för senare.Give the policy a name and record it for later. I det här exemplet kan du använda "Frontendapp_signupandsignin", Tänk på att detta ska föregås av "B2C_1_" för att göra "B2C_1_Frontendapp_signupandsignin"For this example, you can use "Frontendapp_signupandsignin", note that this will be prefixed with "B2C_1_" to make "B2C_1_Frontendapp_signupandsignin"

  6. Under "identitets leverantörer" och "lokala konton" markerar du "e-postregistrering" (eller "användar-ID-registrering" beroende på konfigurationen av B2C-klienten) och klickar på OK.Under 'Identity providers' and "Local accounts", check 'Email sign up' (or 'User ID sign up' depending on the config of your B2C tenant) and click OK. Den här konfigurationen är att registrera lokala B2C-konton, inte att härleda till en annan identitetsprovider (t. ex. en social identitetsprovider) att använda en användares befintliga konton för sociala medier.This configuration is because we'll be registering local B2C accounts, not deferring to another identity provider (like a social identity provider) to use an user's existing social media account.

  7. Lämna standardinställningarna för MFA-och villkorlig åtkomst.Leave the MFA and conditional access settings at their defaults.

  8. Under "användarattribut och anspråk" klickar du på "Visa fler..." Välj sedan de anspråks alternativ som du vill att användarna ska ange och ha returnerat i token.Under 'User Attributes and claims', click 'Show More...' then choose the claim options that you want your users to enter and have returned in the token. Kontrol lera åtminstone visnings namnet och e-postadressen för att samla in, med visnings namnet och e-postadresserna för att returnera (Läs noggrant noga på det faktum att du samlar in EmailAddress, singular och ber att returnera e-postadresser, flera) och klicka på "skapa".Check at least 'Display Name' and 'Email Address' to collect, with 'Display Name' and 'Email Addresses' to return (pay careful attention to the fact that you are collecting emailaddress, singular, and asking to return email addresses, multiple), and click 'OK', then click 'Create'.

  9. Klicka på det användar flöde som du skapade i listan och klicka sedan på knappen Kör användar flöde.Click on the user flow that you created in the list, then click the 'Run user flow' button.

  10. Den här åtgärden öppnar bladet kör användar flöde, väljer klient dels programmet, kopierar slut punkten för användar flödet och sparar den för senare.This action will open the run user flow blade, select the frontend application, copy the user flow endpoint and save it for later.

  11. Kopiera och lagra länken överst och registrera dig som den välkända OpenID konfigurations slut punkt för senare användning.Copy and store the link at the top, recording as the 'well-known openid configuration endpoint' for later use.

    Anteckning

    Med B2C-principer kan du exponera Azure AD B2C inloggnings slut punkter för att kunna avbilda olika data komponenter och logga in användare på olika sätt.B2C Policies allow you to expose the Azure AD B2C login endpoints to be able to capture different data components and sign in users in different ways.

    I det här fallet konfigurerade vi ett registrerings-eller inloggnings flöde (princip).In this case we configured a sign up or sign in flow (policy). Detta exponerade även en välkänd konfigurations slut punkt, i båda fallen har vår skapade princip identifierats i URL: en med frågesträngparametern "p =".This also exposed a well-known configuration endpoint, in both cases our created policy was identified in the URL by the "p=" query string parameter.

    När detta är gjort har du nu en fungerande verksamhet till en konsument identitets plattform som ska logga in användare i flera program.Once this is done, you now have a functional Business to Consumer identity platform that will sign users into multiple applications.

Bygg funktions-API: etBuild the function API

  1. Växla tillbaka till Azure AD-standardklienten i Azure Portal så att vi kan konfigurera objekt i prenumerationen igen.Switch back to your standard Azure AD tenant in the Azure portal so we can configure items in your subscription again.

  2. Gå till bladet Function apps i Azure Portal, öppna din tomma Function-app, klicka på functions, klicka på Lägg till.Go to the Function Apps blade of the Azure portal, open your empty function app, then click 'Functions', click 'Add'.

  3. I den utfällande som visas väljer du "utveckla i portalen" under "Välj en mall" och sedan "HTTP-utlösare" under mal LINY information Name ' Hej ' med autentiseringsnivå ' function ' och väljer sedan Lägg till.In the flyout that appears, choose 'Develop in portal', under 'select a template' then choose 'HTTP trigger', under Template details name it 'hello' with authorization level 'Function', then select Add.

  4. Växla till bladet kod + test och kopiera – klistra in exempel koden från nedan över den befintliga koden som visas.Switch to the Code + Test blade and copy-paste the sample code from below over the existing code that appears.

  5. Välj SparaSelect Save.

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

    Tips

    Den c#-skript funktions kod som du nyss klistrade in loggar bara in en rad till funktions loggarna och returnerar texten "Hello World" med vissa dynamiska data (datum och tid).The c# script function code you just pasted simply logs a line to the functions logs, and returns the text "Hello World" with some dynamic data (the date and time).

  6. Välj "integration" på bladet till vänster och klicka sedan på http-länken (req) i rutan utlösare.Select “Integration” from the left-hand blade, then click the http (req) link inside the 'Trigger' box.

  7. I list rutan "markerade HTTP-metoder" avmarkerar du http POST-metoden och lämnar bara markerat och klickar sedan på Spara.From the 'Selected HTTP methods' dropdown, uncheck the http POST method, leaving only GET selected, then click Save.

  8. Växla tillbaka till fliken kod + test, klicka på Hämta funktions webb adress och kopiera sedan den URL som visas och spara den för senare.Switch back to the Code + Test tab, click 'Get Function URL', then copy the URL that appears and save it for later.

    Anteckning

    Bindningarna som du nyss skapade ger dig bara funktioner för att svara på anonyma HTTP GET-begäranden till den URL som du precis kopierade ( https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey ).The bindings you just created simply tell Functions to respond on anonymous http GET requests to the URL you just copied (https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey). Nu har vi ett skalbart Server lös https API som kan returnera en mycket enkel nytto Last.Now we have a scalable serverless https API, that is capable of returning a very simple payload.

    Nu kan du testa att anropa detta API från en webbläsare med din version av URL: en som du precis kopierade och sparade.You can now test calling this API from a web browser using your version of the URL above that you just copied and saved. Du kan också ta bort frågesträngparametern "? Code = secretkey" i URL-adressen och testa igen för att bevisa att Azure Functions returnerar ett 401-fel.You can also remove the query string parameters "?code=secretkey" portion of the URL , and test again, to prove that Azure Functions will return a 401 error.

Konfigurera och skydda funktions-API: etConfigure and secure the function API

  1. Två extra områden i Function-appen måste konfigureras (auktoriserings-och nätverks begränsningar).Two extra areas in the function app need to be configured (Authorization and Network Restrictions).

  2. Vi börjar med att konfigurera autentisering/auktorisering, så gå tillbaka till rot bladet i Function-appen via dynamiska objekt.Firstly Let's configure Authentication / Authorization, so navigate back to the root blade of the function app via the breadcrumb.

  3. Välj sedan ' autentisering/auktorisering ' (under ' Inställningar ').Next select 'Authentication / Authorization' (under 'Settings').

  4. Aktivera funktionen för App Service autentisering.Turn on the App Service Authentication feature.

  5. Ange den åtgärd som ska vidtas när förfrågan inte är autentiserad att logga in med Azure Active Directory.Set the Action to take when request is not authenticated dropdown to "Log in with Azure Active Directory".

  6. Under "autentiseringsproviders" väljer du "Azure Active Directory".Under 'Authentication Providers', choose ‘Azure Active Directory’.

  7. Välj Avancerat från växeln hanterings läge.Choose ‘Advanced’ from the Management Mode switch.

  8. Klistra in Server dels programmets [Application]-klient-ID (från Azure AD B2C) i rutan klient-IDPaste the Backend application's [Application] Client ID (from Azure AD B2C) into the ‘Client ID’ box

  9. Klistra in den välkända konfigurations slut punkten med öppen ID från registrerings-och inloggnings principen i rutan utfärdar-URL (vi har spelat in den här konfigurationen tidigare).Paste the Well-known open-id configuration endpoint from the sign up and sign in policy into the Issuer URL box (we recorded this configuration earlier).

  10. Klicka på "Visa hemlighet" och klistra in backend-programmets klient hemlighet i lämplig ruta.Click 'Show Secret' and paste the Backend application's client secret into the appropriate box.

  11. Välj OK, som tar dig tillbaka till bladet för val av identitetsprovider/skärm.Select OK, which takes you back to the identity provider selection blade/screen.

  12. Lämna token Store aktiverat under avancerade inställningar (standard).Leave Token Store enabled under advanced settings (default).

  13. Klicka på Spara (längst upp till vänster på bladet).Click 'Save' (at the top left of the blade).

    Viktigt

    Nu distribueras funktions-API: et och ska resultera i 401 svar om rätt JWT inte anges som en auktorisering: Bearer-huvud och bör returnera data när en giltig begäran visas.Now your Function API is deployed and should throw 401 responses if the correct JWT is not supplied as an Authorization: Bearer header, and should return data when a valid request is presented.
    Du har lagt till ytterligare skydd mot djupgående säkerhet i EasyAuth genom att konfigurera alternativet "logga in med Azure AD" för att hantera oautentiserade begär Anden.You added additional defense-in-depth security in EasyAuth by configuring the 'Login With Azure AD' option to handle unauthenticated requests. Tänk på att detta ändrar beteendet för obehöriga begär Anden mellan backend-Funktionsapp och klient delens SPA som EasyAuth utfärdar en 302-omdirigering till AAD i stället för en 401 som inte har auktoriserats, korrigerar vi detta genom att använda API Management senare.Be aware that this will change the unauthorized request behavior between the Backend Function App and Frontend SPA as EasyAuth will issue a 302 redirect to AAD instead of a 401 Not Authorized response, we will correct this by using API Management later.

    Vi har fortfarande ingen IP-säkerhet tillämpad, om du har en giltig nyckel-och OAuth2-token, kan vem som helst anropa detta från var som helst, så vi vill tvinga alla förfrågningar att komma via API Management.We still have no IP security applied, if you have a valid key and OAuth2 token, anyone can call this from anywhere - ideally we want to force all requests to come via API Management.

    Om du använder APIM förbruknings nivå finns det ingen dedikerad Azure API Management virtuell IP-adress för att tillåta-lista med funktionen åtkomst begränsningar.If you're using APIM Consumption tier then there isn't a dedicated Azure API Management Virtual IP to allow-list with the functions access-restrictions. I Azure API Management standard SKU: n och över VIP är en enskild klient och för resursens livs längd.In the Azure API Management Standard SKU and above the VIP is single tenant and for the lifetime of the resource. För användnings nivån Azure API Management kan du låsa API-anropen via den delade hemliga funktions nyckeln i den del av URI: n som du kopierade ovan.For the Azure API Management Consumption tier, you can lock down your API calls via the shared secret function key in the portion of the URI you copied above. För förbruknings nivån är steg 12-17 inte heller tillämpliga.Also, for the Consumption tier - steps 12-17 below do not apply.

  14. Stäng bladet "autentisering/auktorisering"Close the 'Authentication / Authorization' blade

  15. Öppna bladet API Management i portalen och öppna sedan instansen.Open the API Management blade of the portal, then open your instance.

  16. Registrera den privata VIP som visas på fliken Översikt.Record the Private VIP shown on the overview tab.

  17. Gå tillbaka till bladet Azure Functions på portalen och öppna sedan instansen igen.Return to the Azure Functions blade of the portal then open your instance again.

  18. Välj nätverk och välj sedan konfigurera åtkomst begränsningarSelect 'Networking' and then select 'Configure access restrictions'

  19. Klicka på Lägg till regel och ange den VIP som kopierades i steg 3 ovan i formatet xx. xx. xx. xx/32.Click 'Add Rule', and enter the VIP copied in step 3 above in the format xx.xx.xx.xx/32.

  20. Om du vill fortsätta att interagera med funktions portalen och utföra de valfria stegen nedan, bör du lägga till din egen offentliga IP-adress eller CIDR-intervall här.If you want to continue to interact with the functions portal, and to carry out the optional steps below, you should add your own public IP address or CIDR range here too.

  21. När det finns en Tillåt-post i listan lägger Azure till en implicit neka-regel för att blockera alla andra adresser.Once there’s an allow entry in the list, Azure adds an implicit deny rule to block all other addresses.

Du måste lägga till CIDR-formaterade block med adresser i panelen IP-begränsningar.You'll need to add CIDR formatted blocks of addresses to the IP restrictions panel. När du behöver lägga till en enskild adress, till exempel API Management VIP, måste du lägga till den i formatet xx. xx. xx. xx/32.When you need to add a single address such as the API Management VIP, you need to add it in the format xx.xx.xx.xx/32.

Anteckning

Nu ska funktions-API: et inte kunna anropas från någon annan stans än via API Management eller din adress.Now your Function API should not be callable from anywhere other than via API management, or your address.

  1. Öppna bladet API Management och öppna sedan instansen.Open the API Management blade, then open your instance.

  2. Välj bladet API: er (under API: er).Select the APIs Blade (under APIs).

  3. I fönstret Lägg till ett nytt API väljer du Funktionsapp och väljer sedan fullständig längst upp i popup-fönstret.From the 'Add a New API' pane, choose 'Function App', then select 'Full' from the top of the popup.

  4. Klicka på Bläddra, Välj den app som du är värd för API: et i och klicka på Välj.Click Browse, choose the function app you're hosting the API inside, and click select. Klicka sedan på Välj igen.Next, click select again.

  5. Ge API: et ett namn och en beskrivning för API Managementens interna användning och Lägg till det i den obegränsade produkten.Give the API a name and description for API Management's internal use and add it to the ‘unlimited’ Product.

  6. Kopiera och registrera API: s bas-URL och klicka på Skapa.Copy and record the API's 'base URL' and click 'create'.

  7. Klicka på fliken Inställningar, under prenumeration – Stäng av kryss rutan "prenumeration krävs" eftersom vi ska använda OAuth JWT-token i det här fallet för hastighets begränsning.Click the 'settings' tab, then under subscription - switch off the 'Subscription Required' checkbox as we will use the Oauth JWT token in this case to rate limit. Observera att om du använder förbruknings nivån krävs det fortfarande i en produktions miljö.Note that if you are using the consumption tier, this would still be required in a production environment.

    Tips

    Om du använder förbruknings nivån APIM är den obegränsade produkten inte tillgänglig som en del av lådan.If using the consumption tier of APIM the unlimited product won't be available as an out of the box. Gå i stället till "Products" under "API: er" och tryck på "Lägg till".Instead, navigate to "Products" under "APIs" and hit "Add".
    Skriv "obegränsat" som produkt namn och beskrivning och välj det API som du nyss lade till från bild texten "+" längst ned till vänster på skärmen.Type "Unlimited" as the product name and description and select the API you just added from the "+" APIs callout at the bottom left of the screen. Markera kryss rutan publicerad.Select the "published" checkbox. Lämna resten som standard.Leave the rest as default. Klicka slutligen på knappen "skapa".Finally, hit the "create" button. Detta skapade den "obegränsad" produkten och tilldelade den till ditt API.This created the "unlimited" product and assigned it to your API. Du kan anpassa den nya produkten senare.You can customize your new product later.

Konfigurera och avbilda rätt inställningar för lagrings slut punktConfigure and capture the correct storage endpoint settings

  1. Öppna bladet lagrings konton i Azure PortalOpen the storage accounts blade in the Azure portal

  2. Välj det konto som du skapade och välj bladet "statisk webbplats" från avsnittet Inställningar (om du inte ser alternativet "statisk webbplats" kontrollerar du att du har skapat ett v2-konto).Select the account you created and select the 'Static Website' blade from the Settings section (if you don't see a 'Static Website' option, check you created a V2 account).

  3. Ställ in funktionen för statisk webb värd till "aktive rad" och ange index dokument namnet till "index.html" och klicka sedan på "Spara".Set the static web hosting feature to 'enabled', and set the index document name to 'index.html', then click 'save'.

  4. Anteckna innehållet i den primära slut punkten för senare, eftersom den här platsen är den plats där klient dels platsen finns.Note down the contents of the 'Primary Endpoint' for later, as this location is where the frontend site will be hosted.

    Tips

    Du kan använda Azure Blob Storage + CDN-omskrivning eller Azure App Service som värd för funktionen SPA-men Blob Storage som värd för en statisk webbplats ger oss en standard behållare för att hantera statiskt webb innehåll/HTML/JS/CSS från Azure Storage och kommer att härleda en standard sida för oss för noll arbete.You could use either Azure Blob Storage + CDN rewrite, or Azure App Service to host the SPA - but Blob Storage's Static Website hosting feature gives us a default container to serve static web content / html / js / css from Azure Storage and will infer a default page for us for zero work.

Konfigurera CORS -och validate-JWT- principerSet up the CORS and validate-jwt policies

Följande avsnitt bör följas oavsett vilken APIM-nivå som används.The following sections should be followed regardless of the APIM tier being used. Lagrings kontots URL är från det lagrings konto som du har gjort tillgängligt från kraven överst i den här artikeln.The storage account URL is from the storage account you will have made available from the prerequisites at the top of this article.

  1. Växla till API Management-bladet i portalen och öppna instansen.Switch to the API management blade of the portal and open your instance.

  2. Välj API: er och välj sedan alla API: er.Select APIs, then select “All APIs”.

  3. Under "inkommande bearbetning" klickar du på knappen kodvy "</>" för att Visa princip redigeraren.Under "Inbound processing", click the code view button "</>" to show the policy editor.

  4. Redigera avsnittet inkommande och klistra in nedanstående XML så att det ser ut ungefär så här.Edit the inbound section and paste the below xml so it reads like the following.

  5. Ersätt följande parametrar i principenReplace the following parameters in the Policy

  6. {PrimaryStorageEndpoint} (Den primära lagrings slut punkten som du kopierade i föregående avsnitt), {b2cpolicy-välkänd-OpenID} (den välkända OpenID konfigurations slut punkten som du kopierade tidigare) och {backend-API-application-Client-ID} (B2C-program/klient-ID för Server dels-API: et) med rätt värden sparade tidigare.{PrimaryStorageEndpoint} (The 'Primary Storage Endpoint' you copied in the previous section), {b2cpolicy-well-known-openid} (The 'well-known openid configuration endpoint' you copied earlier) and {backend-api-application-client-id} (The B2C Application / Client ID for the backend API) with the correct values saved earlier.

  7. Om du använder förbruknings nivån för API Management bör du ta bort både principen för begränsning efter nyckel eftersom den här principen inte är tillgänglig när du använder användnings nivån i Azure API Management.If you're using the Consumption tier of API Management, then you should remove both rate-limit-by-key policy as this policy is not available when using the Consumption tier of Azure API Management.

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

    Anteckning

    Nu kan Azure API Management svara på kors ursprungs begär Anden från dina JavaScript SPA-appar och den utför begränsning, hastighets begränsning och för validering av JWT auth-token som skickas innan du vidarebefordrar begäran till Function API.Now Azure API management is able respond to cross origin requests from your JavaScript SPA apps, and it will perform throttling, rate-limiting and pre-validation of the JWT auth token being passed BEFORE forwarding the request on to the Function API.

    Grattis, nu har du Azure AD B2C, API Management och Azure Functions samar beta för att publicera, skydda och använda en API!Congratulations, you now have Azure AD B2C, API Management and Azure Functions working together to publish, secure AND consume an API!

    Tips

    Om du använder API Management förbruknings nivå i stället för hastighets begränsning av JWT-ämnet eller inkommande IP-adress (begränsa anrops frekvensen per nyckel princip stöds inte idag för nivån "förbrukning"), kan du begränsa efter anrops frekvens kvoten här.If you're using the API Management consumption tier then instead of rate limiting by the JWT subject or incoming IP Address (Limit call rate by key policy is not supported today for the "Consumption" tier), you can Limit by call rate quota see here.
    Det här exemplet är ett program med en enda sida med Java Script, men vi använder bara API Management nyckeln för Rate-Limiting-och fakturerings anrop.As this example is a JavaScript Single Page Application, we use the API Management Key only for rate-limiting and billing calls. Den faktiska auktoriseringen och autentiseringen hanteras av Azure AD B2C och kapslas in i JWT, som verifieras två gånger, en gång av API Management, och sedan av Server delen Azure function.The actual Authorization and Authentication is handled by Azure AD B2C, and is encapsulated in the JWT, which gets validated twice, once by API Management, and then by the backend Azure Function.

Ladda upp exempel skriptet SPA till statisk lagringUpload the JavaScript SPA sample to static storage

  1. På bladet lagrings konto väljer du bladet behållare från avsnittet BLOB service och klickar på den $web behållare som visas i den högra rutan.Still in the storage account blade, select the 'Containers' blade from the Blob Service section and click on the $web container that appears in the right-hand pane.

  2. Spara koden nedan till en fil lokalt på datorn som index.html och överför sedan filen index.html till $web-behållaren.Save the code below to a file locally on your machine as index.html and then upload the file index.html to the $web container.

     <!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 AAD 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 will 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>
    
  3. Bläddra till den primära slut punkten för den statiska webbplatsen som du sparade tidigare i det sista avsnittet.Browse to the Static Website Primary Endpoint you stored earlier in the last section.

    Anteckning

    Grattis, du har precis distribuerat en JavaScript-app med ett enda sidfel till Azure Storage statiskt innehåll som värd.Congratulations, you just deployed a JavaScript Single Page App to Azure Storage Static content hosting.
    Eftersom vi inte har konfigurerat JS-appen med Azure AD B2C information ännu – sidan fungerar inte ännu om du öppnar den.Since we haven’t configured the JS app with your Azure AD B2C details yet – the page won't work yet if you open it.

Konfigurera Java Script SPA för Azure AD B2CConfigure the JavaScript SPA for Azure AD B2C

  1. Nu vet vi var allt är: vi kan konfigurera SPA med lämplig API Management-API-adress och rätt Azure AD B2C program/klient-ID.Now we know where everything is: we can configure the SPA with the appropriate API Management API address and the correct Azure AD B2C application / client IDs.
  2. Gå tillbaka till bladet Azure Portal lagringGo back to the Azure portal storage blade
  3. Välj behållare (under Inställningar)Select 'Containers' (under 'Settings')
  4. Välj behållaren $web i listanSelect the '$web' container from the list
  5. Välj index.html BLOB i listanSelect index.html blob from the list
  6. Klicka på RedigeraClick 'Edit'
  7. Uppdatera auth-värdena i msal config-avsnittet så att de matchar ditt klient program som du registrerade i B2C tidigare.Update the auth values in the msal config section to match your front-end application you registered in B2C earlier. Använd kod kommentarer för tips om hur konfigurations värden ska se ut.Use the code comments for hints on how the config values should look. Auktoritet svärdet måste vara i formatet:-https://{b2ctenantname}. b2clogin. com/TFP/{b2ctenantname}. onmicrosoft. com}/{signupandsigninpolicyname}, om du har använt våra exempel namn och din B2C-klient kallas "contoso", förväntar du att utfärdaren ska vara https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com}/Frontendapp_signupandsignin .The authority value needs to be in the format:- https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantname}.onmicrosoft.com}/{signupandsigninpolicyname}, if you have used our sample names and your b2c tenant is called 'contoso' then you would expect the authority to be 'https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com}/Frontendapp_signupandsignin'.
  8. Ange API-värdena som matchar din server dels adress (API-bas-URL: en som du registrerade tidigare och värdena "b2cScopes" registrerades tidigare för Server dels programmet).Set the api values to match your backend address (The API Base Url you recorded earlier, and the 'b2cScopes' values were recorded earlier for the backend application).
  9. Klicka på SparaClick Save

Ange omdirigerings-URI: er för Azure AD B2C frontend-appenSet the redirect URIs for the Azure AD B2C frontend app

  1. Öppna bladet Azure AD B2C och navigera till program registreringen för program varan för JavaScript-frontend.Open the Azure AD B2C blade and navigate to the application registration for the JavaScript Frontend Application.

  2. Klicka på omdirigering av URI: er och ta bort plats hållaren som https://jwt.ms du angav tidigare.Click 'Redirect URIs' and delete the placeholder 'https://jwt.ms' we entered earlier.

  3. Lägg till en ny URI för den primära (lagring) slut punkten (minus det avslutande snedstrecket).Add a new URI for the primary (storage) endpoint (minus the trailing forward slash).

    Anteckning

    Den här konfigurationen leder till att en klient med klient dels programmet tar emot en åtkomsttoken med lämpliga anspråk från Azure AD B2C.This configuration will result in a client of the frontend application receiving an access token with appropriate claims from Azure AD B2C.
    SPA kommer att kunna lägga till detta som en Bearer-token i https-huvudet i anropet till Server dels-API: et.The SPA will be able to add this as a bearer token in the https header in the call to the backend API.

    API Management validerar token, hastighets begränsnings anrop till slut punkten av både ämnet för det JWT som utfärdats av Azure ID (användaren) och IP-adressen för anroparen (beroende på tjänst nivå för API Management, se kommentaren ovan) innan du skickar genom förfrågan till den mottagande Azure Function API, så att du lägger till funktions säkerhets nyckeln.API Management will pre-validate the token, rate-limit calls to the endpoint by both the subject of the JWT issued by Azure ID (the user) and by IP address of the caller (depending on the service tier of API Management, see the note above), before passing through the request to the receiving Azure Function API, adding the functions security key.
    SPA kommer att återge svaret i webbläsaren.The SPA will render the response in the browser.

    Grattis, du har konfigurerat Azure AD B2C, Azure API Management Azure Functions, Azure App Service behörighet att arbeta med perfekt harmoniregeln!Congratulations, you’ve configured Azure AD B2C, Azure API Management, Azure Functions, Azure App Service Authorization to work in perfect harmony!

Nu har vi en enkel app med en enkel säker API som vi testar.Now we have a simple app with a simple secured API, let's test it.

Testa klient programmetTest the client application

  1. Öppna den exempel-App-URL som du antecknade från det lagrings konto som du skapade tidigare.Open the sample app URL that you noted down from the storage account you created earlier.
  2. Klicka på "logga in" i det övre högra hörnet, så öppnas det Azure AD B2C registrera dig eller logga in i profilen.Click “Sign In” in the top-right-hand corner, this click will pop up your Azure AD B2C sign up or sign in profile.
  3. Appen bör Välkommen till ditt B2C-profil namn.The app should welcome you by your B2C profile name.
  4. Klicka på anropa API och uppdatera med värdena som skickas tillbaka från ditt säkra API.Now Click "Call API" and the page should update with the values sent back from your secured API.
  5. Om du upprepade gånger klickar på anrops-API-knappen och du kör på Developer-nivån eller ovanför API Management bör du tänka på att din lösning börjar bedöma API: et och den här funktionen bör rapporteras i appen med ett lämpligt meddelande.If you repeatedly click the Call API button and you're running in the developer tier or above of API Management, you should note that your solution will begin to rate limit the API and this feature should be reported in the app with an appropriate message.

Och vi är klaraAnd we're done

Stegen ovan kan anpassas och redige ras för att tillåta många olika användningar av Azure AD B2C med API Management.The steps above can be adapted and edited to allow many different uses of Azure AD B2C with API Management.

Nästa stegNext steps