Protección del back-end de SPA con OAuth 2.0, Azure Active Directory B2C y Azure API ManagementProtect SPA backend with OAuth 2.0, Azure Active Directory B2C and Azure API Management

En este escenario se muestra cómo configurar la instancia de Azure API Management para proteger una API.This scenario shows you how to configure your Azure API Management instance to protect an API. Usaremos el flujo de SPA de Azure AD B2C (código de autenticación + PKCE) para adquirir un token, junto con API Management para proteger un back-end de Azure Functions con 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.

ObjetivosAims

Vamos a ver cómo se puede usar API Management en un escenario simplificado con Azure Functions y 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. Creará una aplicación JavaScript (JS) que llama a una API que inicia la sesión de los usuarios con Azure AD B2C.You'll create a JavaScript (JS) app calling an API, that signs in users with Azure AD B2C. A continuación, usará las características de directiva de validación de JWT, CORS y limitar la tasa de llamadas por clave de API Management para proteger la API de back-end.Then you'll use API Management's validate-jwt, CORS, and Rate Limit By Key policy features to protect the Backend API.

Para la defensa en profundidad, usamos EasyAuth para validar el token de nuevo dentro de la API de back-end y garantizar que API Management es el único servicio que puede llamar al back-end de Azure Functions.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.

Qué aprenderáWhat will you learn

  • Configuración de una aplicación de página única y una API de back-end en Azure Active Directory B2CSetup of a Single Page App and backend API in Azure Active Directory B2C
  • Creación de una API de back-end Azure FunctionsCreation of an Azure Functions Backend API
  • Importación de una API de Azure Functions en Azure API ManagementImport of an Azure Functions API into Azure API Management
  • Protección de la API en Azure API ManagementSecuring the API in Azure API Management
  • Llamada a los puntos de conexión de autorización de Azure Active Directory B2C a través de las bibliotecas de la plataforma de identidad de Microsoft (MSAL.js)Calling the Azure Active Directory B2C Authorization Endpoints via the Microsoft Identity Platform Libraries (MSAL.js)
  • Almacenamiento de una aplicación de página única de HTML/Vanilla JS y su servicio desde un punto de conexión de Azure Blob StorageStoring a HTML / Vanilla JS Single Page Application and serving it from an Azure Blob Storage Endpoint

Requisitos previosPrerequisites

Para seguir los pasos de este artículo, debe tener:To follow the steps in this article, you must have:

  • Una cuenta de almacenamiento de Azure (StorageV2) de uso general V2 para hospedar la aplicación de página única JS de front-end.An Azure (StorageV2) General Purpose V2 Storage Account to host the frontend JS Single Page App.
  • Una instancia de Azure API Management (cualquier nivel funcionará, incluido "Consumo"; sin embargo, algunas características aplicables al escenario completo no están disponibles en este nivel [Limitar la tasa de llamadas por clave y dirección IP virtual dedicada]; estas restricciones se indican a continuación en el artículo en las secciones correspondientes).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).
  • Una aplicación de Azure Functions vacía (que ejecute el entorno de ejecución de .NET Core V3.1 en un plan de consumo) para hospedar la API llamada.An empty Azure Function app (running the V3.1 .NET Core runtime, on a Consumption Plan) to host the called API
  • Un inquilino de Azure AD B2C vinculado a una suscripción.An Azure AD B2C tenant, linked to a subscription.

Aunque en la práctica usaría recursos en la misma región en cargas de trabajo de producción, para este artículo de procedimientos, la región de implementación no importa.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.

Información generalOverview

A continuación se muestra una ilustración de los componentes en uso y el flujo entre ellos una vez completado este proceso.Here's an illustration of the components in use and the flow between them once this process is complete. Componentes en uso y flujoComponents in use and flow

Aquí se muestra una rápida visión general de los pasos:Here's a quick overview of the steps:

  1. Cree las aplicaciones de llamada de Azure AD B2C (front-end, API Management) y de API con ámbitos, y concédales acceso de APICreate the Azure AD B2C Calling (Frontend, API Management) and API Applications with scopes and grant API Access

  2. Cree las directivas de registro e inicio de sesión para permitir que los usuarios inicien sesión con Azure AD B2C.Create the sign up and sign in policies to allow users to sign in with Azure AD B2C

  3. Configure API Management con los nuevos identificadores y claves de cliente de Azure AD B2C para habilitar la autorización de usuario de OAuth2 en la consola del desarrolladorConfigure API Management with the new Azure AD B2C Client IDs and keys to Enable OAuth2 user authorization in the Developer Console

  4. Compile Function APIBuild the Function API

  5. Configure Function API para habilitar Easy Auth con el nuevo identificador y las claves de cliente de Azure AD B2C y realice el bloqueo para la IP virtual de APIMConfigure the Function API to enable EasyAuth with the new Azure AD B2C Client ID’s and Keys and lock down to APIM VIP

  6. Compile la definición de API en API ManagementBuild the API Definition in API Management

  7. Configure Oauth2 para la configuración de la API de API ManagementSet up Oauth2 for the API Management API configuration

  8. Configure la directiva CORS y agregue la validate-jwt para validar el token de OAuth para todas las solicitudes entrantesSet up the CORS policy and add the validate-jwt policy to validate the OAuth token for every incoming request

  9. Compile la aplicación que realiza la llamada para que consuma la APIBuild the calling application to consume the API

  10. Cargue el ejemplo de aplicación JS de página únicaUpload the JS SPA Sample

  11. Configure aplicación JS cliente de ejemplo con las nuevas claves y el nuevo identificador de cliente de Azure AD B2CConfigure the Sample JS Client App with the new Azure AD B2C Client ID’s and keys

  12. Pruebe la aplicación clienteTest the Client Application

    Sugerencia

    Vamos a capturar bastantes piezas de información y claves, etc. a medida que avanzamos en este documento; puede que le resulte útil tener un editor de texto abierto para almacenar los siguientes elementos de configuración temporalmente.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.

    ID. DE CLIENTE DE BACK-END DE B2C:B2C BACKEND CLIENT ID:
    CLAVE DE SECRETO DE CLIENTE DE BACK-END DE B2C:B2C BACKEND CLIENT SECRET KEY:
    URI DE ÁMBITO DE API DE BACK-END DE B2C:B2C BACKEND API SCOPE URI:
    ID. DE CLIENTE DE FRONT-END DE B2C:B2C FRONTEND CLIENT ID:
    URI DE PUNTO DE CONEXIÓN DE FLUJO DE USUARIO DE B2C:B2C USER FLOW ENDPOINT URI:
    PUNTO DE CONEXIÓN DE OPENID CONOCIDO DE B2C:B2C WELL-KNOWN OPENID ENDPOINT:
    NOMBRE DE LA DIRECTIVA DE B2C: Frontendapp_signupandsignin DIRECCIÓN URL DE FUNCIÓN:B2C POLICY NAME: Frontendapp_signupandsignin FUNCTION URL:
    DIRECCIÓN URL BASE DE APIM API: URL DEL PUNTO DE CONEXIÓN PRINCIPAL DE ALMACENAMIENTO:APIM API BASE URL: STORAGE PRIMARY ENDPOINT URL:

Configuración de la aplicación de back-endConfigure the backend application

Abra la hoja Azure AD B2C en el portal y realice los pasos siguientes.Open the Azure AD B2C blade in the portal and do the following steps.

  1. Seleccione la pestaña Registros de aplicaciones.Select the App Registrations tab

  2. Haga clic en el botón "Nuevo registro".Click the 'New Registration' button.

  3. Elija "Web" en el cuadro de selección URI de redireccionamiento.Choose 'Web' from the Redirect URI selection box.

  4. Ahora establezca el Nombre para mostrar, que sea único y pertinente para el servicio que se va a crear.Now set the Display Name, choose something unique and relevant to the service being created. En este ejemplo, usaremos el nombre "Aplicación de back-end".In this example, we will use the name "Backend Application".

  5. Use marcadores de posición para las direcciones URL de respuesta, como "https://jwt.ms" (un sitio de descodificación de tokens propiedad de Microsoft), actualizaremos estas direcciones URL más adelante.Use placeholders for the reply urls, like 'https://jwt.ms' (A Microsoft owned token decoding site), we’ll update those urls later.

  6. Asegúrese de que ha seleccionado la opción "Cuentas en cualquier proveedor de identidades o directorio de la organización (para autenticar usuarios con flujos de usuario)".Ensure you have selected the "Accounts in any identity provider or organizational directory (for authenticating users with user flows)" option

  7. En este ejemplo, desactive la casilla "Concesión de consentimiento del administrador", ya que hoy no se requerirán permisos offline_access.For this sample, uncheck the "Grant admin consent" box, as we won't require offline_access permissions today.

  8. Haga clic en "Registrar".Click 'Register'.

  9. Registre el identificador de cliente de la aplicación de back-end para su uso posterior, que aparece en "Id. de aplicación (cliente)".Record the Backend Application Client ID for later use (shown under 'Application (client) ID').

  10. Seleccione la pestaña Certificados y secretos (bajo Administrar) y haga clic en "Nuevo secreto de cliente" para generar una clave de autenticación (acepte la configuración predeterminada y haga clic en "Agregar").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. Después de hacer clic en "Agregar", copie la clave (en "valor") en algún lugar seguro para su uso posterior como "secreto de cliente de back-end". Tenga en cuenta que este cuadro de diálogo es la ÚNICA posibilidad que tendrá para copiar esta clave.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. Ahora, seleccione la pestaña Exponer una API (en Administrar).Now select the Expose an API Tab (Under Manage).

  13. Se le pedirá que establezca el URI de AppID, seleccione y registre el valor predeterminado.You will be prompted to set the AppID URI, select and record the default value.

  14. Cree el ámbito de la API de función y póngale el nombre "Hello". Puede usar la frase "Hello" para todas las opciones en las que puede escribir un valor. Luego, registre el URI del valor de ámbito completo rellenado y haga clic en "Agregar ámbito".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. Vuelva a la raíz de la hoja Azure AD B2C seleccionando la ruta de navegación "Azure AD B2C" en la parte superior izquierda del portal.Return to the root of the Azure AD B2C blade by selecting the 'Azure AD B2C' breadcrumb at the top left of the portal.

    Nota

    Los ámbitos de Azure AD B2C son permisos dentro de la API a los que otras aplicaciones pueden solicitar acceso mediante la hoja de acceso a API de sus aplicaciones.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.

Configuración de la aplicación de front-endConfigure the frontend application

  1. Seleccione la pestaña Registros de aplicaciones.Select the App Registrations tab
  2. Haga clic en el botón "Nuevo registro".Click the 'New Registration' button.
  3. Elija "Aplicación de página única (SPA)" en el cuadro de selección del URI de redireccionamiento.Choose 'Single Page Application (SPA)' from the Redirect URI selection box.
  4. Ahora establezca el nombre para mostrar y el URI de AppID, elija algo único y pertinente para la aplicación de front-end que usará este registro de la aplicación AAD B2C.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. En este ejemplo, puede usar "Aplicación de front-end".In this example, you can use "Frontend Application"
  5. Al igual que en el primer registro de la aplicación, deje la selección de los tipos de cuenta admitidos en su valor predeterminado (autenticación de usuarios con flujos de usuarios).As per the first app registration, leave the supported account types selection to default (authenticating users with user flows)
  6. Use marcadores de posición para las direcciones URL de respuesta, como "https://jwt.ms" (un sitio de descodificación de tokens propiedad de Microsoft), actualizaremos estas direcciones URL más adelante.Use placeholders for the reply urls, like 'https://jwt.ms' (A Microsoft owned token decoding site), we’ll update those urls later.
  7. Deje marcada la casilla Conceder consentimiento de administrador.Leave the grant admin consent box ticked
  8. Haga clic en "Registrar".Click 'Register'.
  9. Registre el identificador de cliente de la aplicación de front-end para su uso posterior, que aparece en "Id. de aplicación (cliente)".Record the Frontend Application Client ID for later use (shown under 'Application (client) ID').
  10. Cambie a la pestaña Permisos de API.Switch to the API Permissions tab.
  11. Para conceder acceso a la aplicación de back-end, haga clic en "Agregar un permiso", luego en "Mis API", seleccione "Aplicación de back-end", seleccione "Permisos", seleccione el ámbito que creó en la sección anterior y haga clic en "Agregar permisos".Grant 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. Haga clic en "Conceder consentimiento de administrador para {inquilino}" y haga clic en" Sí "en el cuadro de diálogo emergente.Click 'Grant admin consent for {tenant} and click 'Yes' from the popup dialog. Este elemento emergente da su consentimiento a la "Aplicación de front-end" para usar el permiso "Hello" definido en la "Aplicación de back-end" que se creó anteriormente.This popup consents the "Frontend Application" to use the permission "hello" defined in the "Backend Application" created earlier.
  13. Todos los permisos deben mostrarse ahora para la aplicación como una marca de verificación verde en la columna de estado.All Permissions should now show for the app as a green tick under the status column

Creación de un flujo de usuario de registro e inicio de sesiónCreate a "Sign up and Sign in" user flow

  1. Vuelva a la raíz de la hoja de B2C seleccionando la ruta de navegación de Azure AD B2C.Return to the root of the B2C blade by selecting the Azure AD B2C breadcrumb.

  2. Cambie a la pestaña "Flujos de usuario" (en Directivas).Switch to the 'User Flows' (Under Policies) tab.

  3. Haga clic en "Nuevo flujo de usuario".Click "New user flow"

  4. Elija el tipo de flujo de usuario "Registrarse e iniciar sesión" y seleccione "Recomendado". Luego, haga clic en "Crear".Choose the 'Sign up and sign in' user flow type, and select 'Recommended' and then 'Create'

  5. Asígnele un nombre a la directiva y regístrelo para más adelante.Give the policy a name and record it for later. En este ejemplo, puede usar "Frontendapp_signupandsignin", tenga en cuenta que se le antepondrá "B2C_1_" creando "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. En "Proveedores de identidades" y "Cuentas locales", active "Registro con correo electrónico" (o "Registro con Id. de usuario" en función de la configuración del inquilino de B2C) y haga clic en Aceptar.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. Esta configuración se debe a que vamos a registrar cuentas locales B2C, y no remitirnos a otro proveedor de identidades (como un proveedor de identidades sociales) para utilizar la cuenta de medios sociales existente de un usuario.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. Deje la configuración de MFA y de acceso condicional en sus valores predeterminados.Leave the MFA and conditional access settings at their defaults.

  8. En "User Attributes and claims" (Notificaciones y atributos de usuario), haga clic en "Mostrar más...", elija las opciones de notificaciones que desee que los usuarios escriban y reciban de vuelta en el 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. Active al menos "Nombre para mostrar" y "Dirección de correo electrónico" para recopilar, con "Nombre para mostrar" y "Direcciones de correo electrónico" para devolver (preste mucha atención al hecho de que está recopilando dirección de correo electrónico, en singular, y pidiendo que se devuelvan direcciones de correo electrónico, en plural), y haga clic en "Aceptar", y luego en "Crear".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. Haga clic en el flujo de usuario que creó en la lista y luego en el botón "Ejecutar flujo de usuario".Click on the user flow that you created in the list, then click the 'Run user flow' button.

  10. Esta acción abrirá la hoja para ejecutar el flujo de usuario, seleccione la aplicación de front-end, copie el punto de conexión del flujo de usuario y guárdelo para más adelante.This action will open the run user flow blade, select the frontend application, copy the user flow endpoint and save it for later.

  11. Copie y guarde el vínculo de la parte superior, registrándolo como "punto de conexión de configuración de OpenID conocido" para su uso posterior.Copy and store the link at the top, recording as the 'well-known openid configuration endpoint' for later use.

    Nota

    Las directivas de B2C permiten exponer los puntos de conexión de inicio de sesión de Azure AD B2C para poder capturar diferentes componentes de datos e iniciar la sesión de los usuarios de diferentes maneras.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.

    En este caso, se ha configurado un flujo de inicio de registro o de inicio de sesión (directiva).In this case we configured a sign up or sign in flow (policy). Esto también expuso un punto conexión de configuración conocido, en ambos casos nuestra directiva creada se identificó en la dirección URL mediante el parámetro de cadena de consulta "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.

    Una vez hecho esto tendrá una plataforma de identidad de negocio a consumidor (B2C) funcional para que los usuarios inicien sesión en varias aplicaciones.Once this is done, you now have a functional Business to Consumer identity platform that will sign users into multiple applications.

Compilación de la API de funciónBuild the function API

  1. Vuelva a cambiar al inquilino de Azure AD estándar en Azure Portal para poder configurar de nuevo los elementos de la suscripción.Switch back to your standard Azure AD tenant in the Azure portal so we can configure items in your subscription again.

  2. Vaya a la hoja Aplicaciones de funciones de Azure Portal, abra la aplicación de función vacía y haga clic en "Functions". Luego, haga clic en "Agregar".Go to the Function Apps blade of the Azure portal, open your empty function app, then click 'Functions', click 'Add'.

  3. En el desplegable que aparece, elija "Desarrollar en el portal", en "Seleccionar una plantilla", elija "Desencadenador HTTP" y, en Detalles de la plantilla, póngale el nombre "hello" con el nivel de autorización "Función". Luego, seleccione Agregar.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. Cambie a la hoja Código y prueba y copie y pegue el código de ejemplo siguiente sobre el código existente que aparece.Switch to the Code + Test blade and copy-paste the sample code from below over the existing code that appears.

  5. Seleccione Guardar.Select 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()}");
    }
    
    

    Sugerencia

    El código de la función de script de C# que acaba de pegar simplemente registra una línea en los registros de función y devuelve el texto "Hola mundo" con algunos datos dinámicos (fecha y hora).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. Seleccione "Integración" en la hoja de la izquierda y, a continuación, haga clic en el vínculo HTTP (solicitud) dentro del cuadro "Desencadenador".Select “Integration” from the left-hand blade, then click the http (req) link inside the 'Trigger' box.

  7. En la lista desplegable "Métodos HTTP seleccionados", desactive el método HTTP POST, dejando solo seleccionado GET, y haga clic en Guardar.From the 'Selected HTTP methods' dropdown, uncheck the http POST method, leaving only GET selected, then click Save.

  8. Vuelva a la pestaña Código y prueba, haga clic en "Obtener la dirección URL de la función" y, a continuación, copie la dirección URL que aparece y guárdela para más adelante.Switch back to the Code + Test tab, click 'Get Function URL', then copy the URL that appears and save it for later.

    Nota

    Los enlaces que acaba de crear simplemente indican a las funciones que respondan a solicitudes HTTP GET anónimas a la dirección URL que acaba de copiar (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). Ahora tenemos una API HTTPS sin servidor escalable capaz de devolver una carga muy sencilla.Now we have a scalable serverless https API, that is capable of returning a very simple payload.

    Ahora puede probar a llamar a esta API desde un explorador web utilizando su versión de la dirección URL anterior que acaba de copiar y guardar.You can now test calling this API from a web browser using your version of the URL above that you just copied and saved. También puede quitar la parte "?code=secretkey" de los parámetros de la cadena de consulta de la dirección URL y probar de nuevo para comprobar que Azure Functions devolverá un error 401.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.

Configuración y protección de la API de funciónConfigure and secure the function API

  1. Es necesario configurar dos áreas adicionales en la aplicación de funciones (restricciones de autenticación y de red).Two extra areas in the function app need to be configured (Authorization and Network Restrictions).

  2. En primer lugar, vamos a configurar la autenticación y la autorización, así que vuelva a la hoja raíz de la aplicación de funciones a través de la ruta de navegación.Firstly Let's configure Authentication / Authorization, so navigate back to the root blade of the function app via the breadcrumb.

  3. A continuación, seleccione "Autenticación/autorización" (en "Configuración").Next select 'Authentication / Authorization' (under 'Settings').

  4. Active la característica de autenticación de App Service.Turn on the App Service Authentication feature.

  5. Establezca la acción que desea realizar cuando la solicitud no se autentique en el cuadro desplegable "Iniciar sesión con Azure Active Directory".Set the Action to take when request is not authenticated dropdown to "Log in with Azure Active Directory".

  6. En "Proveedores de autenticación", elija "Azure Active Directory".Under 'Authentication Providers', choose ‘Azure Active Directory’.

  7. Elija "Opciones avanzadas" en el conmutador Modo de administración.Choose ‘Advanced’ from the Management Mode switch.

  8. Pegue el identificador de cliente de la aplicación de back-end [Aplicación] (de Azure AD B2C) en el cuadro "Id. de cliente".Paste the Backend application's [Application] Client ID (from Azure AD B2C) into the ‘Client ID’ box

  9. Pegue el punto de conexión de configuración OpenID conocido de la directiva de registro y inicio de sesión en el cuadro URL del emisor (hemos registrado esta configuración anteriormente).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. Haga clic en "Mostrar secreto" y pegue el secreto de cliente de la aplicación de back-end en el cuadro correspondiente.Click 'Show Secret' and paste the Backend application's client secret into the appropriate box.

  11. Seleccione Aceptar para volver a la pantalla o la hoja de selección del proveedor de identidades.Select OK, which takes you back to the identity provider selection blade/screen.

  12. Deje el Almacén de tokens habilitado en la configuración avanzada (valor predeterminado).Leave Token Store enabled under advanced settings (default).

  13. Haga clic en "Guardar" (en la parte superior de la hoja).Click 'Save' (at the top left of the blade).

    Importante

    Ahora, la API de Function está implementada, por lo que debe generar respuestas 401 si no se proporciona el JWT correcto como encabezado Autorización: Portador y devolver datos cuando se presente una solicitud correcta.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.
    Ha agregado una medida de seguridad de defensa en profundidad adicional en EasyAuth configurando la opción "Login With Azure AD" (Inicio de sesión con Azure AD) para administrar las solicitudes no autenticadas.You added additional defense-in-depth security in EasyAuth by configuring the 'Login With Azure AD' option to handle unauthenticated requests. Tenga en cuenta que esto cambiará el comportamiento de las solicitudes no autorizadas entre la aplicación BackEnd Function y la SPA Frontend, ya que EasyAuth emitirá un redireccionamiento 302 a AAD en lugar de una respuesta 401 no autorizada. Corregiremos este comportamiento más adelante con API Management.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.

    Sin embargo, aún no hemos aplicado la seguridad IP. Si tiene una clave válida y un token de OAuth2, cualquiera puede realizar la llamada desde cualquier lugar (lo ideal sería exigir que todas las solicitudes lleguen a través de 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.

    Si usa el nivel de consumo de APIM, no hay una dirección IP virtual de Azure API Management dedicada para la lista de permitidos con las funciones de restricción de acceso.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. En la SKU Estándar de Azure API Management Standard y superiores, la IP virtual es de un solo inquilino y para toda la vigencia del recurso.In the Azure API Management Standard SKU and above the VIP is single tenant and for the lifetime of the resource. En el nivel Consumo de Azure API Management, puede bloquear las llamadas API a través de la clave de función secreta compartida en la parte del URI que copió anteriormente.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. Además, para el nivel Consumo, los pasos 12-17 siguientes no se aplican.Also, for the Consumption tier - steps 12-17 below do not apply.

  14. Cierre la hoja "Autenticación/Autorización".Close the 'Authentication / Authorization' blade

  15. Abra la hoja API Management del portal y, luego, abra su instancia.Open the API Management blade of the portal, then open your instance.

  16. Registre la IP virtual privada que aparece en la pestaña Información general.Record the Private VIP shown on the overview tab.

  17. Vuelva a la hoja Azure Functions del portal y, a continuación, vuelva a abrir su instancia.Return to the Azure Functions blade of the portal then open your instance again.

  18. Seleccione "Redes" y luego "Configuración de las restricciones de acceso".Select 'Networking' and then select 'Configure access restrictions'

  19. Haga clic en "Agregar regla" y escriba la IP virtual copiada en el paso 3 anterior con el formato 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. Si desea seguir interactuando con el portal de funciones y llevar a cabo los pasos opcionales que se indican a continuación, primero debe agregar su propia dirección IP pública o intervalo CIDR.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. Cuando haya una entrada de permiso en la lista, Azure agrega una regla de denegación implícita para bloquear todas las demás direcciones.Once there’s an allow entry in the list, Azure adds an implicit deny rule to block all other addresses.

Deberá agregar bloques de direcciones con formato CIDR al panel restricciones de IP.You'll need to add CIDR formatted blocks of addresses to the IP restrictions panel. Cuando necesite agregar una sola dirección, como la IP virtual de API Management, debe hacerlo en formato 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.

Nota

Ahora la API de función no debería estar accesible por llamada desde otro origen distinto de API Management o su dirección.Now your Function API should not be callable from anywhere other than via API management, or your address.

  1. Abra la hoja API Management y después la instancia.Open the API Management blade, then open your instance.

  2. Seleccione la hoja API (en API).Select the APIs Blade (under APIs).

  3. En el panel "Add a New API" (Agregar una nueva API), elija "Function App" y seleccione "Completo" en la parte superior de la ventana emergente.From the 'Add a New API' pane, choose 'Function App', then select 'Full' from the top of the popup.

  4. Haga clic en Examinar, elija la aplicación de funciones que hospede la API y haga clic en Seleccionar.Click Browse, choose the function app you're hosting the API inside, and click select. A continuación, haga clic en Seleccionar de nuevo.Next, click select again.

  5. Proporciónele un nombre a la API y una descripción para uso interno de API Management y agréguelos al producto "Unlimited" (Ilimitado).Give the API a name and description for API Management's internal use and add it to the ‘unlimited’ Product.

  6. Copie y registre la "URL base" de la API y haga clic en "Crear".Copy and record the API's 'base URL' and click 'create'.

  7. Haga clic en la pestaña "Configuración" y, a continuación, en Suscripción. Desactive la casilla "Suscripción necesaria", ya que usaremos el token de JWT de OAuth en este caso para limitar la frecuencia.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. Tenga en cuenta que, si usa el nivel Consumo, esto seguirá siendo necesario en un entorno de producción.Note that if you are using the consumption tier, this would still be required in a production environment.

    Sugerencia

    Si usa el nivel Consumo de APIM, el producto ilimitado no estará disponible de forma inmediata.If using the consumption tier of APIM the unlimited product won't be available as an out of the box. Tendrá que ir a "Productos" en "API" y presionar "Agregar".Instead, navigate to "Products" under "APIs" and hit "Add".
    Escriba "Ilimitado" como nombre y descripción del producto y seleccione la API que acaba de agregar en la llamada "+" de API en la parte inferior izquierda de la pantalla.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. Seleccione la pestaña "Publicadas".Select the "published" checkbox. Deje el resto tal como está.Leave the rest as default. Por último, pulse el botón "Crear".Finally, hit the "create" button. Esto creó el producto "ilimitado" y lo asignó a su API.This created the "unlimited" product and assigned it to your API. Puede personalizar el nuevo producto más adelante.You can customize your new product later.

Configuración y captura de la configuración correcta del punto de conexión de almacenamientoConfigure and capture the correct storage endpoint settings

  1. Abra la hoja Cuentas de almacenamiento en Azure Portal.Open the storage accounts blade in the Azure portal

  2. Seleccione la cuenta que ha creado y la hoja "Sitio web estático" en la sección Configuración (si no ve la opción "Sitio web estático", compruebe que creó una cuenta V2).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. Establezca la característica de hospedaje web estático en "Habilitado" y dele a documento de índice el nombre "index.html". Después, haga clic en "Guardar".Set the static web hosting feature to 'enabled', and set the index document name to 'index.html', then click 'save'.

  4. Anote el contenido del punto de conexión principal para más adelante, ya que esta ubicación es donde se hospedará el sitio de front-end.Note down the contents of the 'Primary Endpoint' for later, as this location is where the frontend site will be hosted.

    Sugerencia

    Puede usar Azure Blob Storage + reescritura de la red CDN, o Azure App Service para hospedar la aplicación de página única, pero la característica de hospedaje de sitios web estáticos de Blob Storage proporciona un contenedor predeterminado que sirve contenido/html/JS/css web estático de Azure Storage e infiere una página predeterminada para que no tengamos que hacer nada.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.

Configuración de las directivas CORS y validate-jwtSet up the CORS and validate-jwt policies

Se deben seguir las siguientes secciones independientemente del nivel de APIM que se use.The following sections should be followed regardless of the APIM tier being used. La dirección URL de la cuenta de almacenamiento es de la cuenta de almacenamiento que estará disponible a raíz de los requisitos previos de la parte superior de este artículo.The storage account URL is from the storage account you will have made available from the prerequisites at the top of this article.

  1. Cambie a la hoja API Management del portal y abra su instancia.Switch to the API management blade of the portal and open your instance.

  2. Seleccione API y, a continuación, "Todas las API".Select APIs, then select “All APIs”.

  3. En "Procesamiento de entrada", haga clic en el botón de vista Código "</>" para mostrar el editor de directivas.Under "Inbound processing", click the code view button "</>" to show the policy editor.

  4. Edite la sección de entrada y pegue el código XML siguiente para que sea similar al siguiente.Edit the inbound section and paste the below xml so it reads like the following.

  5. Sustituya los siguientes parámetros en la directiva.Replace the following parameters in the Policy

  6. {PrimaryStorageEndpoint} (El punto de conexión de almacenamiento principal que copió en la sección anterior), {b2cpolicy-Well-Known-OpenID} (el "punto de conexión de configuración de OpenID conocido" que copió anteriormente) y {backend-API-Application-Client-ID} (el identificador de cliente/aplicación B2C para la API de back-end) con los valores correctos guardados anteriormente.{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. Si usa el nivel Consumo de API Management, debe quitar ambas directivas de limitar la tasa de llamadas por clave, ya que esta directiva no está disponible cuando se usa el nivel Consumo de 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>
    

    Nota

    Ahora, Azure API Management podrá responder a las solicitudes de origen cruzado desde las aplicaciones de página única de JavaScript y realizará la limitación, la limitación de velocidad y la validación previa del token de autenticación JWT que se pasa ANTES de reenviar la solicitud a la API de función.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.

    Enhorabuena, ahora tiene Azure AD B2C, API Management y Azure Functions trabajando juntos para publicar, proteger y consumir una API.Congratulations, you now have Azure AD B2C, API Management and Azure Functions working together to publish, secure AND consume an API!

    Sugerencia

    Si usa el nivel Consumo de API Management, en lugar de la limitación de velocidad por el sujeto de JWT o la dirección IP entrante (actualmente no se admite la directiva de limitar la tasa de llamadas por clave para el nivel "Consumo"), puede limitar por la cuota de tasa de llamadas, (consulte aquí).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.
    Como este ejemplo es una aplicación JavaScript de página única, la clave de API Management solo se usa para las llamadas de facturación y de limitación de velocidad.As this example is a JavaScript Single Page Application, we use the API Management Key only for rate-limiting and billing calls. La autenticación y la autorización reales se administran mediante Azure AD B2C y se encapsulan en JWT, que se valida dos veces, una desde API Management y, a continuación, desde la función de Azure de backend.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.

Carga del ejemplo de aplicación de página única de JavaScript en el almacenamiento estáticoUpload the JavaScript SPA sample to static storage

  1. Todavía en la hoja de la cuenta de almacenamiento, seleccione la hoja "Contenedores" en la sección Blob service y haga clic en el contenedor $web que aparece en el panel derecho.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. Guarde el código siguiente en un archivo de la máquina como index.html y cargue este archivo en el contenedor $web.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. Vaya al punto de conexión principal del sitio web estático que almacenó en la última sección.Browse to the Static Website Primary Endpoint you stored earlier in the last section.

    Nota

    Enhorabuena, acaba de implementar una aplicación de página única de JavaScript para el hospedaje de contenido estático de Azure Storage.Congratulations, you just deployed a JavaScript Single Page App to Azure Storage Static content hosting.
    Dado que no hemos configurado la aplicación JS con los detalles de Azure AD B2C aún, la página no funcionará todavía si la abre.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.

Configuración de la aplicación de página única de JavaScript SPA para Azure AD B2CConfigure the JavaScript SPA for Azure AD B2C

  1. Ahora sabemos dónde está todo: podemos configurar la aplicación de página única con la dirección de API de API Management adecuada y los identificadores de aplicación y de cliente de Azure AD B2C correctos.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. Vuelva a la hoja de almacenamiento de Azure Portal.Go back to the Azure portal storage blade
  3. Seleccione "Contenedores" (en "Configuración").Select 'Containers' (under 'Settings')
  4. Seleccione el contenedor "$web" en la lista.Select the '$web' container from the list
  5. Seleccione el blob index.html en la lista.Select index.html blob from the list
  6. Haga clic en "Editar".Click 'Edit'
  7. Actualice los valores de autenticación en la sección de configuración de msal para que coincida con la aplicación de front-end que registró anteriormente en B2C.Update the auth values in the msal config section to match your front-end application you registered in B2C earlier. Use los comentarios de código para ver sugerencias sobre el aspecto que deberían tener los valores de configuración.Use the code comments for hints on how the config values should look. El valor de autoridad debe tener el formato https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantname}.onmicrosoft.com}/{signupandsigninpolicyname}.Si ha usado los nombres de ejemplo y el inquilino de B2C se llama "contoso", se espera que la autoridad sea "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. Establezca los valores de la API para que coincidan con la dirección del back-end (la URL base de API que registró anteriormente, y los valores de "b2cScopes" se registraron anteriormente para la aplicación de back-end).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. Haga clic en GuardarClick Save

Establecimiento de los URI de redireccionamiento para la aplicación de front-end de Azure AD B2CSet the redirect URIs for the Azure AD B2C frontend app

  1. Abra la hoja Azure AD B2C y vaya al registro de la aplicación JavaScript de front-end.Open the Azure AD B2C blade and navigate to the application registration for the JavaScript Frontend Application.

  2. Haga clic en "URI de redireccionamiento" y elimine el marcador de posición "https://jwt.ms" que se especificó anteriormente.Click 'Redirect URIs' and delete the placeholder 'https://jwt.ms' we entered earlier.

  3. Agregue un nuevo URI para el punto de conexión principal (almacenamiento) (sin la barra diagonal final).Add a new URI for the primary (storage) endpoint (minus the trailing forward slash).

    Nota

    Esta configuración hará que un cliente de la aplicación de front-end reciba un token de acceso con las notificaciones adecuadas de 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.
    La aplicación de página única podrá agregarlo como token de portador al encabezado HTTPS en la llamada a la API de back-end.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 validará previamente el token, limitará la frecuencia de las llamadas al punto de conexión por el sujeto del JWT emitido por el identificador de Azure (el usuario) y por la dirección IP del autor de la llamada (en función del nivel de servicio de API Management, consulte la nota anterior) antes de pasar la solicitud a la API de Azure Functions de recepción, agregando la clave de seguridad.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.
    La aplicación de página única representará la respuesta en el explorador.The SPA will render the response in the browser.

    Enhorabuena, ha configurado Azure AD B2C, Azure API Management, Azure Functions y la autorización de Azure App Service para que trabajen en perfecta armonía.Congratulations, you’ve configured Azure AD B2C, Azure API Management, Azure Functions, Azure App Service Authorization to work in perfect harmony!

Ahora tenemos una aplicación sencilla con una API segura sencilla, vamos a probarla.Now we have a simple app with a simple secured API, let's test it.

Prueba de la aplicación clienteTest the client application

  1. Abra la dirección URL de la aplicación de ejemplo que anotó de la cuenta de almacenamiento que creó anteriormente.Open the sample app URL that you noted down from the storage account you created earlier.
  2. Haga clic en "Iniciar sesión" en la esquina superior derecha, lo que hará que aparezca su perfil de registro o de inicio de sesión de Azure AD B2C emergente.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. La aplicación debería darte la bienvenida por su nombre de perfil B2C.The app should welcome you by your B2C profile name.
  4. Ahora haga clic en "Llamar a API" y la página debería actualizarse con los valores devueltos desde la API protegida.Now Click "Call API" and the page should update with the values sent back from your secured API.
  5. Si hace clic repetidamente en el botón Llamar a API y ejecuta en el nivel de desarrollador o superior de API Management, debe tener en cuenta que su solución comenzará a limitar la frecuencia de la API y esta característica debe notificarse en la aplicación con un mensaje adecuado.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.

Y hemos terminadoAnd we're done

Los pasos anteriores se pueden adaptar y editar para permitir gran cantidad de usos diferentes de Azure AD B2C con API Management.The steps above can be adapted and edited to allow many different uses of Azure AD B2C with API Management.

Pasos siguientesNext steps