Partilhar via


Configurar um provedor de email personalizado para eventos de envio de senha única (visualização)

Aplica-se a:Círculo branco com um símbolo X cinzento. Locatários da força deCírculo verde com um símbolo de marca de verificação branco. trabalho Locatários externos (saiba mais)

Este artigo fornece um guia sobre como configurar e configurar um provedor de email personalizado para o tipo de evento Enviar OTP (One Time Passcode). O evento é acionado quando um e-mail OTP é ativado, ele permite que você chame uma API REST para usar seu próprio provedor de e-mail chamando uma API REST.

Gorjeta

Experimentar agora

Para experimentar esse recurso, vá para a demonstração do Woodgrove Groceries e inicie o caso de uso "Use a custom Email Provider for One Time code".

Pré-requisitos

Etapa 1: Criar um aplicativo do Azure Function

Esta seção mostra como configurar um aplicativo do Azure Function no portal do Azure. A função API é a porta de entrada para o seu provedor de e-mail. Você cria um aplicativo Azure Function para hospedar a função de gatilho HTTP e define as configurações na função.

Gorjeta

As etapas neste artigo podem variar ligeiramente com base no portal a partir do qual você começou.

  1. Entre no portal do Azure como pelo menos um Administrador de Aplicativo e Administrador de Autenticação.

  2. A partir do menu do portal do Azure ou a partir da Home page, selecione Criar um recurso.

  3. Procure e selecione Função App e selecione Criar.

  4. Na página Criar Aplicativo de Função, selecione Consumo e, em seguida, Selecionar.

  5. Na página Criar Aplicativo de Função (Consumo), na guia Noções básicas, crie um aplicativo de função usando as configurações especificadas na tabela a seguir:

    Definição Valor sugerido Description
    Subscrição a sua subscrição A assinatura sob a qual o novo aplicativo de função é criado.
    Grupo de Recursos myResourceGroup Selecione o grupo de recursos usado para configurar os recursos do Serviço de Comunicações do Azure e do Serviço de Comunicação por Email como parte dos pré-requisitos
    Nome da Aplicação de Funções Nome globalmente exclusivo Um nome que identifica o novo aplicativo de função. Os carateres válidos são a-z (não sensível a maiúsculas e minúsculas), 0-9 e -.
    Implantar código ou imagem de contêiner Código Opção para publicar ficheiros de código ou um contentor de Docker. Para este tutorial, selecione Código.
    Pilha de runtime .NET A sua linguagem de programação preferida. Para este tutorial, selecione .NET.
    Versão 8 (LTS) Em processo Versão do tempo de execução 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 preferida Selecione uma região perto de você ou perto de outros serviços que suas funções possam acessar.
    Sistema operativo Windows O sistema operacional é pré-selecionado para você com base na seleção da pilha de tempo de execução.
  6. Selecione Rever + criar para rever as seleções de configuração da aplicação e, em seguida, selecione Criar. A implantação leva alguns minutos.

  7. Depois de implantado, selecione Ir para o recurso para exibir seu novo aplicativo de função.

1.1 Criar uma função de gatilho HTTP

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

  1. No seu aplicativo de funções, no menu, selecione Funções.
  2. Selecione Criar função.
  3. Na janela Criar função, em Selecionar um modelo, procure e selecione o modelo de gatilho HTTP. Selecione Seguinte.
  4. Em Detalhes do modelo, insira CustomAuthenticationExtensionsAPI para a propriedade Function Name .
  5. Para o nível de autorização, selecione Função.
  6. Selecione Criar.

1.2 Editar a função

O código começa com a leitura do objeto JSON de entrada. O Microsoft Entra ID envia o objeto JSON para sua API. Neste exemplo, ele lê o endereço de e-mail (identificador) e a OTP. Em seguida, o código envia os detalhes para o serviço de comunicações para enviar o e-mail usando um modelo dinâmico.

Este guia de instruções demonstra o evento de envio de OTP usando os Serviços de Comunicação do Azure e o SendGrid. Use as guias para selecionar sua implementação.

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

  2. Substitua o código inteiro pelo trecho de código a seguir.

    using System.Dynamic;
    using System.Text.Json;
    using System.Text.Json.Nodes;
    using System.Text.Json.Serialization;
    using Azure.Communication.Email;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Http.HttpResults;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace Company.AuthEvents.OnOtpSend.CustomEmailACS
    {
        public class CustomEmailACS
        {
            private readonly ILogger<CustomEmailACS> _logger;
    
            public CustomEmailACS(ILogger<CustomEmailACS> logger)
            {
                _logger = logger;
            }
    
            [Function("OnOtpSend_CustomEmailACS")]
            public async Task<IActionResult> RunAsync([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
            {
                _logger.LogInformation("C# HTTP trigger function processed a request.");
    
                // Get the request body
                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
                JsonNode jsonPayload = JsonNode.Parse(requestBody)!;
    
                // Get OTP and mail to
                string emailTo = jsonPayload["data"]!["otpContext"]!["identifier"]!.ToString();
                string otp = jsonPayload["data"]!["otpContext"]!["onetimecode"]!.ToString();
    
                // Send email
                await SendEmailAsync(emailTo, otp);
    
                // Prepare response
                ResponseObject responseData = new ResponseObject("microsoft.graph.OnOtpSendResponseData");
                responseData.Data.Actions = new List<ResponseAction>() { new ResponseAction(
                    "microsoft.graph.OtpSend.continueWithDefaultBehavior") };
    
                return new OkObjectResult(responseData);
            }
    
            private async Task SendEmailAsync(string emailTo, string code)
            {
                // Get app settings
                var connectionString = Environment.GetEnvironmentVariable("mail_connectionString");
                var sender = Environment.GetEnvironmentVariable("mail_sender");
                var subject = Environment.GetEnvironmentVariable("mail_subject");
    
                try
                {
                    if (!string.IsNullOrEmpty(connectionString))
                    {
                        var emailClient = new EmailClient(connectionString);
                        var body = EmailTemplate.GenerateBody(code);
    
                        _logger.LogInformation($"Sending OTP to {emailTo}");
    
                        EmailSendOperation emailSendOperation = await emailClient.SendAsync(
                        Azure.WaitUntil.Started,
                        sender,
                        emailTo,
                        subject,
                        body);
                    }
                }
                catch (System.Exception ex)
                {
                    _logger.LogError(ex.Message);
                }
            }
        }
    
        public class ResponseObject
        {
            [JsonPropertyName("data")]
            public Data Data { get; set; }
    
            public ResponseObject(string dataType)
            {
                Data = new Data(dataType);
            }
        }
    
        public class Data
        {
            [JsonPropertyName("@odata.type")]
            public string DataType { get; set; }
            [JsonPropertyName("actions")]
            public List<ResponseAction> Actions { get; set; }
    
            public Data(string dataType)
            {
                DataType = dataType;
            }
        }
    
        public class ResponseAction
        {
            [JsonPropertyName("@odata.type")]
            public string DataType { get; set; }
    
            public ResponseAction(string dataType)
            {
                DataType = dataType;
            }
        }
    
        public class EmailTemplate
        {
            public static string GenerateBody(string oneTimeCode)
            {
                return @$"<html><body>
                <div style='background-color: #1F6402!important; padding: 15px'>
                    <table>
                    <tbody>
                        <tr>
                            <td colspan='2' style='padding: 0px;font-family: "Segoe UI Semibold", "Segoe UI Bold", "Segoe UI", "Helvetica Neue Medium", Arial, sans-serif;font-size: 17px;color: white;'>Woodgrove Groceries live demo</td>
                        </tr>
                        <tr>
                            <td colspan='2' style='padding: 15px 0px 0px;font-family: "Segoe UI Light", "Segoe UI", "Helvetica Neue Medium", Arial, sans-serif;font-size: 35px;color: white;'>Your Woodgrove verification code</td>
                        </tr>
                        <tr>
                            <td colspan='2' style='padding: 25px 0px 0px;font-family: "Segoe UI", Tahoma, Verdana, Arial, sans-serif;font-size: 14px;color: white;'> To access <span style='font-family: "Segoe UI Bold", "Segoe UI Semibold", "Segoe UI", "Helvetica Neue Medium", Arial, sans-serif; font-size: 14px; font-weight: bold; color: white;'>Woodgrove Groceries</span>'s app, please copy and enter the code below into the sign-up or sign-in page. This code is valid for 30 minutes. </td>
                        </tr>
                        <tr>
                            <td colspan='2' style='padding: 25px 0px 0px;font-family: "Segoe UI", Tahoma, Verdana, Arial, sans-serif;font-size: 14px;color: white;'>Your account verification code:</td>
                        </tr>
                        <tr>
                            <td style='padding: 0px;font-family: "Segoe UI Bold", "Segoe UI Semibold", "Segoe UI", "Helvetica Neue Medium", Arial, sans-serif;font-size: 25px;font-weight: bold;color: white;padding-top: 5px;'>
                            {oneTimeCode}</td>
                            <td rowspan='3' style='text-align: center;'>
                                <img src='https://woodgrovedemo.com/custom-email/shopping.png' style='border-radius: 50%; width: 100px'>
                            </td>
                        </tr>
                        <tr>
                            <td style='padding: 25px 0px 0px;font-family: "Segoe UI", Tahoma, Verdana, Arial, sans-serif;font-size: 14px;color: white;'> If you didn't request a code, you can ignore this email. </td>
                        </tr>
                        <tr>
                            <td style='padding: 25px 0px 0px;font-family: "Segoe UI", Tahoma, Verdana, Arial, sans-serif;font-size: 14px;color: white;'> Best regards, </td>
                        </tr>
                        <tr>
                            <td>
                                <img src='https://woodgrovedemo.com/Company-branding/headerlogo.png' height='20'>
                            </td>
                            <td style='font-family: "Segoe UI", Tahoma, Verdana, Arial, sans-serif;font-size: 14px;color: white; text-align: center;'>
                                <a href='https://woodgrovedemo.com/Privacy' style='color: white; text-decoration: none;'>Privacy Statement</a>
                            </td>
                        </tr>
                    </tbody>
                    </table>
                </div>
                </body></html>";
            }
        }
    }
    
  3. Selecione Obter URL da função e copie o URL da tecla de função, que doravante é usado e referido como {Function_Url}. Feche a função.

Etapa 2: Adicionar cadeias de conexão à Função do Azure

As cadeias de conexão permitem que os SDKs dos Serviços de Comunicação se conectem e se autentiquem no Azure. Para os Serviços de Comunicação do Azure e o SendGrid, você precisará adicionar essas cadeias de conexão ao seu aplicativo Azure Function como variáveis de ambiente.

2.1: Extrair as cadeias de conexão e os pontos de extremidade de serviço do seu recurso dos Serviços de Comunicação do Azure

Você pode acessar suas cadeias de conexão e pontos de extremidade de serviço dos Serviços de Comunicação a partir do portal do Azure ou programaticamente com as APIs do Azure Resource Manager.

  1. Na página inicial no portal do Azure, abra o menu do portal, procure e selecione Todos os recursos.

  2. Procure e selecione o Serviço de Comunicações do Azure criado como parte dos Pré-requisitos deste artigo.

  3. No painel esquerdo, selecione a lista suspensa Configurações e, em seguida, selecione Chaves.

  4. Copie o ponto de extremidade e, da chave primária, copie os valores para chave e cadeia de conexão.

    Captura de ecrã da página Chaves de Serviço de Comunicações do Azure a mostrar as localizações dos pontos finais e das chaves.

2.2: Adicionar as cadeias de conexão à Função do Azure

  1. Navegue de volta para a Função do Azure que você criou em Criar um aplicativo do Azure Function.

  2. Na página Visão geral do seu aplicativo de função, no menu à esquerda, selecione Configurações>As variáveis de ambiente adicionam as seguintes configurações do aplicativo. Depois que todas as configurações forem adicionadas, selecione Aplicar e, em seguida , Confirmar.

    Definição Valor (exemplo) Description
    mail_connectionString A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u A chave primária dos Serviços de Comunicação do Azure.
    mail_sender from.email@myemailprovider.com O endereço de e-mail de origem.
    mail_subject Demonstração do CIAM O assunto do e-mail.

Etapa 3: Registrar uma extensão de autenticação personalizada

Nesta etapa, você configura uma extensão de autenticação personalizada, que o Microsoft Entra ID usa para chamar sua Função do Azure. A extensão de autenticação personalizada contém informações sobre seu ponto de extremidade da API REST, as declarações que ele analisa da API REST e como autenticar na API REST. Use o portal do Azure ou o Microsoft Graph para registrar um aplicativo para autenticar sua extensão de autenticação personalizada para sua Função do Azure.

Registrar uma extensão de autenticação personalizada

  1. Entre no portal do Azure como pelo menos um Administrador de Aplicativo e Administrador de Autenticação.

  2. Procure e selecione Microsoft Entra ID e selecione Aplicações empresariais.

  3. Selecione Extensões de autenticação personalizadas e, em seguida, selecione Criar uma extensão personalizada.

  4. Em Noções básicas, selecione o tipo de evento EmailOtpSend e selecione Avançar.

    Captura de ecrã do portal do Azure a realçar o evento de envio de OTP de e-mail.

  5. Na guia Configuração do Ponto de Extremidade, preencha as seguintes propriedades e selecione Avançar para continuar.

    • Nome - Um nome para sua extensão de autenticação personalizada. Por exemplo, Email OTP Send.
    • URL de destino - A {Function_Url} URL da sua função do Azure. Navegue até a página Visão geral do seu aplicativo Azure Function e selecione a função que você criou. Na página Visão geral da função, selecione Obter URL da função e use o ícone de cópia para copiar o URL customauthenticationextension_extension (chave do sistema).
    • Descrição - Uma descrição para suas extensões de autenticação personalizadas.
  6. Na guia Autenticação de API, selecione a opção Criar novo registro de aplicativo para criar um registro de aplicativo que represente seu aplicativo de função.

  7. Dê um nome ao aplicativo, por exemplo , API de eventos de autenticação do Azure Functions e selecione Avançar.

  8. Na guia Aplicativos, selecione o aplicativo a ser associado à extensão de autenticação personalizada. Selecione Seguinte. Você tem a opção de aplicá-lo em todo o locatário marcando a caixa. Selecione Seguinte para continuar.

  9. Na guia Revisão, verifique se os detalhes estão corretos para a extensão de autenticação personalizada. Observe a ID do Aplicativo em Autenticação de API, que é necessária para configurar a autenticação para sua Função do Azure em seu aplicativo do Azure Function. Selecione Criar.

Depois que sua extensão de autenticação personalizada for criada, abra o aplicativo no portal em Registros de aplicativo e selecione Permissões de API.

Na página de permissões da API, selecione o botão Conceder consentimento de administrador para "YourTenant" para dar consentimento de administrador ao aplicativo registrado, o que permite que a extensão de autenticação personalizada se autentique em sua API. A extensão de autenticação personalizada usa client_credentials para autenticar no Aplicativo de Função do Azure usando a Receive custom authentication extension HTTP requests permissão.

A captura de tela a seguir mostra como conceder permissões.

Captura de ecrã do portal do Azure e como conceder consentimento de administrador.

Etapa 4: Configurar um aplicativo OpenID Connect para testar com

Para obter um token e testar a extensão de autenticação personalizada, você pode usar o https://jwt.ms aplicativo. É um aplicativo Web de propriedade da Microsoft que exibe o conteúdo decodificado de um token (o conteúdo do token nunca sai do seu navegador).

Siga estas etapas para registrar o aplicativo Web jwt.ms :

4.1 Registar uma aplicação Web de teste

  1. Entre no centro de administração do Microsoft Entra como pelo menos um Administrador de Aplicativos.
  2. Navegue até Registros de aplicativos de identidade>>.
  3. Selecione Novo registo.
  4. Insira um Nome para o aplicativo. Por exemplo, Meu aplicativo de teste.
  5. Em Tipos de conta suportados, selecione Contas somente neste diretório organizacional.
  6. Na lista suspensa Selecione uma plataforma no URI de redirecionamento, selecione Web e digite https://jwt.ms a caixa de texto URL.
  7. Selecione Registrar para concluir o registro do aplicativo.
  8. No registro do aplicativo, em Visão geral, copie a ID do aplicativo (cliente), que é usada posteriormente e chamada de {App_to_sendotp_ID}. No Microsoft Graph, ele é referenciado pela propriedade appId .

A captura de tela a seguir mostra como registrar o aplicativo My Test.

Captura de tela que mostra como selecionar o tipo de conta suportado e redirecionar o URI.

4.1 Obter o ID do aplicativo

No registro do aplicativo, em Visão geral, copie a ID do aplicativo (cliente). O ID do aplicativo é chamado de {App_to_sendotp_ID} nas etapas posteriores. No Microsoft Graph, ele é referenciado pela propriedade appId .

4.2 Ativar fluxo implícito

O aplicativo de teste jwt.ms usa o fluxo implícito. Habilite o fluxo implícito no registro do aplicativo My Test:

  1. Em Gerir, selecione Autenticação.
  2. Em Concessão implícita e fluxos híbridos, marque a caixa de seleção Tokens de ID (usados para fluxos implícitos e híbridos).
  3. Selecione Guardar.

Nota

O aplicativo jwt.ms usa o fluxo implícito para obter um token de ID e é apenas para fins de teste. O fluxo implícito não é recomendado para aplicações de produção. Para aplicativos de produção, use o fluxo de código de autorização.

Etapa 5: Proteger sua função do Azure

A extensão de autenticação personalizada do Microsoft Entra usa o fluxo de servidor para servidor para obter um token de acesso que é enviado no cabeçalho HTTP Authorization para sua função do Azure. Ao publicar sua função no Azure, especialmente em um ambiente de produção, você precisa validar o token enviado no cabeçalho de autorização.

Para proteger sua função do Azure, siga estas etapas para integrar a autenticação do Microsoft Entra, para validar tokens de entrada com seu registro de aplicativo de API de eventos de autenticação do Azure Functions.

Nota

Se o aplicativo de função do Azure estiver hospedado em um locatário do Azure diferente do locatário no qual sua extensão de autenticação personalizada está registrada, pule para a etapa do provedor de identidade OpenID Connect.

  1. Inicie sessão no portal do Azure.
  2. Navegue e selecione o aplicativo de função que você publicou anteriormente.
  3. Selecione Autenticação no menu à esquerda.
  4. Selecione Adicionar provedor de identidade.
  5. No menu suspensoSelecione Microsoft como o provedor de identidade.
  6. Em Registro de aplicativo -> Tipo de registro de aplicativo, selecione Escolher um registro de aplicativo existente neste diretório e escolha o registro de aplicativo de API de eventos de autenticação do Azure Functions que você criou anteriormente ao registrar o provedor de email personalizado.
  7. Adicione a expiração secreta do cliente para o aplicativo.
  8. Em Solicitações não autenticadas, selecione HTTP 401 Não autorizado como o provedor de identidade.
  9. Desmarque a opção Loja de tokens.
  10. Selecione Adicionar para adicionar autenticação à sua Função do Azure.

Captura de tela que mostra como adicionar autenticação ao seu aplicativo de função.

5.1 Usando o provedor de identidade OpenID Connect

Se você configurou o provedor de identidade da Microsoft, ignore esta etapa. Caso contrário, se a Função do Azure estiver hospedada em um locatário diferente do locatário no qual sua extensão de autenticação personalizada está registrada, siga estas etapas para proteger sua função:

  1. Entre no portal do Azure e, em seguida, navegue e selecione o aplicativo de função que você publicou anteriormente.

  2. Selecione Autenticação no painel esquerdo.

  3. Selecione Adicionar provedor de identidade.

  4. Selecione OpenID Connect como o provedor de identidade.

  5. Forneça um nome, como Contoso Microsoft Entra ID.

  6. Na entrada Metadados, insira a seguinte URL para a URL do documento. Substitua o {tenantId} pelo seu ID de locatário do Microsoft Entra e {tenantname} pelo nome do seu locatário sem o 'onmicrosoft.com'.

    https://{tenantname}.ciamlogin.com/{tenantId}/v2.0/.well-known/openid-configuration
    
  7. No Registro do aplicativo, insira a ID do aplicativo (ID do cliente) dos eventos de autenticação do Azure Functions Registro do aplicativo da API que você criou anteriormente.

  8. No centro de administração do Microsoft Entra:

    1. Selecione o registro do aplicativo de API de eventos de autenticação do Azure Functions que você criou anteriormente.
    2. Selecione Certificados & segredos Segredos do>cliente Novo segredo do>cliente.
    3. Adicione uma descrição do segredo do cliente.
    4. Selecione uma expiração para o segredo ou especifique um tempo de vida personalizado.
    5. Selecione Adicionar.
    6. Registre o valor do segredo para uso no código do aplicativo cliente. Este valor secreto nunca mais é apresentado depois de sair desta página.
  9. De volta à Função do Azure, sob o registro do aplicativo, insira o segredo do cliente.

  10. Desmarque a opção Loja de tokens.

  11. Selecione Adicionar para adicionar o provedor de identidade OpenID Connect.

Etapa 6: Testar o aplicativo

Para testar o seu fornecedor de e-mail personalizado, siga estes passos:

  1. Abra um novo navegador privado e navegue e inicie sessão através do seguinte URL.

    https://{tenantname}.ciamlogin.com/{tenant-id}/oauth2/v2.0/authorize?client_id={App_to_sendotp_ID}&response_type=id_token&redirect_uri=https://jwt.ms&scope=openid&state=12345&nonce=12345
    
  2. Substitua {tenant-id} pelo seu ID de inquilino, nome de inquilino ou um dos seus nomes de domínio verificados. Por exemplo, contoso.onmicrosoft.com.

  3. Substitua {tenantname} pelo nome do seu inquilino sem o "onmicrosoft.com".

  4. Substitua {App_to_sendotp_ID} pela ID de registro do aplicativo Meu teste.

  5. Certifique-se de entrar usando uma conta de senha de e-mail único. Em seguida, selecione Enviar código. Certifique-se de que o código enviado para os endereços de e-mail registados utiliza o fornecedor personalizado registado acima.

Etapa 7: Voltar para o Microsoft Provider

Se ocorrer um erro na sua API de extensão, por padrão, o Entra ID não enviará uma OTP para o usuário. Em vez disso, você pode definir o comportamento no erro para retornar ao Microsoft Provider.

Para habilitar isso, execute a seguinte solicitação. Substitua {customListenerOjectId} pelo ID do ouvinte de autenticação personalizado gravado anteriormente.

  • Você precisa da permissão delegada EventListener.ReadWrite.All .
PATCH https://graph.microsoft.com/beta/identity/authenticationEventListeners/{customListenerOjectId}

{
    "@odata.type": "#microsoft.graph.onEmailOtpSendListener",
    "handler": {
        "@odata.type": "#microsoft.graph.onOtpSendCustomExtensionHandler",
        "configuration": {
            "behaviorOnError": {
                "@odata.type": "#microsoft.graph.fallbackToMicrosoftProviderOnError"
            }
        }
    }
}

Consulte também