Cómo crear un login seguro en AWS con Cognito y MFA usando SAM CLI
💡 ¿Por qué pasar a CloudFormation?
Es el servicio nativo de AWS para infraestructura como código (IaC) que permite crear, aprovisionar y administrar recursos en la nube mediante plantillas.
📝 Archivo pasos-cognito.md
- Toda la configuración manual se encuentra en este archivo.
- Los usuarios los crearemos desde CLI.
# Pasos para crear grupo de usuarios en Amazon Cognito
- Dar clic en **"Grupo de usuarios"**
- Seleccionar **"Aplicación de una sola página (SPA)"**
- Asignarle nombre a la aplicación `sistema-ia`
- En opciones para los identificadores de inicio de sesión
- Seleccionar **"Correo electrónico"**
- Deshabilitar el registro automático
- En atributos necesarios para el inicio de sesión
- Seleccionar `email`
- Seleccionar `nickname`
- Dar clic en **"Crear directorio de usuarios"**
- Dar clic en **"Configure la MFA"**
- Seleccionar **"Autenticación multifactor"**
- Seleccionar **"MFA requerida"**
- Seleccionar **"Aplicaciones de autenticación"**
- Dar clic en **"Guardar los cambios"**Al tener el archivo, iremos a Kiro para que cree el “template.yaml” y “samconfig.toml” con los pasos de cada recurso.
🔥 Creación de Template
- El artículo anterior nos permitió crear paso a paso la arquitectura, por lo que sabemos qué configuración tiene cada recurso; estos pasos se pueden guardar en un archivo.md
⚙️ Archivo samconfig.toml
version = 0.1
[default.global.parameters]
# Nombre del stack en CloudFormation (compartido por deploy y delete)
stack_name = "cognito-sistema-ia"
# Región de AWS donde se desplegarán los recursos
region = "us-east-1"
[default.deploy.parameters]
# Prefijo para organizar los artefactos dentro del bucket
s3_prefix = "sam-artifacts-cognito-sistema-ia"
# Desactivar confirmación de cambios
confirm_changeset = false
# Capacidades IAM requeridas para crear roles y políticas
capabilities = ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
# No revertir cambios si el despliegue falla
disable_rollback = true
# Habilitar la resolución de referencias S3
resolve_s3 = true
# Tags para identificar los recursos
tags = [
"CostCenter=client-cognito-ai-demo",
"Project=cognito-ai-demo",
"ClientName=dm",
"Environment=prod",
"ManagedBy=SAM"
]🐪 Archivo template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: >
Cognito User Pool para sistema-ia
- Login por email
- MFA requerido (TOTP)
- Sin auto-registro
- Atributos requeridos: email, nickname
Resources:
SistemaIAUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: sistema-ia
# Solo email como identificador de inicio de sesión
UsernameAttributes:
- email
# Deshabilitar registro automático (solo admins crean usuarios)
AdminCreateUserConfig:
AllowAdminCreateUserOnly: true
InviteMessageTemplate:
EmailMessage: "Tu usuario es {username} y tu contraseña temporal es {####}"
EmailSubject: "Invitación a sistema-ia"
# Atributos requeridos
Schema:
- Name: email
AttributeDataType: String
Required: true
Mutable: true
- Name: nickname
AttributeDataType: String
Required: true
Mutable: true
# Políticas de contraseña
Policies:
PasswordPolicy:
MinimumLength: 8
RequireUppercase: true
RequireLowercase: true
RequireNumbers: true
RequireSymbols: true
# MFA requerido - solo TOTP (aplicación de autenticación)
MfaConfiguration: "ON"
EnabledMfas:
- SOFTWARE_TOKEN_MFA
# Verificación automática de email
AutoVerifiedAttributes:
- email
# Configuración de recuperación de cuenta
AccountRecoverySetting:
RecoveryMechanisms:
- Name: verified_email
Priority: 1
UserPoolAddOns:
AdvancedSecurityMode: AUDIT
# App Client para SPA (sin secret)
SistemaIAUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: sistema-ia-spa
UserPoolId: !Ref SistemaIAUserPool
# SPA no usa client secret
GenerateSecret: false
# Flujos de autenticación permitidos para SPA
ExplicitAuthFlows:
- ALLOW_USER_SRP_AUTH
- ALLOW_REFRESH_TOKEN_AUTH
# Vigencia de tokens
AccessTokenValidity: 1 # horas
IdTokenValidity: 1 # horas
RefreshTokenValidity: 1 # horas
TokenValidityUnits:
AccessToken: hours
IdToken: hours
RefreshToken: hours
# Atributos que el cliente puede leer/escribir
ReadAttributes:
- email
- nickname
- email_verified
WriteAttributes:
- email
- nickname
PreventUserExistenceErrors: ENABLED
Outputs:
UserPoolId:
Description: ID del User Pool
Value: !Ref SistemaIAUserPool
Export:
Name: !Sub "${AWS::StackName}-UserPoolId"
UserPoolArn:
Description: ARN del User Pool
Value: !GetAtt SistemaIAUserPool.Arn
Export:
Name: !Sub "${AWS::StackName}-UserPoolArn"
UserPoolClientId:
Description: ID del App Client (usar en el frontend SPA)
Value: !Ref SistemaIAUserPoolClient
Export:
Name: !Sub "${AWS::StackName}-UserPoolClientId"🧱 Estructura de repositorio
- El repositorio debe contener lo siguiente para realizar el despliegue correctamente.
├── prompt/
│ ├── pasos-cognito.md # Descripción de la arquitectura
├── template.yaml # Infraestructura SAM (todos los recursos AWS)
├── samconfig.toml # Configuración del SAM CLI y parámetro🚀 Despliegue de Arquitectura
- Paso 1: El comando “sam build” construye la aplicación, resuelve dependencias, copia el código y prepara los artefactos en la carpeta .aws-sam/build.
Get David Melchor’s stories in your inbox
Join Medium for free to get updates from this writer.
- Paso 2: El comando “sam deploy” empaqueta y despliega la aplicación en AWS, creando o actualizando el stack de CloudFormation.
- Paso 3: Revisar que la pila esté creada correctamente.
- Paso 4: Revisar cada recurso desde la consola de administración.
👤 Creación de usuario desde cli
- Este paso se realiza desde consola para no colocar las credenciales dentro de la plantilla.
aws cognito-idp admin-create-user \
--user-pool-id *id del grupo de usuarios*\
--username *correo del usuario* \
--user-attributes Name=email,Value=*correo del usuario* Name=nickname,Value=*apodo* \
--temporary-password 'contraseña del usuario' \
--message-action SUPPRESS🗑️ Destruir la Arquitectura
- Dentro de la plantilla se puede definir un bucket dedicado para el stack; de lo contrario, se asigna a uno existente relacionado a CloudFormation.
💡 Conclusiones
- Con Kiro creamos la configuración y la plantilla de CloudFormation en minutos.
- Con los pasos anteriores podemos desplegar los recursos en cualquier región de AWS y destruirlos sin que se quede algún recurso huérfano.







