Hoy, muchas compañías usan contraseñas de un solo uso (OTP) para autenticar a los usuarios. Una aplicación le solicita una contraseña para continuar. Esta contraseña se le envía por mensaje de texto a un número de teléfono registrado. Ingrese la contraseña para autenticar.
Es un enfoque fácil y seguro para verificar la identidad del usuario. En esta publicación de blog, describiremos cómo integrar la misma funcionalidad OTP en un chatbot de Amazon Lex.
Amazon Lex le permite construir fácilmente interfaces de conversación realistas en sus aplicaciones existentes utilizando voz y texto.
Antes saltamos a los detalles, echemos un vistazo más de cerca a las OTP. OTP es generalmente una secuencia de números que es válida solo para una sesión o transacción de inicio de sesión.
La OTP caduca después de un cierto período de tiempo y, después de eso, se debe generar uno nuevo. Se puede usar en una variedad de canales, como web, dispositivos móviles u otros dispositivos.
En esta publicación de blog, mostraremos cómo autenticar a sus usuarios usando un ejemplo de chatbot de pedidos de alimentos en un dispositivo móvil. El robot de Amazon Lex hará el pedido a los usuarios solo después de que hayan sido autenticados por OTP.
Consideremos la siguiente conversación que usa OTP.
Para lograr la interacción que acabamos de describir, creamos un bot de entrega de alimentos primero con las siguientes intenciones: GetFoodMenu y OrderFood. La contraseña de OTP se usa en intentos que involucran transacciones, como OrderFood.
Le mostraremos dos implementaciones diferentes de capturar la OTP: una por voz y la otra por texto. En la primera implementación, Amazon Lex captura la OTP directamente como una modalidad de voz o texto. El valor de OTP se envía directamente a Amazon Lex como un valor de ranura. En la segunda implementación, la aplicación cliente captura la OTP (mediante la modalidad de texto). La aplicación del cliente captura la OTP del cuadro de diálogo del cliente y la envía a Amazon Lex como un atributo de sesión. Los atributos de la sesión se pueden cifrar.
Es importante tener en cuenta que todas las llamadas API realizadas al tiempo de ejecución de Amazon Lex se cifran mediante HTTPS. El cifrado de la OTP cuando se usa a través de atributos de sesión proporciona un nivel adicional de seguridad. Amazon Lex pasa la OTP recibida a través del atributo de sesión o el valor del espacio a una función Lambda de AWS que puede verificar la OTP.
Arquitectura de la aplicación
El bot tiene una arquitectura que se basa en los siguientes servicios de AWS:
- Amazon Lex por construir la interfaz de conversación.
- AWS Lambda para ejecutar la validación y cumplimiento de datos.
- Amazon DynamoDB para almacenar y recuperar datos.
- Amazon Simple Notification Service (SNS) para publicar mensajes SMS.
- AWS Key Servicio de administración (KMS) para cifrar y descifrar la OTP.
- Grupo de identidad de Amazon Cognito para obtener credenciales temporales de AWS para usar KMS.
El siguiente diagrama ilustra cómo los diversos servicios funcionan juntos.
Cuando el usuario inicia por primera vez una interacción con el bot, el correo electrónico del usuario u otros metadatos se pasan de la interfaz al tiempo de ejecución de Amazon Lex.
Un código de validación de AWS Lambda hook se usa para realizar las siguientes tareas:
- AWS Lambda genera una OTP y la almacena en la tabla DynamoDB.
- AWS Lambda envía la OTP al teléfono móvil del usuario mediante SNS.
- El usuario ingresa la OTP en el aplicación cliente, que se envía como un tipo de ranura a Amazon Lex.
- AWS Lambda verifica la OTP y, si la autenticación es exitosa, le indica a Amazon Lex que continúe con la conversación.
Después de que el usuario se autentica el usuario puede realizar un pedido con el bot de Amazon Lex.
Capturando la OTP usando la modalidad de texto
De manera similar a la primera implementación, el correo electrónico del usuario u otros metadatos se envían al tiempo de ejecución de Amazon Lex desde el extremo frontal. [19659002] En la segunda implementación, se utiliza un gancho de código de validación de AWS Lambda para realizar las siguientes tareas:
- AWS Lambda genera un OTP y lo almacena en la tabla DynamoDB.
- Lambda envía el OTP al teléfono móvil del usuario usando SNS
- El usuario ingresa al O TP en el cuadro de diálogo de la aplicación cliente.
- La aplicación cliente cifra la OTP ingresada por el usuario y la envía al tiempo de ejecución de Amazon Lex en los atributos de la sesión.
Nota : los atributos de la sesión pueden estar encriptado.
- AWS Lambda verifica la OTP y, si la autenticación es exitosa, le indica a Amazon Lex que continúe con la conversación.
Nota: si la OTP está encriptada, la función Lambda primero tendrá que descifrarlo.
Después de autenticar al usuario, puede realizar un pedido con el bot de Amazon Lex.
Generando un OTP
Hay muchos métodos para generar un OTP. En nuestro ejemplo, generamos un número aleatorio de seis dígitos como OTP que es válido por un minuto y lo almacenamos en una tabla DynamoDB. Para verificar la OTP, comparamos el valor ingresado por el usuario con el valor en la tabla DynamoDB.
Implementación del bot OTP
Use este botón AWS CloudFormation para iniciar el bot OTP en la región AWS us-east-1 :
El código fuente está disponible en nuestro repositorio de GitHub .
Abra la consola AWS CloudFormation, y en la página de Parámetros, Ingrese un número de teléfono válido. Este es el número de teléfono al que se envía la OTP.
Elija Siguiente dos veces para mostrar la página Revisar.
Seleccione la casilla de verificación de reconocimiento y elija Crear para implementar el ExampleBot.
The CloudFormation stack crea los siguientes recursos en su cuenta de AWS:
- Amazon S3 se almacena para alojar las interfaces de usuario web de ExampleBot.
- Amazon Lex Bot para proporcionar procesamiento en lenguaje natural.
- Funciones de AWS Lambda utilizadas para enviar y validar la OTP. [19659012] Roles de AWS IAM para la función Lambda.
- Tablas de Amazon DynamoDB para almacenar datos de sesión.
- Clave de AWS KMS para cifrar y descifrar datos.
- Grupo de identidad de Amazon Cognito configurado para autenticar clientes y proporcionar credenciales temporales de AWS.
Cuando se completa la implementación (después de aproximadamente 15 minutos), la pestaña Salida de la pila muestra lo siguiente:
- ExampleBotURL : haga clic en esta URL para interactuar con ExampleBot.
Creemos el bot
Th Esta publicación de blog se basa en los conceptos básicos de construcción de bots cubiertos en Construyendo mejores bots usando Amazon Lex . Siguiendo la guía de esa publicación de blog, creamos un bot de Amazon Lex con dos intentos: GetFoodMenu y OrderFood.
El intento GetFoodMenu no requiere autenticación. El usuario puede preguntarle al bot qué alimentos hay en el menú, tales como:
Recomiende algo.
Muéstreme su menú, por favor.
¿Qué hay en el menú?
¿Qué tipo de comida tienes?
El bot devuelve una lista de alimentos que el usuario puede pedir cuando se obtiene la intención de GetFoodMenu.
Si el usuario ya sabe qué artículo de comida quiere pedir , pueden pedir el alimento con el siguiente texto de entrada para invocar la intención de OrderFood:
Me gustaría pedir un poco de pasta.
¿Puedo pedir algo de comida por favor?
Hamburguesa con queso !
Amazon Lex utiliza el enlace de código Lambda para verificar si el usuario está autenticado. Si el usuario está autenticado, Amazon Lex agrega el alimento al pedido actual del usuario.
Si el usuario aún no se ha autenticado, la interacción se ve así:
Usuario: Me gustaría pedir un poco de pasta. [19659070] Bot: Parece que todavía no estás autenticado. Hemos enviado una OTP a su número de teléfono registrado. Ingrese la OTP.
Usuario: 812734
Nota : Si el usuario está utilizando la modalidad de texto, la entrada “a” del usuario puede cifrarse.
Bot: Gracias por ingresar el OTP. Agregamos pizza a su pedido. ¿Desea algo más?
Si el usuario no está autenticado, Amazon Lex inicia el proceso de autenticación multifactor (MFA). AWS Lambda consulta la tabla DynamoDB para obtener el número de teléfono móvil y la dirección de entrega de ese usuario. Después de que DynamoDB devuelve los valores, AWS Lambda genera una OTP basada en los metadatos del usuario, la guarda en una tabla de DynamoDB con un UUID como clave principal y la almacena en los atributos de la sesión. Luego, AWS Lambda usa SNS para enviar un OTP al usuario y obtener el pin usando la ranura del pin en la intención de OrderFood.
Después de que el usuario ingresa el OTP, Amazon Lex usa el gancho de código Lambda para validar el pin. AWS Lambda consulta la tabla DynamoDB con el UUID en los atributos de la sesión para verificar la OTP. Si el pin es correcto, la función Lambda consulta a DynamoDB por los datos secretos; si el pin es incorrecto, Lambda realiza el paso de validación nuevamente.
Detalles de implementación
Las siguientes tablas y capturas de pantalla muestran los diferentes tipos de ranuras e intentos, y cómo puede usar la consola de administración de AWS para especificar los que desea.
Ranuras
Tipo de ranura: | Valores de ranura |
Alimentos | Amazon.Food |
Pin | Amazon.Number |
Intents [19659080] Nombre del intentoEjemplos de declaracionesOrderFood
Me gustaría pedir algo de {Food}
{Food}
Me gustaría {food}
order {food}
¿Puedo pedir algo de comida por favor
¿Puedo pedir algo de {Food} por favor
GetFoodMenu
Recomiende algo.
Muéstrame tu menú, por favor.
¿Qué hay en el menú?
¿Qué tipo de comida tienes?
La intención GetFoodMenu usa la función GetMenu Lambda como el gancho del código de inicialización y validación para realizar la lógica, mientras que la intención OrderFood usa la función OrderFood Lambda como el código de inicialización y validación enganche para realizar la lógica.
Estos son los pasos que sigue la función Lambda:
- La función Lambda primero comprueba qué intención ha invocado el usuario.
- Si la carga útil es para la intención GetFoodMenu:
- Suponemos que el cliente enviará los siguientes elementos en el atributo de sesión para la primera llamada a la API de tiempo de ejecución de Amazon Lex. Como no podemos pasar atributos de sesión en la consola Lex, para fines de prueba, nuestra función Lambda creará los siguientes atributos de sesión si el atributo de sesión está vacío.
{’email’: ‘user@domain.com’, ‘auth’: ‘false’, ‘uuid’: None, ‘currentOrder’: None, ‘encryptedPin’: None}
- Suponemos que el cliente enviará los siguientes elementos en el atributo de sesión para la primera llamada a la API de tiempo de ejecución de Amazon Lex. Como no podemos pasar atributos de sesión en la consola Lex, para fines de prueba, nuestra función Lambda creará los siguientes atributos de sesión si el atributo de sesión está vacío.
- ’email’ es la dirección de correo electrónico de el usuario.
- ‘auth’: ‘falso’ implica que el usuario no está autenticado.
- ‘uuid’ es una bandera utilizada más tarde como la clave principal para almacenar el OTP en el DynamoDB.
- ‘currentOrder’ se mantendrá seguimiento de los alimentos solicitados por el usuario.
- ‘EncriptadoPin’ será utilizado por el cliente frontend para enviar OTP encriptado. Si la implementación no requiere que se cifre OTP, entonces este atributo es opcional.
- La función Lambda devolverá una lista de alimentos y le preguntará al usuario qué alimentos desea ordenar. En otras palabras, la función Lambda generará Slot para la ranura de Alimentos en OrderFood
- Si la carga útil es para la intención de OrderFood:
- Como dijimos anteriormente, para fines de prueba, nuestra función Lambda creará el siguiente atributo de sesión si los atributos de sesión están vacíos.
{’email’: ‘user@domain.com’, ‘auth’: ‘false’, ‘uuid’: None, ‘currentOrder’: None, ‘encryptedPin’: None} - Si el usuario está autenticado, el Lambda la función agregará el alimento solicitado a currentOrder en los atributos de la sesión.
- La función Lambda consultará la tabla DynamoDB phoneNumbers usando el correo electrónico para el número de teléfono del usuario.
- Si DynamoDB no puede devolver un número de teléfono que coincida con esa dirección de correo electrónico, la función Lambda le dirá al usuario que no pudo encontrar un número de teléfono asociado con ese correo electrónico y le pedirá que se ponga en contacto con el servicio de asistencia.
- La función Lambda generará un OTP y un uuid. El uuid se almacena en los atributos de la sesión y el par de valores clave {uuid: OTP} se almacenará como un registro en la tabla DynamoDB onpin.
- La función Lambda usará SNS para enviar el OTP al número de teléfono del usuario y preguntar el usuario ingrese el pin único que recibió al obtener la ranura del pin en OrderFood
- Después de que el usuario ingrese el pin, la función Lambda consultará en la tabla DyetimemoDB de pin único el registro con el uuid almacenado en los atributos de sesión.
- Si el usuario ingresa un pin incorrecto, la función Lambda generará una nueva OTP, la almacenará en DynamoDB, actualizará el uuid en Atributos de sesión, enviará esta nueva OTP al usuario a través de SNS nuevamente y le pedirá al usuario que ingrese el pin de nuevo. La siguiente captura de pantalla ilustra esto.
- Si el pin es correcto, Lambda validará el alimento que solicita el usuario.
- Si el tipo de ranura “Alimento” es nulo, Lambda preguntará al usuario qué datos le interesan al obtener el ” Alimento “en la intención” OrderFood “.
- Lambda agregará el alimento solicitado a ‘CurrentOrder’ en los atributos de la sesión.
- Si el usuario ingresa un pin incorrecto, la función Lambda generará una nueva OTP, la almacenará en DynamoDB, actualizará el uuid en Atributos de sesión, enviará esta nueva OTP al usuario a través de SNS nuevamente y le pedirá al usuario que ingrese el pin de nuevo. La siguiente captura de pantalla ilustra esto.
- Como dijimos anteriormente, para fines de prueba, nuestra función Lambda creará el siguiente atributo de sesión si los atributos de sesión están vacíos.
- Después de autenticar al usuario, los elementos posteriores que desee agregar al pedido no requerirán autenticación mientras la sesión no caduque.
Cifrado y descifrado OTP
En esta sección, Le mostraremos cómo cifrar la OTP desde el lado del cliente antes de enviar la OTP como un atributo de sesión a Amazon Lex. También le mostraremos cómo descifrar el atributo de sesión en la función Lambda.
Para cifrar la OTP, la interfaz necesita usar el grupo de identidad de Amazon Cognito para asumir un rol no autenticado que tiene los permisos para realizar la acción de cifrado usando KMS antes de enviar la OTP a Amazon Lex como un atributo de sesión. Para obtener más información sobre el grupo de identidad de Amazon Cognito, consulte la documentación .
Después de que la función Lambda reciba la OTP si está cifrada, Lambda usa KMS para descifrar la OTP y consultar una tabla de Dynamo DB para confirmar si OTP es correcto.
Consulte la documentación vinculada aquí para conocer los requisitos previos:
Asegúrese de que las identidades no autenticadas estén habilitadas.
- Cree una clave KMS .
- Bloquee el acceso a la clave KMS a la función no autenticada creada en el paso 1.
- Permitir que el rol no autenticado de Amazon Cognito use este KMS para realizar la acción de cifrado.
- Permitir que el rol IAM de la función Lambda descifre la acción de KMS.
- Aquí hay un ejemplo de las dos declaraciones de política clave que ilustran esto.
Ahora estamos listos para usar la interfaz para cifrar la OTP:
- En el cliente de interfaz, use la API GetCredentialsForIdentity para obtener las credenciales temporales de AWS para el rol no autenticado de Amazon Cognito. La interfaz utiliza estas credenciales temporales para acceder al servicio AWS KMS.
- La interfaz utiliza la API KMS Encrypt para cifrar la OTP.
- La OTP cifrada se envía a Amazon Lex en la sesión atributos.
- La función Lambda utiliza el KMS Descifrar API para descifrar la OTP cifrada.
- Después de descifrar la OTP, la función Lambda valida el valor de OTP.
Conclusión
En este En la publicación mostramos cómo usar la funcionalidad OTP en un bot de Amazon Lex usando un ejemplo simple. En nuestro diseño, utilizamos AWS Lambda para ejecutar la validación y el cumplimiento de datos; DynamoDB para almacenar y recuperar datos; SNS para publicar mensajes SMS; KMS para cifrar y descifrar la OTP; y el grupo de identidad de Amazon Cognito para obtener credenciales temporales de AWS para usar KMS.
Es fácil incorporar la funcionalidad OTP descrita aquí en cualquier bot. Puede pasar el pin OTP de la interfaz a Amazon Lex como valor de ranura o valor de atributo de sesión en su intención. Luego, envíe y realice la validación utilizando una función Lambda, ¡y su bot estará listo para aceptar OTP!