Proteja APIs sem servidor com o Gerenciamento de API do Azure e o Azure AD B2C para consumo de um SPA

APLICA-SE A: Todas as camadas de gerenciamento de API

Este cenário mostra como configurar sua instância de Gerenciamento de API do Azure para proteger uma API. Usaremos o fluxo do Azure AD B2C SPA (Auth Code + PKCE) para adquirir um token, juntamente com o Gerenciamento de API para proteger um back-end do Azure Functions usando o EasyAuth.

Para obter uma visão geral conceitual da autorização de API, consulte Autenticação e autorização para APIs no Gerenciamento de API.

Objetivos

Vamos ver como o Gerenciamento de API pode ser usado em um cenário simplificado com o Azure Functions e o Azure AD B2C. Você criará um aplicativo JavaScript (JS) chamando uma API que entra em usuários com o Azure AD B2C. Em seguida, você usará os recursos de política validate-jwt, CORS e Rate Limit By Key do Gerenciamento de API para proteger a API de back-end.

Para uma defesa em profundidade, usamos o EasyAuth para validar o token novamente dentro da API de back-end e garantir que o gerenciamento de API seja o único serviço que pode chamar o back-end do Azure Functions.

O que você vai aprender

  • Configuração de um aplicativo de página única e API de back-end no Azure Ative Directory B2C
  • Criação de uma API de back-end do Azure Functions
  • Importação de uma API do Azure Functions para o Gerenciamento de API do Azure
  • Protegendo a API no Gerenciamento de API do Azure
  • Chamando os pontos de extremidade de autorização B2C do Ative Directory do Azure por meio das bibliotecas da plataforma de identidade da Microsoft (MSAL.js)
  • Armazenando um Aplicativo de Página Única HTML / Vanilla JS e servindo-o a partir de um Ponto de Extremidade de Armazenamento de Blob do Azure

Pré-requisitos

Para seguir as etapas neste artigo, você deve ter:

  • Uma Conta de Armazenamento V2 de Uso Geral do Azure (StorageV2) para hospedar o aplicativo de página única JS frontend.
  • Uma instância de Gerenciamento de API do Azure (qualquer camada funcionará, incluindo 'Consumo', no entanto, certos recursos aplicáveis ao cenário completo não estão disponíveis nessa camada (limite de taxa por chave e IP Virtual dedicado), essas restrições são descritas abaixo no artigo, quando apropriado).
  • Um aplicativo vazio do Azure Function (executando o tempo de execução do .NET Core V3.1, em um Plano de Consumo) para hospedar a API chamada
  • Um locatário do Azure AD B2C, vinculado a uma assinatura.

Embora na prática você use recursos na mesma região em cargas de trabalho de produção, para este artigo de instruções a região de implantação não é importante.

Descrição geral

Aqui está uma ilustração dos componentes em uso e do fluxo entre eles quando esse processo for concluído. Componentes em uso e fluxo

Aqui está uma rápida visão geral das etapas:

  1. Crie a Chamada do Azure AD B2C (Frontend, Gerenciamento de API) e os Aplicativos de API com escopos e conceda acesso à API

  2. Crie as políticas de inscrição e entrada para permitir que os usuários entrem com o Azure AD B2C

  3. Configurar o Gerenciamento de API com as novas IDs e chaves de Cliente do Azure AD B2C para Habilitar a autorização de usuário OAuth2 no Console do Desenvolvedor

  4. Criar a API de função

  5. Configure a API de Função para habilitar o EasyAuth com as novas IDs e Chaves de Cliente do Azure AD B2C e bloqueie para APIM VIP

  6. Criar a definição de API no Gerenciamento de API

  7. Configurar o Oauth2 para a configuração da API de Gerenciamento de API

  8. Configure a política CORS e adicione a política validate-jwt para validar o token OAuth para cada solicitação recebida

  9. Crie o aplicativo de chamada para consumir a API

  10. Carregue o exemplo de SPA JS

  11. Configurar o Aplicativo Cliente JS de Exemplo com as novas IDs e chaves do Cliente do Azure AD B2C

  12. Testar o aplicativo cliente

    Gorjeta

    Vamos capturar algumas informações e chaves, etc., enquanto percorremos este documento, você pode achar útil ter um editor de texto aberto para armazenar os seguintes itens de configuração temporariamente.

    ID DO CLIENTE DE BACK-END B2C: CHAVE SECRETA DO CLIENTE DE BACK-END B2C: URI DO ESCOPO DA API DE BACK-END B2C: ID DO CLIENTE DE FRONTEND B2C: URI DO PONTO DE EXTREMIDADE DO FLUXO DE USUÁRIO B2C: PONTO DE EXTREMIDADE OPENID BEM CONHECIDO B2C: NOME DA POLÍTICA B2C: URL Frontendapp_signupandsignin DA FUNÇÃO: URL BASE DA APIM API: URL DO PONTO DE EXTREMIDADE PRIMÁRIO DE ARMAZENAMENTO:

Configurar o aplicativo de back-end

Abra a folha Azure AD B2C no portal e execute as etapas a seguir.

  1. Selecione a guia Registros de aplicativos

  2. Clique no botão 'Novo registo'.

  3. Escolha 'Web' na caixa de seleção Redirecionar URI.

  4. Agora defina o Nome para Exibição, escolha algo exclusivo e relevante para o serviço que está sendo criado. Neste exemplo, usaremos o nome "Aplicativo de back-end".

  5. Use espaços reservados para as urls de resposta, como 'https://jwt.ms' (Um site de decodificação de token de propriedade da Microsoft), atualizaremos essas urls mais tarde.

  6. Certifique-se de ter selecionado a opção "Contas em qualquer provedor de identidade ou diretório organizacional (para autenticar usuários com fluxos de usuários)"

  7. Para este exemplo, desmarque a caixa "Conceder consentimento de administrador", pois não precisaremos de offline_access permissões hoje.

  8. Clique em “Registar”.

  9. Registre o ID do cliente do aplicativo de back-end para uso posterior (mostrado em 'ID do aplicativo (cliente)').

  10. Selecione a guia Certificados e Segredos (em Gerenciar) e clique em 'Novo Segredo do Cliente' para gerar uma chave de autenticação (Aceite as configurações padrão e clique em 'Adicionar').

  11. Ao clicar em 'Adicionar', copie a chave (em 'valor') em algum lugar seguro para uso posterior como o 'Segredo do cliente de back-end' - observe que esta caixa de diálogo é a ÚNICA chance que você terá de copiar essa chave.

  12. Agora selecione a guia Expor uma API (em Gerenciar).

  13. Você será solicitado a definir o URI do AppID, selecionar e registrar o valor padrão.

  14. Crie e nomeie o escopo "Olá" para sua API de função, você pode usar a frase "Olá" para todas as opções entregáveis, gravando o URI de valor de escopo completo preenchido e, em seguida, clique em "Adicionar escopo".

  15. Retorne à raiz da folha do Azure AD B2C selecionando a trilha 'Azure AD B2C' no canto superior esquerdo do portal.

    Nota

    Os escopos do Azure AD B2C são efetivamente permissões dentro de sua API às quais outros aplicativos podem solicitar acesso por meio da folha de acesso à API de seus aplicativos, efetivamente você acabou de criar permissões de aplicativo para sua API chamada.

Configurar o aplicativo frontend

  1. Selecione a guia Registros de aplicativos
  2. Clique no botão 'Novo registo'.
  3. Escolha 'Aplicativo de página única (SPA)' na caixa de seleção Redirecionar URI.
  4. Agora defina o Nome para Exibição e o URI do AppID, escolha algo exclusivo e relevante para o aplicativo Frontend que usará esse registro de aplicativo B2C do Azure Ative Directory. Neste exemplo, você pode usar "Frontend Application"
  5. De acordo com o primeiro registro do aplicativo, deixe a seleção de tipos de conta suportados como padrão (autenticando usuários com fluxos de usuários)
  6. Use espaços reservados para as urls de resposta, como 'https://jwt.ms' (Um site de decodificação de token de propriedade da Microsoft), atualizaremos essas urls mais tarde.
  7. Deixe a caixa de consentimento de administrador de concessão marcada
  8. Clique em “Registar”.
  9. Registre o ID do Cliente do Aplicativo Frontend para uso posterior (mostrado em 'ID do Aplicativo (cliente)').
  10. Alterne para a guia Permissões da API.
  11. Conceda acesso ao aplicativo de back-end clicando em 'Adicionar uma permissão', depois em 'Minhas APIs', selecione o 'Aplicativo de back-end', selecione 'Permissões', selecione o escopo criado na seção anterior e clique em 'Adicionar permissões'
  12. Clique em 'Conceder consentimento de administrador para {tenant} e clique em 'Sim' na caixa de diálogo pop-up. Este pop-up consente que o "Aplicativo Frontend" use a permissão "Olá" definida no "Aplicativo Backend" criado anteriormente.
  13. Todas as permissões agora devem ser exibidas para o aplicativo como um tick verde na coluna de status

Criar um fluxo de usuário "Inscrição e entrada"

  1. Retorne à raiz da folha B2C selecionando a trilha do Azure AD B2C.

  2. Mude para o separador 'Fluxos de Utilizador' (Em Políticas).

  3. Clique em "Novo fluxo de usuário"

  4. Escolha o tipo de fluxo de usuário 'Inscrever-se e entrar' e selecione 'Recomendado' e, em seguida, 'Criar'

  5. Dê um nome à política e registre-a para mais tarde. Para este exemplo, você pode usar "Frontendapp_signupandsignin", observe que isso será prefixado com "B2C_1_" para fazer "B2C_1_Frontendapp_signupandsignin"

  6. Em "Provedores de identidade" e "Contas locais", marque "Inscrição por e-mail" (ou "Inscrição com ID de usuário", dependendo da configuração do seu locatário B2C) e clique em OK. Essa configuração ocorre porque registraremos contas B2C locais, não adiando para outro provedor de identidade (como um provedor de identidade social) para usar a conta de mídia social existente de um usuário.

  7. Deixe as configurações de MFA e acesso condicional em seus padrões.

  8. Em 'Atributos e declarações do usuário', clique em 'Mostrar mais...' Em seguida, escolha as opções de declaração que você deseja que seus usuários insiram e retornaram no token. Marque pelo menos 'Nome de exibição' e 'Endereço de e-mail' para coletar, com 'Nome de exibição' e 'Endereços de e-mail' para retornar (preste muita atenção ao fato de que você está coletando endereço de e-mail, singular, e pedindo para retornar endereços de e-mail, vários), e clique em 'OK', em seguida, clique em 'Criar'.

  9. Clique no fluxo de usuário que você criou na lista e, em seguida, clique no botão 'Executar fluxo de usuário'.

  10. Essa ação abrirá a folha de fluxo de usuário de execução, selecionará o aplicativo front-end, copiará o ponto de extremidade de fluxo de usuário e salvá-lo-á para mais tarde.

  11. Copie e armazene o link na parte superior, gravando como o 'endpoint de configuração openid bem conhecido' para uso posterior.

    Nota

    As Políticas B2C permitem que você exponha os pontos de extremidade de logon do Azure AD B2C para poder capturar diferentes componentes de dados e entrar em usuários de maneiras diferentes.

    Nesse caso, configuramos um fluxo de inscrição ou entrada (política). Isso também expôs um ponto de extremidade de configuração bem conhecido, em ambos os casos nossa política criada foi identificada na URL pelo parâmetro de cadeia de caracteres de consulta "p=".

    Feito isso, você agora tem uma plataforma funcional de identidade Business to Consumer que conectará os usuários em vários aplicativos.

Criar a API de função

  1. Volte para seu locatário padrão do Microsoft Entra no portal do Azure para que possamos configurar itens em sua assinatura novamente.

  2. Vá para a folha Aplicativos de Função do portal do Azure, abra seu aplicativo de função vazio e clique em 'Funções', clique em 'Adicionar'.

  3. No submenu que aparece, escolha 'Desenvolver no portal', em 'selecionar um modelo' e escolha 'Gatilho HTTP', em Detalhes do modelo, nomeie-o como 'Olá' com nível de autorização 'Função' e, em seguida, selecione Adicionar.

  4. Alterne para a folha Código + Teste e copie e cole o código de exemplo abaixo sobre o código existente exibido.

  5. Selecione Guardar.

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

    Gorjeta

    O código da função de script C# que você acabou de colar simplesmente registra uma linha nos logs de funções e retorna o texto "Hello World" com alguns dados dinâmicos (a data e a hora).

  6. Selecione "Integração" na folha esquerda e, em seguida, clique no link http (req) dentro da caixa 'Gatilho'.

  7. No menu suspenso 'Métodos HTTP selecionados', desmarque o método http POST, deixando apenas GET selecionado, e clique em Salvar.

  8. Volte para a guia Código + Teste, clique em 'Obter URL da função', copie o URL que aparece e salve-o para mais tarde.

    Nota

    As ligações que você acabou de criar simplesmente dizem ao Functions para responder em solicitações http GET anônimas para o URL que você acabou de copiar (https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey). Agora temos uma API https sem servidor escalável, que é capaz de retornar uma carga útil muito simples.

    Agora você pode testar a chamada dessa API a partir de um navegador da Web usando sua versão do URL acima que você acabou de copiar e salvar. Você também pode remover a parte "?code=secretkey" dos parâmetros de cadeia de caracteres de consulta da URL e testar novamente para provar que o Azure Functions retornará um erro 401.

Configurar e proteger a função API

  1. Duas áreas extras no aplicativo de função precisam ser configuradas (Autorização e Restrições de rede).

  2. Em primeiro lugar, vamos configurar a autenticação / autorização, então navegue de volta para a folha raiz do aplicativo de função através da trilha de navegação.

  3. Em seguida, selecione 'Autenticação' (em 'Configurações').

  4. Clique em 'Adicionar provedor de identidade'

  5. Na lista suspensa Provedor de identidade, selecione 'Microsoft'

  6. Para Registro de aplicativo, selecione 'Fornecer os detalhes de um registro de aplicativo existente'

  7. Cole a ID do cliente do aplicativo de back-end (do Azure AD B2C) na caixa 'ID do aplicativo (cliente)' (registramos essa configuração anteriormente).

  8. Cole o ponto de extremidade de configuração de id aberto conhecido da política de inscrição e entrada na caixa URL do emissor (registramos essa configuração anteriormente).

  9. Cole o segredo do cliente do aplicativo de back-end na caixa apropriada (registramos essa configuração anteriormente).

  10. Para 'Solicitações não autenticadas', selecione 'HTTP 401 Não autorizado: recomendado para APIs'

  11. Deixe o Repositório de Tokens ativado (padrão).

  12. Clique em 'Guardar' (no canto superior esquerdo da lâmina).

    Importante

    Agora sua API de função está implantada e deve lançar 401 respostas se o JWT correto não for fornecido como um cabeçalho Authorization: Bearer e deve retornar dados quando uma solicitação válida for apresentada. Você adicionou segurança adicional de defesa profunda no EasyAuth configurando a opção 'Login com ID do Microsoft Entra' para lidar com solicitações não autenticadas.

    Ainda não temos segurança IP aplicada, se você tiver uma chave válida e um token OAuth2, qualquer pessoa pode ligar de qualquer lugar - idealmente, queremos forçar todas as solicitações a vir via Gerenciamento de API.

    Se você estiver usando as camadas Consumo de Gerenciamento de API, Básico v2 e Padrão v2, não haverá um IP Virtual de Gerenciamento de API do Azure dedicado para permitir lista com as restrições de acesso de funções. Nas camadas clássicas (dedicadas) do Gerenciamento de API do Azure, o VIP é um único locatário e representa o tempo de vida do recurso. Para as camadas executadas na infraestrutura compartilhada, você pode bloquear suas chamadas de API por meio da chave de função de segredo compartilhado na parte do URI copiada acima. Além disso, para esses níveis - as etapas 12 a 17 abaixo não se aplicam.

  13. Feche a folha 'Autenticação' no portal Serviço de Aplicativo/Funções.

  14. Abra a folha Gerenciamento de API do portal e abra sua instância.

  15. Grave o VIP privado mostrado na guia de visão geral.

  16. Retorne à folha Azure Functions do portal e abra sua instância novamente.

  17. Selecione 'Rede' e, em seguida, selecione 'Configurar restrições de acesso'

  18. Clique em 'Adicionar Regra' e insira o VIP copiado no passo 3 acima no formato xx.xx.xx.xx/32.

  19. Se você quiser continuar a interagir com o portal de funções, e para executar as etapas opcionais abaixo, você deve adicionar seu próprio endereço IP público ou intervalo CIDR aqui também.

  20. Quando há uma entrada de permissão na lista, o Azure adiciona uma regra de negação implícita para bloquear todos os outros endereços.

Você precisará adicionar blocos de endereços formatados em CIDR ao painel de restrições de IP. Quando você precisar adicionar um único endereço, como o VIP de Gerenciamento de API, precisará adicioná-lo no formato xx.xx.xx.xx/32.

Nota

Agora, sua API de função não deve ser chamada de qualquer outro lugar que não seja por meio do gerenciamento de API ou do seu endereço.

  1. Abra a folha Gerenciamento de API e abra sua instância.

  2. Selecione a lâmina APIs (em APIs).

  3. No painel 'Adicionar uma nova API', escolha 'Aplicativo de função' e, em seguida, selecione 'Completo' na parte superior do pop-up.

  4. Clique em Procurar, escolha o aplicativo de função no qual você está hospedando a API e clique em selecionar. Em seguida, clique em selecionar novamente.

  5. Dê à API um nome e uma descrição para uso interno do Gerenciamento de API e adicione-a ao Produto "ilimitado".

  6. Copie e grave o 'URL base' da API e clique em 'criar'.

  7. Clique na guia 'configurações' e, em seguida, em assinatura - desligue a caixa de seleção 'Assinatura necessária', pois usaremos o token Oauth JWT neste caso para limitar a taxa. Observe que, se você estiver usando a camada de consumo, isso ainda será necessário em um ambiente de produção.

    Gorjeta

    Se estiver usando a camada de consumo do APIM, o produto ilimitado não estará disponível como um produto pronto para uso. Em vez disso, navegue até "Produtos" em "APIs" e clique em "Adicionar". Digite "Unlimited" como o nome e a descrição do produto e selecione a API que você acabou de adicionar no texto explicativo das APIs "+" no canto inferior esquerdo da tela. Marque a caixa de seleção "publicado". Deixe o restante como padrão. Por fim, clique no botão "criar". Isso criou o produto "ilimitado" e o atribuiu à sua API. Pode personalizar o seu novo produto mais tarde.

Configurar e capturar as configurações corretas do ponto de extremidade de armazenamento

  1. Abrir a folha de contas de armazenamento no portal do Azure

  2. Selecione a conta que criou e selecione a folha 'Website estático' na secção Definições (se não vir uma opção 'Website estático', verifique se criou uma conta V2).

  3. Defina o recurso estático de hospedagem na Web como 'habilitado', defina o nome do documento de índice como 'index.html' e clique em 'salvar'.

  4. Anote o conteúdo do 'Ponto de extremidade primário' para mais tarde, pois esse local é onde o site de front-end será hospedado.

    Gorjeta

    Você pode usar o Armazenamento de Blobs do Azure + regravação de CDN ou o Serviço de Aplicativo do Azure para hospedar o SPA, mas o recurso de hospedagem de Site Estático do Armazenamento de Blob nos dá um contêiner padrão para fornecer conteúdo da Web estático / html / js / css do Armazenamento do Azure e inferirá uma página padrão para nós para trabalho zero.

Configurar o CORS e validar políticas jwt

As seções a seguir devem ser seguidas independentemente da camada APIM que está sendo usada. O URL da conta de armazenamento é da conta de armazenamento que você disponibilizou a partir dos pré-requisitos na parte superior deste artigo.

  1. Alterne para a folha de gerenciamento de API do portal e abra sua instância.

  2. Selecione APIs e, em seguida, selecione "Todas as APIs".

  3. Em "Processamento de entrada", clique no botão de visualização de código "</>" para mostrar o editor de políticas.

  4. Edite a seção de entrada e cole o xml abaixo para que ele fique como o seguinte.

  5. Substitua os seguintes parâmetros na Política

  6. {PrimaryStorageEndpoint} (O 'Primary Storage Endpoint' que você copiou na seção anterior), {b2cpolicy-well-known-openid} (O 'endpoint de configuração openid conhecido' que você copiou anteriormente) e {backend-api-application-client-id} (O aplicativo B2C / ID do cliente para a API de back-end) com os valores corretos salvos anteriormente.

  7. Se você estiver usando a camada de Consumo do Gerenciamento de API, deverá remover ambas as políticas de limite de taxa por chave, pois essa política não está disponível ao usar a camada de Consumo do Gerenciamento de API do Azure.

    <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

    Agora, o gerenciamento de API do Azure é capaz de responder a solicitações de origem cruzada de seus aplicativos SPA JavaScript e executará limitação, limitação de taxa e pré-validação do token de autenticação JWT que está sendo passado ANTES de encaminhar a solicitação para a API de Função.

    Parabéns, agora você tem o Azure AD B2C, o Gerenciamento de API e o Azure Functions trabalhando juntos para publicar, proteger E consumir uma API!

    Gorjeta

    Se você estiver usando a camada de consumo de Gerenciamento de API, em vez de limitar a taxa pelo assunto JWT ou pelo endereço IP de entrada (a política Limitar a taxa de chamadas por chave não é suportada atualmente para a camada "Consumo"), você pode Limitar por cota de taxa de chamada veja aqui. Como este exemplo é um aplicativo de página única JavaScript, usamos a chave de gerenciamento de API apenas para chamadas de limite de taxa e cobrança. A Autorização e Autenticação reais são tratadas pelo Azure AD B2C e são encapsuladas no JWT, que é validado duas vezes, uma pelo Gerenciamento de API e, em seguida, pela Função do Azure de back-end.

Carregue o exemplo de SPA JavaScript para armazenamento estático

  1. Ainda na folha da conta de armazenamento, selecione a folha 'Contêineres' na seção Serviço de Blob e clique no contêiner $web que aparece no painel direito.

  2. Salve o código abaixo em um arquivo localmente em sua máquina como index.html e, em seguida, carregue o arquivo index.html para o contêiner $web.

     <!doctype html>
     <html lang="en">
     <head>
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
          <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.11.1/js/msal-browser.min.js"></script>
     </head>
     <body>
          <div class="container-fluid">
              <div class="row">
                  <div class="col-md-12">
                     <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
                         <div class="container-fluid">
                             <a class="navbar-brand" href="#">Azure Active Directory B2C with Azure API Management</a>
                             <div class="navbar-nav">
                                 <button class="btn btn-success" id="signinbtn"  onClick="login()">Sign In</a>
                             </div>
                         </div>
                     </nav>
                  </div>
              </div>
              <div class="row">
                  <div class="col-md-12">
                      <div class="card" >
                         <div id="cardheader" class="card-header">
                             <div class="card-text"id="message">Please sign in to continue</div>
                         </div>
                         <div class="card-body">
                             <button class="btn btn-warning" id="callapibtn" onClick="getAPIData()">Call API</a>
                             <div id="progress" class="spinner-border" role="status">
                                 <span class="visually-hidden">Loading...</span>
                             </div>
                         </div>
                      </div>
                  </div>
              </div>
          </div>
          <script lang="javascript">
                 // Just change the values in this config object ONLY.
                 var config = {
                     msal: {
                         auth: {
                             clientId: "{CLIENTID}", // This is the client ID of your FRONTEND application that you registered with the SPA type in Azure Active Directory B2C
                             authority:  "{YOURAUTHORITYB2C}", // Formatted as https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantguid or full tenant name including onmicrosoft.com}/{signuporinpolicyname}
                             redirectUri: "{StoragePrimaryEndpoint}", // The storage hosting address of the SPA, a web-enabled v2 storage account - recorded earlier as the Primary Endpoint.
                             knownAuthorities: ["{B2CTENANTDOMAIN}"] // {b2ctenantname}.b2clogin.com
                         },
                         cache: {
                             cacheLocation: "sessionStorage",
                             storeAuthStateInCookie: false
                         }
                     },
                     api: {
                         scopes: ["{BACKENDAPISCOPE}"], // The scope that we request for the API from B2C, this should be the backend API scope, with the full URI.
                         backend: "{APIBASEURL}/hello" // The location that we'll call for the backend api, this should be hosted in API Management, suffixed with the name of the API operation (in the sample this is '/hello').
                     }
                 }
                 document.getElementById("callapibtn").hidden = true;
                 document.getElementById("progress").hidden = true;
                 const myMSALObj = new msal.PublicClientApplication(config.msal);
                 myMSALObj.handleRedirectPromise().then((tokenResponse) => {
                     if(tokenResponse !== null){
                         console.log(tokenResponse.account);
                         document.getElementById("message").innerHTML = "Welcome, " + tokenResponse.account.name;
                         document.getElementById("signinbtn").hidden = true;
                         document.getElementById("callapibtn").hidden = false;
                     }}).catch((error) => {console.log("Error Signing in:" + error);
                 });
                 function login() {
                     try {
                         myMSALObj.loginRedirect({scopes: config.api.scopes});
                     } catch (err) {console.log(err);}
                 }
                 function getAPIData() {
                     document.getElementById("progress").hidden = false;
                     document.getElementById("message").innerHTML = "Calling backend ... "
                     document.getElementById("cardheader").classList.remove('bg-success','bg-warning','bg-danger');
                     myMSALObj.acquireTokenSilent({scopes: config.api.scopes, account: getAccount()}).then(tokenResponse => {
                         const headers = new Headers();
                         headers.append("Authorization", `Bearer ${tokenResponse.accessToken}`);
                         fetch(config.api.backend, {method: "GET", headers: headers})
                             .then(async (response)  => {
                                 if (!response.ok)
                                 {
                                     document.getElementById("message").innerHTML = "Error: " + response.status + " " + JSON.parse(await response.text()).message;
                                     document.getElementById("cardheader").classList.add('bg-warning');
                                 }
                                 else
                                 {
                                     document.getElementById("cardheader").classList.add('bg-success');
                                     document.getElementById("message").innerHTML = await response.text();
                                 }
                                 }).catch(async (error) => {
                                     document.getElementById("cardheader").classList.add('bg-danger');
                                     document.getElementById("message").innerHTML = "Error: " + error;
                                 });
                     }).catch(error => {console.log("Error Acquiring Token Silently: " + error);
                         return myMSALObj.acquireTokenRedirect({scopes: config.api.scopes, forceRefresh: false})
                     });
                     document.getElementById("progress").hidden = true;
              }
             function getAccount() {
                 var accounts = myMSALObj.getAllAccounts();
                 if (!accounts || accounts.length === 0) {
                     return null;
                 } else {
                     return accounts[0];
                 }
             }
         </script>
      </body>
     </html>
    
  3. Navegue até o ponto de extremidade primário do site estático que você armazenou anteriormente na última seção.

    Nota

    Parabéns, você acabou de implantar um aplicativo JavaScript de página única na hospedagem de conteúdo estático do Armazenamento do Azure. Como ainda não configuramos o aplicativo JS com seus detalhes do Azure AD B2C, a página ainda não funcionará se você abri-la.

Configurar o SPA JavaScript para Azure AD B2C

  1. Agora sabemos onde tudo está: podemos configurar o SPA com o endereço apropriado da API de Gerenciamento de API e as IDs de aplicativo/cliente do Azure AD B2C corretas.
  2. Voltar à folha de armazenamento do portal do Azure
  3. Selecione 'Contentores' (em 'Definições')
  4. Selecione o recipiente '$web' na lista
  5. Selecione index.html blob na lista
  6. Clique em 'Editar'
  7. Atualize os valores de autenticação na seção de configuração do MSAL para corresponder ao seu aplicativo front-end que você registrou no B2C anteriormente. Use os comentários de código para obter dicas sobre como os valores de configuração devem parecer. O valor da autoridade precisa estar no formato:- https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantname}.onmicrosoft.com}/{signupandsigninpolicyname}, se você usou nossos nomes de exemplo e seu locatário b2c é chamado de 'contoso', então você esperaria que a autoridade fosse 'https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com/Frontendapp_signupandsignin'.
  8. Defina os valores da api para corresponderem ao seu endereço de back-end (A URL base da API que você gravou anteriormente e os valores 'b2cScopes' foram registrados anteriormente para o aplicativo de back-end).
  9. Clicar em Guardar

Definir os URIs de redirecionamento para o aplicativo frontend do Azure AD B2C

  1. Abra a folha Azure AD B2C e navegue até o registro do aplicativo para o Aplicativo Frontend JavaScript.

  2. Clique em 'Redirecionar URIs' e exclua o espaço reservado 'https://jwt.ms' que inserimos anteriormente.

  3. Adicione um novo URI para o ponto de extremidade primário (armazenamento) (menos a barra à direita).

    Nota

    Essa configuração resultará em um cliente do aplicativo frontend recebendo um token de acesso com declarações apropriadas do Azure AD B2C. O SPA poderá adicioná-lo como um token de portador no cabeçalho https na chamada para a API de back-end.

    O Gerenciamento de API pré-validará o token, as chamadas de limite de taxa para o ponto de extremidade pelo assunto do JWT emitido pela ID do Azure (o usuário) e pelo endereço IP do chamador (dependendo da camada de serviço do Gerenciamento de API, consulte a nota acima), antes de passar pela solicitação para a API de Função do Azure de recebimento, adicionando a chave de segurança de funções. O SPA renderizará a resposta no navegador.

    Parabéns, você configurou o Azure AD B2C, o Gerenciamento de API do Azure, o Azure Functions, a Autorização do Serviço de Aplicativo do Azure para trabalhar em perfeita harmonia!

Agora temos um aplicativo simples com uma API segura simples, vamos testá-lo.

Testar o aplicativo cliente

  1. Abra o URL do aplicativo de exemplo que você anotou na conta de armazenamento criada anteriormente.
  2. Clique em "Entrar" no canto superior direito, esse clique exibirá seu perfil de inscrição ou entrada do Azure AD B2C.
  3. O aplicativo deve recebê-lo pelo seu nome de perfil B2C.
  4. Agora clique em "Chamar API" e a página deve ser atualizada com os valores enviados de volta da sua API segura.
  5. Se você clicar repetidamente no botão Chamar API e estiver executando na camada de desenvolvedor ou acima do Gerenciamento de API, observe que sua solução começará a limitar a taxa da API e esse recurso deverá ser relatado no aplicativo com uma mensagem apropriada.

E já lá vamos

As etapas acima podem ser adaptadas e editadas para permitir muitos usos diferentes do Azure AD B2C com Gerenciamento de API.

Próximos passos