Criar uma API REST para um evento de início de emissão de token no Azure Functions

Este artigo descreve como criar uma API REST com um evento de início de emissão de token usando o Azure Functions no portal do Azure. Crie um aplicativo do Azure Functions e uma função de gatilho HTTP que possam retornar declarações extras para o token.

Pré-requisitos

Este artigo descreve como criar uma API REST para um evento de início de emissão de token usando a biblioteca NuGet Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents e defina-a para autenticação. Você vai criar uma função de gatilho HTTP no Visual Studio ou Visual Studio Code, configurá-la para autenticação e implantá-la no portal do Azure, onde poderá ser acessada por meio do Azure Functions.

Pré-requisitos

Observação

O biblioteca NuGet Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents está atualmente na versão prévia. As etapas neste artigo estão sujeitas a alterações. Para implementação de disponibilidade geral de um evento de início de emissão de token, você pode fazer isso usando o portal do Azure.

Criar o aplicativo de funções do Azure

No portal do Azure, crie um aplicativo de funções do Azure e seu recurso associado, antes de continuar a criar a função de gatilho HTTP.

  1. Entre no portal do Microsoft Azure como, no mínimo, Administrador de Aplicativos e Administrador de Autenticação.

  2. No menu do portal do Azure ou na Página inicial, selecione Criar um recurso.

  3. Pesquise e selecione Function App e selecione Criar.

  4. Na página Básico, crie um aplicativo de funções usando as configurações especificadas na tabela a seguir:

    Configuração Valor sugerido Descrição
    Assinatura Sua assinatura A assinatura sob a qual o novo aplicativo de funções será criado.
    Grupo de Recursos myResourceGroup Selecione um grupo de recursos existente ou nomeie um novo no qual você criará seu aplicativo de funções.
    Nome do aplicativo de funções Nome globalmente exclusivo Um nome que identifique o novo aplicativo de funções. Os caracteres válidos são a-z (não diferencia maiúsculas de minúsculas), 0-9 e -.
    Implantar código ou imagem de contêiner Código Opção para publicar arquivos de código ou um contêiner do Docker. Para este tutorial, selecione Código.
    Pilha de runtime .NET Sua linguagem de programação preferida. Para este tutorial, selecione .NET.
    Versão 6 (LTS) Em processo Versão do runtime do .NET. Em processo significa que você pode criar e modificar funções no portal, o que é recomendado para este guia
    Região Região preferencial Selecione uma região perto de você ou perto de outros serviços que suas funções podem acessar.
    Sistema operacional Windows O sistema operacional é pré-selecionado para você com base na seleção da pilha de runtime.
    Tipo de plano Consumo (sem servidor) Plano de hospedagem que define como os recursos são alocados para seu aplicativo de funções.
  5. Selecione Examinar + criar para examinar as seleções de configuração do aplicativo e, em seguida, selecione Criar. A implantação leva alguns minutos.

  6. Depois de implantado, selecione Ir para o recurso para visualizar seu novo aplicativo de funções.

Criar uma função de gatilho HTTP

Depois que o aplicativo de funções do Azure for criado, crie uma função de gatilho HTTP dentro do aplicativo. O gatilho HTTP permite invocar uma função com uma solicitação HTTP e é referenciado pela extensão de autenticação personalizada do Microsoft Entra.

  1. Na página Visão geral do seu aplicativo de funções, selecione o painel Funções e selecione Criar função em Criar no portal do Azure.
  2. Na janela Criar Função, deixe a propriedade Ambiente de desenvolvimento como Desenvolver no portal. Em Template, selecione Gatilho HTTP.
  3. Em Detalhes do modelo, insira CustomAuthenticationExtensionsAPI para a propriedade Nova Função.
  4. Para o Nível de autorização, selecione Função.
  5. Selecione Criar. Captura de tela que mostra como escolher o ambiente de desenvolvimento e o modelo.

Editar a função

O código lê o objeto JSON de entrada e o Microsoft Entra ID envia o objeto JSON para sua API. Neste exemplo, ele lê o valor da ID de correlação. Em seguida, o código retorna uma coleção de declarações personalizadas, incluindo o CorrelationId original, o ApiVersion de sua Função do Azure, um DateOfBirth e um CustomRoles que é retornado para o Microsoft Entra ID.

  1. No menu, em Desenvolvedor, selecione Código + Teste.

  2. Substitua todo o código pelo trecho a seguir e, em seguida, selecione Salvar.

    #r "Newtonsoft.Json"
    using System.Net;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    using Newtonsoft.Json;
    public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        dynamic data = JsonConvert.DeserializeObject(requestBody);
    
        // Read the correlation ID from the Microsoft Entra request    
        string correlationId = data?.data.authenticationContext.correlationId;
    
        // Claims to return to Microsoft Entra
        ResponseContent r = new ResponseContent();
        r.data.actions[0].claims.CorrelationId = correlationId;
        r.data.actions[0].claims.ApiVersion = "1.0.0";
        r.data.actions[0].claims.DateOfBirth = "01/01/2000";
        r.data.actions[0].claims.CustomRoles.Add("Writer");
        r.data.actions[0].claims.CustomRoles.Add("Editor");
        return new OkObjectResult(r);
    }
    public class ResponseContent{
        [JsonProperty("data")]
        public Data data { get; set; }
        public ResponseContent()
        {
            data = new Data();
        }
    }
    public class Data{
        [JsonProperty("@odata.type")]
        public string odatatype { get; set; }
        public List<Action> actions { get; set; }
        public Data()
        {
            odatatype = "microsoft.graph.onTokenIssuanceStartResponseData";
            actions = new List<Action>();
            actions.Add(new Action());
        }
    }
    public class Action{
        [JsonProperty("@odata.type")]
        public string odatatype { get; set; }
        public Claims claims { get; set; }
        public Action()
        {
            odatatype = "microsoft.graph.tokenIssuanceStart.provideClaimsForToken";
            claims = new Claims();
        }
    }
    public class Claims{
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string CorrelationId { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string DateOfBirth { get; set; }
        public string ApiVersion { get; set; }
        public List<string> CustomRoles { get; set; }
        public Claims()
        {
            CustomRoles = new List<string>();
        }
    }
    
  3. No menu superior, selecione Obter URL da função e copie o valor da URL. Essa URL de função pode ser usada ao configurar uma extensão de autenticação personalizada.

Criar e compilar o aplicativo de funções do Azure

Nesta etapa, você vai criar uma API de função de gatilho HTTP usando seu IDE, instalar os pacotes NuGet necessários e copiar no código de exemplo. Crie o projeto e execute a função para extrair a URL da função local.

Criar o aplicativo

Para criar um aplicativo de funções do Azure, siga estas etapas:

  1. Abra o Visual Studio e selecione Criar um projeto.
  2. Pesquise e selecione Azure Functions e selecione Próximo.
  3. Dê um nome ao projeto, como AuthEventsTrigger. É uma boa ideia combinar o nome da solução com o nome do projeto.
  4. Selecione um local para o projeto. Selecione Avançar.
  5. Selecione NET 6.0 (suporte a longo prazo) como a estrutura de destino.
  6. Selecione Gatilho HTTP como o tipo de Função e defina o Nível de autorização como Função. Selecione Criar.
  7. No Gerenciador de Soluções, renomeie o arquivo Function1.cs como AuthEventsTrigger.cs e aceite a sugestão de alteração de renomeação.

Instalar pacotes Do NuGet e compilar o projeto

Depois de criar o projeto, você precisará instalar os pacotes NuGet necessários e compilar o projeto.

  1. No menu superior do Visual Studio, selecione Projeto e, em seguida, Gerenciar pacotes NuGet.
  2. Selecione a guia Procurar e, em seguida, pesquise e selecione Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents no painel direito. Selecione Instalar.
  3. Aplique e aceite as alterações nos pop-ups exibidos.

Adicione o código de amostra

A API de função é a origem de declarações extras para o token. Para fins deste artigo, estamos codificando os valores para o aplicativo de amostra. Em produção, você pode buscar informações sobre o usuário no armazenamento de dados externo. Consulte a Classe WebJobsAuthenticationEventsContext para propriedades existentes.

No arquivo AuthEventsTrigger.cs, substitua todo o conteúdo do arquivo pelo seguinte código:

using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents.TokenIssuanceStart;
using Microsoft.Azure.WebJobs.Extensions.AuthenticationEvents;

namespace AuthEventsTrigger
{
    public static class AuthEventsTrigger
    {
        [FunctionName("onTokenIssuanceStart")]
        public static WebJobsAuthenticationEventResponse Run(
            [WebJobsAuthenticationEventsTrigger] WebJobsTokenIssuanceStartRequest request, ILogger log)
        {
            try
            {
                // Checks if the request is successful and did the token validation pass
                if (request.RequestStatus == WebJobsAuthenticationEventsRequestStatusType.Successful)
                {
                    // Fetches information about the user from external data store
                    // Add new claims to the token's response
                    request.Response.Actions.Add(
                        new WebJobsProvideClaimsForToken(
                            new WebJobsAuthenticationEventsTokenClaim("dateOfBirth", "01/01/2000"),
                            new WebJobsAuthenticationEventsTokenClaim("customRoles", "Writer", "Editor"),
                            new WebJobsAuthenticationEventsTokenClaim("apiVersion", "1.0.0"),
                            new WebJobsAuthenticationEventsTokenClaim(
                                "correlationId", 
                                request.Data.AuthenticationContext.CorrelationId.ToString())));
                }
                else
                {
                    // If the request fails, such as in token validation, output the failed request status, 
                    // such as in token validation or response validation.
                    log.LogInformation(request.StatusMessage);
                }
                return request.Completed();
            }
            catch (Exception ex) 
            { 
                return request.Failed(ex);
            }
        }
    }
}

Compilar e executar o projeto localmente

O projeto foi criado, e o código de exemplo foi adicionado. Usando o IDE, precisamos compilar e executar o projeto localmente para extrair a URL da função local.

  1. Navegue até Compilar no menu superior e selecione Compilar solução.
  2. Pressione F5 ou selecione AuthEventsTrigger no menu superior para executar a função.
  3. Copie a URL da função do terminal que aparece ao executar a função. Isso pode ser usado ao configurar uma extensão de autenticação personalizada.

É uma boa ideia testar a função localmente antes de implantá-la no Azure. Podemos usar um corpo JSON fictício que imita a solicitação que o Microsoft Entra ID envia para sua API REST. Use sua ferramenta de teste de API preferida para chamar a função diretamente.

  1. No IDE, abra local.settings.json e substitua o código pelo JSON a seguir. Podemos definir "AuthenticationEvents__BypassTokenValidation" como true para fins de testes locais.

    {
      "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "",
        "AzureWebJobsSecretStorageType": "files",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "AuthenticationEvents__BypassTokenValidation" : true
      }
    }
    
  2. Usando sua ferramenta de teste de API preferencial, crie uma nova solicitação HTTP e defina o método HTTP como POST.

  3. Use o corpo JSON a seguir que imita a solicitação que o Microsoft Entra ID envia para sua API REST.

    {
        "type": "microsoft.graph.authenticationEvent.tokenIssuanceStart",
        "source": "/tenants/aaaabbbb-0000-cccc-1111-dddd2222eeee/applications/00001111-aaaa-2222-bbbb-3333cccc4444",
        "data": {
            "@odata.type": "microsoft.graph.onTokenIssuanceStartCalloutData",
            "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
            "authenticationEventListenerId": "11112222-bbbb-3333-cccc-4444dddd5555",
            "customAuthenticationExtensionId": "22223333-cccc-4444-dddd-5555eeee6666",
            "authenticationContext": {
                "correlationId": "aaaa0000-bb11-2222-33cc-444444dddddd",
                "client": {
                    "ip": "127.0.0.1",
                    "locale": "en-us",
                    "market": "en-us"
                },
                "protocol": "OAUTH2.0",
                "clientServicePrincipal": {
                    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
                    "appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
                    "appDisplayName": "My Test application",
                    "displayName": "My Test application"
                },
                "resourceServicePrincipal": {
                    "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
                    "appId": "00001111-aaaa-2222-bbbb-3333cccc4444",
                    "appDisplayName": "My Test application",
                    "displayName": "My Test application"
                },
                "user": {
                    "companyName": "Casey Jensen",
                    "createdDateTime": "2023-08-16T00:00:00Z",
                    "displayName": "Casey Jensen",
                    "givenName": "Casey",
                    "id": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
                    "mail": "casey@contoso.com",
                    "onPremisesSamAccountName": "Casey Jensen",
                    "onPremisesSecurityIdentifier": "<Enter Security Identifier>",
                    "onPremisesUserPrincipalName": "Casey Jensen",
                    "preferredLanguage": "en-us",
                    "surname": "Jensen",
                    "userPrincipalName": "casey@contoso.com",
                    "userType": "Member"
                }
            }
        }
    }
    
    
  4. Selecione Enviar e você deverá receber uma resposta JSON semelhante à seguinte:

    {
        "data": {
            "@odata.type": "microsoft.graph.onTokenIssuanceStartResponseData",
            "actions": [
                {
                    "@odata.type": "microsoft.graph.tokenIssuanceStart.provideClaimsForToken",
                    "claims": {
                        "customClaim1": "customClaimValue1",
                        "customClaim2": [
                            "customClaimString1",
                            "customClaimString2" 
                        ]
                    }
                }
    
            ]
        }
    }
    

Implantar a função e publicar no Azure

A função precisa ser implantada no Azure usando nosso IDE. Verifique se você está conectado corretamente à sua conta do Azure para que a função possa ser publicada.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione Publicar.

  2. Em Destino, selecione Azure e Próximo.

  3. Selecione Aplicativo de Funções do Azure (Windows) para o Destino específico, selecione Aplicativo de Funções do Azure (Windows) e, em seguida, selecione Próximo.

  4. Na Instância do Function, use a lista suspensa Nome da assinatura para selecionar a assinatura na qual o novo aplicativo de funções será criado.

  5. Selecione onde você deseja publicar o novo aplicativo de funções e selecione Criar Novo.

  6. Na página Aplicativo de funções (Windows), use as configurações do aplicativo de funções conforme especificado na tabela a seguir e selecione Criar.

    Configuração Valor sugerido Description
    Nome Nome globalmente exclusivo Um nome que identifique o novo aplicativo de funções. Os caracteres válidos são a-z (não diferencia maiúsculas de minúsculas), 0-9 e -.
    Assinatura Sua assinatura A assinatura na qual este novo aplicativo de funções será criado.
    Grupo de Recursos myResourceGroup Selecione um grupo de recursos existente ou nomeie um novo no qual você criará seu aplicativo de funções.
    Tipo de plano Consumo (sem servidor) Plano de hospedagem que define como os recursos são alocados para seu aplicativo de funções.
    Localidade Região preferencial Selecione uma região perto de você ou perto de outros serviços que suas funções podem acessar.
    Armazenamento do Azure Sua conta de armazenamento Uma conta de armazenamento do Azure é requerida pelo runtime do Functions. Selecione Novo para configurar uma conta de armazenamento para uso geral.
    Application Insights Default Um recurso do Azure Monitor. Isso é selecionado automaticamente. Selecione aquele que você deseja usar ou configure um novo.
  7. Aguarde alguns instantes para que seu aplicativo de funções seja implantado. Depois que a janela for fechada, selecione Concluir.

  8. Um novo painel Publicar será aberto. Na parte superior, selecione Publicar. Aguarde alguns minutos para que seu aplicativo de funções seja implantado e apareça no portal do Azure.

Configurar a autenticação para o Azure Functions

Há três maneiras de configurar a autenticação para o Azure Functions:

Por padrão, o código foi configurado para autenticação no portal do Azure usando variáveis de ambiente. Use as guias abaixo para selecionar seu método preferido de implementar variáveis de ambiente ou, como alternativa, consulte Autenticação e autorização do serviço do Aplicativo Azure integradas. Para configurar as variáveis de ambiente, use os seguintes valores:

Nome Valor
AuthenticationEvents__AudienceAppId ID do aplicativo da extensão de autenticação personalizada que é definida em Configurar um provedor de declaração personalizado para um evento de emissão de token
AuthenticationEvents__AuthorityUrl • Locatário da força de trabalho https://login.microsoftonline.com/<tenantID>
• Locatário externo https://<mydomain>.ciamlogin.com/<tenantID>
AuthenticationEvents__AuthorizedPartyAppId 99045fe1-7639-4a75-9d4a-577b6ca3810f ou outra entidade autorizada

Configurar a autenticação no portal do Azure usando variáveis de ambiente

  1. Entre no portal do Microsoft Azure como, no mínimo, Administrador de Aplicativos ou Administrador de Autenticação.
  2. Navegue até o aplicativo de funções que você criou e, em Configurações, selecione Configuração.
  3. Em Configurações de aplicativo, selecione Nova configuração de aplicativo e adicione as variáveis de ambiente da tabela e seus valores associados.
  4. Selecione Salvar para salvar as configurações do aplicativo.

Próxima etapa