Configuración de un proveedor de correo electrónico personalizado para eventos de envío de código de acceso único (versión preliminar)
Se aplica a: inquilinos de personal
inquilinos externos (más información)
En este artículo se proporciona una guía sobre cómo configurar y establecer un proveedor de correo electrónico personalizado para el tipo de evento de envío de código de acceso único (OTP). El evento se desencadena cuando se activa un correo electrónico de OTP, lo que le permite llamar a una API de REST para usar su propio proveedor de correo electrónico mediante una llamada a una API de REST.
Sugerencia
Para probar esta característica, vaya a la demostración de Woodgrove Groceries e inicie el “Caso de uso usar un proveedor de correo electrónico personalizado para código de un solo uso”.
Requisitos previos
- Familiaridad y comprensión de los conceptos descritos en extensiones de autenticación personalizadas.
- Suscripción a Azure. Si no dispone de una cuenta de Azure, puede registrarse para obtener una evaluación gratuita o usar las ventajas de su Visual Studio Subscription cuando cree una cuenta.
- Un inquilino externo de Microsoft Entra ID.
- Para los usuarios de Azure Communications Services;
- Un recurso de Azure Communications Services. Si no tiene uno, cree uno en Inicio rápido: Crear y administrar recursos de Communication Services mediante un grupo de recursos nuevo o existente.
- Un recurso de Azure Email Communication Services creado y listo con un dominio aprovisionado. Si no tiene uno, consulte Inicio rápido: Crear y administrar recursos de Email Communication Service y use el mismo grupo de recursos que Azure Communication Services.
- Un recurso activo de Communication Services conectado a un dominio de correo electrónico. Consulte Inicio rápido: Conexión de un dominio de correo electrónico comprobado
- (Opcional) Enviar un correo electrónico mediante Azure Communication Services para probar el envío de correos electrónicos a los destinatarios deseados mediante Azure Communication Services, al tiempo que se comprueba la configuración de la aplicación para enviar correo electrónico.
- Para los usuarios de SendGrid:
- Una cuenta de SendGrid. Si no tiene una cuenta de SendGrid, empiece por crear una ahora. Para obtener instrucciones de configuración, consulte la sección Creación de una cuenta de SendGrid en Envío de correos electrónicos con SendGrid y Azure.
Paso 1: Creación de una aplicación de funciones de Azure
En esta sección se muestra cómo configurar una aplicación de funciones de Azure en Azure Portal. La API de función es la puerta de enlace al proveedor de correo electrónico. Cree una aplicación de función de Azure para hospedar la función de desencadenador HTTP y configure las opciones de la función.
Sugerencia
Los pasos de este artículo pueden variar ligeramente en función del portal desde donde comienza.
Inicie sesión en Azure Portal como al menos un Administrador de aplicaciones y un Administrador de autenticación.
En el menú o la página Inicio de Azure Portal, seleccione Crear un recurso.
Busque y seleccione Aplicación de funciones y seleccione Crear.
En la página Crear aplicación de funciones, seleccione Consumo y, a continuación, Seleccionar.
En la página Crear aplicación de funciones (consumo), en la pestaña Aspectos básicos, cree una aplicación de funciones con la configuración especificada en la tabla siguiente:
Configuración Valor sugerido Descripción Suscripción Su suscripción Suscripción en la que se creará esta nueva aplicación de función. Grupo de recursos myResourceGroup Seleccione el grupo de recursos que se usa para configurar los recursos de Azure Communications Service y Email Communication Service como parte de los requisitos previos Nombre de la aplicación de función Nombre único globalmente Nombre que identifica la nueva aplicación de funciones. Los caracteres válidos son a-z
(no distingue mayúsculas de minúsculas),0-9
y-
.Implementación de código o imagen de contenedor Código Opción para publicar archivos de código o un contenedor de Docker. Para este tutorial, seleccione Code. Pila en tiempo de ejecución .NET Lenguaje de programación que prefiere. Para este tutorial, seleccione .NET. Versión 8 (LTS) en curso Versión del entorno de ejecución de .NET. En curso indica que puede crear y modificar funciones en el portal, algo que se recomienda para esta guía. Región Región preferida Seleccione una región próxima a usted o a otros servicios a los que accedan las funciones. Sistema operativo Windows El sistema operativo se preselecciona según la selección de la pila en tiempo de ejecución. Seleccione Revisar y crear para revisar la configuración seleccionada para la aplicación y elija Crear. La implementación tarda unos minutos.
Una vez implementada, seleccione Ir al recurso para ver la nueva aplicación de funciones.
1.1 Creación de una función de desencadenador HTTP
Después de crear la aplicación de funciones de Azure, cree una función de desencadenador HTTP. El desencadenador HTTP permite invocar una función con una solicitud HTTP. La extensión de autenticación personalizada de Microsoft Entra hace referencia a este desencadenador HTTP.
- En la aplicación de funciones, seleccione Funciones en el menú.
- Seleccione Crear función.
- En la ventana Crear función, en Seleccione una plantilla, busque y seleccione la plantilla de Desencadenador HTTP. Seleccione Siguiente.
- En Detalles de plantilla, escriba CustomAuthenticationExtensionsAPI para la propiedad Nombre de función.
- En Nivel de autorización, seleccione Función.
- Seleccione Crear.
1.2 Edición de la función
El código comienza leyendo el objeto JSON entrante. Microsoft Entra ID envía el objeto JSON a la API. En este ejemplo, lee la dirección de correo electrónico (identificador) y el OTP. A continuación, el código envía los detalles al servicio de comunicaciones para enviar el correo electrónico mediante una plantilla dinámica.
En esta guía paso a paso se muestra el evento de envío de OTP mediante Azure Communication Services y SendGrid. Use las pestañas para seleccionar la implementación.
En el menú, seleccione Código y prueba.
Reemplace todo el código por el siguiente fragmento.
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>"; } } }
Seleccione Obtener dirección URL de función y copie la dirección URL de Clave de función, que se usará de ahí en adelante y se conocerá como
{Function_Url}
. Cierre la función.
Paso 2: Adición de cadenas de conexión a la función de Azure
Las cadenas de conexión permiten que los SDK de Communication Services se conecten y se autentiquen en Azure. Para Azure Communication Services y SendGrid, deberá agregar estas cadenas de conexión a la aplicación de funciones de Azure como variables de entorno.
2.1: Extracción de las cadenas de conexión y los puntos de conexión de servicio del recurso de Azure Communication Services
Puede acceder a las cadenas de conexión de Communication Services y a los puntos de conexión de servicio desde Azure Portal o mediante programación con las API de Azure Resource Manager.
En la página Inicio de Azure Portal, abra el menú del portal, busque y seleccione Todos los recursos.
Busque y seleccione el Azure Communications Service creado como parte de los Requisitos previos en este artículo.
En el panel izquierdo, seleccione la lista desplegable Configuración y, después, seleccione Claves.
Copie el Punto de conexión y desde clave principal copie los valores de Clave y Cadena de conexión.
2.2: Adición de las cadenas de conexión a la función de Azure
Vuelva a la función de Azure que creó en Crear una aplicación de funciones de Azure.
En la página Información general de la aplicación de funciones, en el menú izquierdo, seleccione Configuración>Variables de entorno agregue la siguiente configuración de la aplicación. Una vez agregadas todas las opciones de configuración, seleccione Aplicary, después, Confirmar.
Configuración Valor (ejemplo) Descripción mail_connectionString https://ciamotpcommsrvc.unitedstates.communication.azure.com/:accesskey=A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u
Punto de conexión de Azure Communication Services mail_sender from.email@myemailprovider.com Desde la dirección de correo electrónico. mail_subject Demostración de CIAM El asunto del correo electrónico.
Paso 3: Registrar una extensión de autenticación personalizada
En este paso, configurará una extensión de autenticación personalizada, que Microsoft Entra ID usa para llamar a la función de Azure. La extensión de autenticación personalizada contiene información sobre el punto de conexión de la API de REST, las notificaciones que analiza desde la API de REST y cómo autenticarse en la API de REST. Use Azure Portal o Microsoft Graph para registrar una aplicación para autenticar la extensión de autenticación personalizada en la función de Azure.
Registrar una extensión de autenticación personalizada
Inicie sesión en Azure Portal como al menos un Administrador de aplicaciones y un Administrador de autenticación.
Busque y seleccione Microsoft Entra ID y seleccione Aplicaciones empresariales.
Seleccione Extensiones de autenticación personalizadas y, después, seleccione Crear una extensión personalizada.
En Aspectos básicos, seleccione el tipo de evento EmailOtpSend y seleccione Siguiente.
En la pestaña Configuración de punto de conexión, rellene las siguientes propiedades y, a continuación, seleccione Siguiente para continuar.
- Nombre: nombre de la extensión de autenticación personalizada. Por ejemplo, Correo electrónico de envío OTP.
- Dirección URL de destino:
{Function_Url}
de la dirección URL de la función de Azure. Vaya a la página Información general de la aplicación de funciones de Azure y seleccione la función que ha creado. En la página Información general de la función, seleccione Obtener dirección URL de función y use el icono de copia para copiar la dirección URL de customauthenticationextension_extension (clave del sistema). - Descripción: descripción de la extensión de autenticación personalizada.
En la pestaña Autenticación de API, seleccione la opción Crear un nuevo registro de aplicación para crear un registro de aplicación que represente a la aplicación de funciones.
Asigne un nombre a la aplicación, por ejemplo, API de eventos de autenticación de Azure Functionsy seleccione Siguiente.
En la pestaña Aplicaciones, seleccione la aplicación para asociarla a la extensión de autenticación personalizada. Seleccione Siguiente. Tiene la opción de aplicarla en todo el inquilino activando la casilla. Seleccione Siguiente para continuar.
En la pestaña Revisar, compruebe que los detalles son correctos para la extensión de autenticación personalizada. Anote el identificador de aplicación en Autenticación de API, que es necesario para configurar la autenticación para la función de Azure en la aplicación de funciones de Azure. Seleccione Crear.
Conceder consentimiento del administrador
Una vez creada la extensión de autenticación personalizada, abra la aplicación desde el portal en Registros de aplicaciones y seleccione Permisos de API.
En la página Permisos de API, seleccione el botón Conceder consentimiento del administrador para"YourTenant" para dar su consentimiento del administrador a la aplicación registrada, lo que permite que la extensión de autenticación personalizada se autentique en la API. La extensión de autenticación personalizada usa client_credentials
para autenticarse en la aplicación de funciones de Azure mediante el permiso Receive custom authentication extension HTTP requests
.
La siguiente captura de pantalla muestra cómo conceder permisos.
Paso 4: Configuración de una aplicación OpenID Connect con la que probar
Para obtener un token y probar la extensión de autenticación personalizada, puede usar la aplicación https://jwt.ms. Es una aplicación web de Microsoft que muestra el contenido descodificado de un token (el contenido del token nunca sale del explorador).
Siga estos pasos para registrar la aplicación web jwt.ms:
4.1 Registrar una aplicación web de prueba
- Inicie sesión en el Centro de administración de Microsoft Entra como Administrador de aplicaciones como mínimo.
- Vaya aIdentidad>Aplicaciones>Registros de aplicaciones.
- Seleccione Nuevo registro.
- Escriba un Nombre para la aplicación. Por ejemplo, Mi aplicación de prueba.
- En Tipos de cuenta admitidos, seleccione Solo las cuentas de este directorio organizativo.
- En la lista desplegable Seleccionar una plataforma, en URI de redirección, seleccione Web y escriba
https://jwt.ms
en el cuadro de texto Dirección URL. - Seleccione Registrar para completar el registro de la aplicación.
- En el registro de la aplicación, en Información general, copie el Id. de aplicación (cliente), que se usa más adelante y se conoce como
{App_to_sendotp_ID}
. En Microsoft Graph, se hace referencia a él mediante la propiedad appId.
La siguiente captura de pantalla muestra cómo registrar Mi aplicación de prueba.
4.1 Obtener el id. de la aplicación
En el registro de la aplicación, en Información general, copie el Id. de aplicación (cliente). Al id. de la aplicación se hace referencia como {App_to_sendotp_ID}
en pasos posteriores. En Microsoft Graph, se hace referencia a él mediante la propiedad appId.
4.2 Habilitar el flujo implícito
La aplicación de prueba jwt.ms usa el flujo implícito. Habilite el flujo implícito en el registro Mi aplicación de prueba:
Importante
Microsoft recomienda usar el flujo de autenticación más seguro disponible. El flujo de autenticación que se usa para realizar pruebas en este procedimiento requiere un alto grado de confianza en la aplicación y conlleva riesgos que no están presentes en otros flujos. Este enfoque no se debe usar para autenticar a los usuarios en las aplicaciones de producción (obtener más información).
- En Administrar, seleccione Autenticación.
- En Flujos de concesión implícita e híbridos, seleccione la casilla de verificación Tokens de id. (usados para flujos híbridos e implícitos).
- Seleccione Guardar.
Paso 5: Protección de la función de Azure
La extensión de autenticación personalizada de Microsoft Entra usa el flujo de servidor a servidor para obtener un token de acceso que se envía en el encabezado HTTP Authorization
a la función de Azure. Al publicar la función en Azure, especialmente en un entorno de producción, debe validar el token enviado en el encabezado de autorización.
Para proteger la función de Azure, siga estos pasos con el fin de integrar la autenticación de Microsoft Entra, para validar los tokens entrantes con el registro de aplicación de la API de eventos de autenticación de Azure Functions.registro de aplicaciones.
Nota:
Si la aplicación de funciones de Azure se hospeda en un inquilino de Azure diferente del inquilino en el que está registrada la extensión de autenticación personalizada, vaya al paso Uso del proveedor de identidades de OpenID Connect.
- Inicie sesión en Azure Portal.
- Busque y seleccione la aplicación de funciones que publicó anteriormente.
- Seleccione Autenticación en el menú de la izquierda.
- Seleccione Agregar proveedor de identidades.
- En el menú desplegable seleccione Microsoft como proveedor de identidades.
- En Registro de aplicación ->Tipo de registro de aplicación, seleccione Seleccionar un registro de aplicación existente en este directorio y seleccione el registro de aplicación API de eventos de autenticación de Azure Functions que creó antes al registrar el proveedor de correo electrónico personalizado.
- Agregue la expiración del Secreto de cliente de la aplicación.
- En Solicitudes no autenticadas, seleccione HTTP 401 No autorizado como proveedor de identidades.
- Anule la selección de la opción Almacén de tokens.
- Seleccione Agregar para agregar autenticación a la función de Azure.
5.1 Uso del proveedor de identidades de OpenID Connect
Si ha configurado el proveedor de identidades de Microsoft, omita este paso. De lo contrario, si la función de Azure está hospedada en un inquilino diferente al inquilino en el que está registrada la extensión de autenticación personalizada, siga estos pasos para proteger la función:
Inicie sesión en Azure Portal, después busque y seleccione la aplicación de funciones que publicó anteriormente.
Seleccione Autenticación en el panel izquierdo.
Seleccione Agregar proveedor de identidades.
Seleccione OpenID Connect como proveedor de identidades.
Proporcione un nombre, como Contoso Microsoft Entra ID.
En Entrada de metadatos, escriba la siguiente URL en el cuadro Dirección URL del documento. Reemplace el
{tenantId}
por el identificador de inquilino de Microsoft Entra y{tenantname}
por el nombre del inquilino sin el "onmicrosoft.com".https://{tenantname}.ciamlogin.com/{tenantId}/v2.0/.well-known/openid-configuration
En Registro de aplicación, escriba el id. de la aplicación (id. de cliente) del registro de aplicación de la API de eventos de autenticación de Azure Functionsque creó antes.
En el Centro de administración de Microsoft Entra:
- Seleccione el registro de aplicación de la API de eventos de autenticación de Azure Functionsque creó antes.
- Seleccione Certificates & secrets>Client secrets>New client secret (Certificados y secretos > Secretos de cliente > Nuevo secreto de cliente).
- Agregue una descripción para el secreto de cliente.
- Seleccione una expiración para el secreto o especifique una duración personalizada.
- Seleccione Agregar.
- Registre el valor del secreto para usarlo en el código de la aplicación cliente. Este valor secreto no se volverá a mostrar una vez que abandone esta página.
Vuelva a la función de Azure y, en Registro de aplicación, escriba el Secreto de cliente.
Anule la selección de la opción Almacén de tokens.
Seleccione Agregar para agregar el proveedor de identidades de OpenID Connect.
Paso 6: Pruebe la aplicación
Para probar el proveedor de correo electrónico personalizado, siga estos pasos:
Abra un nuevo explorador privado, vaya a la siguiente dirección URL e inicie sesión.
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
Reemplace
{tenant-id}
por el id. del inquilino, el nombre del inquilino o uno de los nombres de dominio comprobados. Por ejemplo,contoso.onmicrosoft.com
.Reemplace
{tenantname}
por el nombre del inquilino sin el "onmicrosoft.com".Reemplace
{App_to_sendotp_ID}
por el id. de registro de Mi aplicación de prueba.Asegúrese de iniciar sesión con una Cuenta de código de acceso de correo electrónico de un solo uso. A continuación, seleccione Enviar código. Asegúrese de que el código enviado a las direcciones de correo electrónico registradas usa el proveedor personalizado registrado anteriormente.
Paso 7: Revertir al proveedor de Microsoft
Si se produce un error en la API de extensión, de forma predeterminada Entra ID no enviará un OTP al usuario. En su lugar, puede establecer el comportamiento en caso de error para revertir al proveedor de Microsoft.
Para habilitar esto, ejecute la siguiente solicitud. Reemplace {customListenerOjectId}
por el identificador de agente de escucha de autenticación personalizado registrado anteriormente.
- Necesita el permiso delegado 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"
}
}
}
}