Introducción
Una aplicación de pedidos necesita una forma de iniciar sesión para sus usuarios. Crearás un directorio de usuarios y un cliente público de aplicación, iniciarás sesión con un usuario sintético, validarás los tokens emitidos y renovarás la sesión antes de limpiar.
Completa primero Construir y validar una API de pedidos. Este entorno nuevo proporciona su propio backend público, entradas desechables de inicio de sesión y un ejemplo de validación de tokens. Mantén privados los archivos de contraseñas y tokens.
Relación con las certificaciones
| Certificación | Tarea del examen | Práctica |
|---|---|---|
| Solutions Architect – Associate (SAA-C03) | Tarea 1.2 | Inicio de sesión Cognito, validación de tokens y renovación de sesiones. |
| Developer – Associate (DVA-C02) | Tarea 2.1 | Inicio de sesión Cognito, validación de tokens y renovación de sesiones. |
| Security – Specialty (SCS-C03) | Tarea 4.1 | Práctica de fundamentos: Inicio de sesión Cognito, validación de tokens y renovación de sesiones. |
Vista general del laboratorio

Crear el directorio de usuarios de la aplicación
En este paso, establecerás un grupo de usuarios, un cliente público de aplicación y un usuario sintético confirmado.
Entra en el espacio de trabajo y usa umask 077 para que los archivos recién creados sean accesibles únicamente para tu usuario. Afecta a los permisos de archivos, no a las reglas de autorización de la API:
cd /home/labex/project
umask 077
Un grupo de usuarios de Cognito, o user pool, es el directorio de usuarios de tu aplicación. Sus usuarios inician sesión en la aplicación; tu identidad IAM preparada de la CLI administra los recursos de nube. Observa AWS View en la parte superior para comparar estos recursos nativos.
Crea el grupo de usuarios del laboratorio. $(...) almacena el ID de grupo devuelto para los comandos nativos posteriores:
POOL_ID=$(aws cognito-idp create-user-pool \
--pool-name labex-a04-users \
--query UserPool.Id \
--output text)
echo "$POOL_ID"
Registra su ID; > escribe el valor en el archivo de inventario:
printf '%s\n' "$POOL_ID" > pool-id.txt
Un cliente de aplicación, o app client, identifica la aplicación que inicia sesiones de usuarios mediante este grupo. Una aplicación pública no puede mantener confidencial un secreto de cliente. Crea este cliente sin secreto y permite el flujo de usuario y contraseña y el flujo de token de renovación usados en este recorrido:
CLIENT_ID=$(aws cognito-idp create-user-pool-client \
--user-pool-id "$POOL_ID" \
--client-name orders-client \
--no-generate-secret \
--explicit-auth-flows ALLOW_USER_PASSWORD_AUTH ALLOW_REFRESH_TOKEN_AUTH \
--query UserPoolClient.ClientId \
--output text)
echo "$CLIENT_ID"
printf '%s\n' "$CLIENT_ID" > client-id.txt
Inspecciona la configuración segura del cliente sin solicitar valores secretos:
aws cognito-idp describe-user-pool-client \
--user-pool-id "$POOL_ID" \
--client-id "$CLIENT_ID" \
--query '{Name:UserPoolClient.ClientName,Flows:UserPoolClient.ExplicitAuthFlows}'
Crea el usuario de demostración con la entrega de correo suprimida. Esta es una acción de aprovisionamiento de administrador, distinta del inicio de sesión posterior del usuario:
aws cognito-idp admin-create-user \
--user-pool-id "$POOL_ID" \
--username labex-demo \
--message-action SUPPRESS \
--user-attributes Name=email,Value=demo@example.test \
--query '{Username:User.Username,Status:User.UserStatus}'
El estado inicial es FORCE_CHANGE_PASSWORD. Solo para este usuario desechable de prueba, aplica mediante la CLI el archivo suministrado de entrada de contraseña permanente. El archivo tiene los campos Username, Password y Permanent; la sintaxis file:// los lee sin imprimir la contraseña:
aws cognito-idp admin-set-user-password \
--user-pool-id "$POOL_ID" \
--cli-input-json file://demo-password.json
Inspecciona únicamente el estado seguro del usuario:
aws cognito-idp admin-get-user \
--user-pool-id "$POOL_ID" \
--username labex-demo \
--query '{Username:Username,Status:UserStatus,Enabled:Enabled}'
Espera labex-demo, CONFIRMED y true. En AWS View, compara el ID del grupo del laboratorio, orders-client, su ausencia de secreto de cliente y el usuario confirmado y habilitado. Ejemplo del estado nativo real de grupo, cliente y usuario:

El grupo ajeno al laboratorio labex-a04-reference permanece vacío. Todavía no se ha solicitado ningún token de usuario.
Iniciar sesión y leer la identidad de la aplicación
En este paso, obtendrás tokens reales para el usuario confirmado y observarás el rechazo de una contraseña incorrecta.
InitiateAuth con USER_PASSWORD_AUTH autentica el nombre de usuario y la contraseña de la aplicación. No autoriza al usuario mediante la identidad de administrador IAM de tu CLI. El archivo suministrado sign-in.json contiene los parámetros sintéticos de usuario y contraseña de esta demostración.
Almacena únicamente AuthenticationResult en un archivo privado. No uses cat sobre esta respuesta; contiene tokens de portador:
aws cognito-idp initiate-auth --client-id "$CLIENT_ID" --auth-flow USER_PASSWORD_AUTH --auth-parameters file://sign-in.json --query AuthenticationResult --output json > tokens.json
Muestra únicamente los campos no secretos de la respuesta con jq. La expresión de presencia de tokens devuelve un booleano en lugar de los valores de los tokens:
jq '{TokenType,ExpiresIn,TokensPresent:(has("AccessToken") and has("IdToken") and has("RefreshToken"))}' tokens.json
Espera Bearer, una duración positiva de caducidad y TokensPresent: true. El token de acceso autoriza solicitudes apropiadas de usuario o API, el token de ID contiene información de identidad para la aplicación y el token de renovación puede obtener nuevos tokens de acceso y de ID. Tienen propósitos distintos y no son intercambiables.
Extrae los tokens de acceso y de ID en archivos privados de transporte. jq -r escribe cadenas sin formato y la redirección evita que aparezcan en el terminal:
jq -r '.AccessToken' tokens.json > access-token.txt
jq -r '.IdToken' tokens.json > id-token.txt
GetUser autentica con el token de acceso. Solicita únicamente el nombre de usuario en su salida:
aws cognito-idp get-user \
--access-token "$(cat access-token.txt)" \
--query Username \
--output text
Espera labex-demo. Esta es una respuesta de Cognito en vivo al token emitido, no una prueba deducida únicamente de un archivo JSON local.
Prueba los parámetros suministrados de contraseña incorrecta y redirige cualquier respuesta inesperada de tokens a un archivo privado separado:
aws cognito-idp initiate-auth --client-id "$CLIENT_ID" --auth-flow USER_PASSWORD_AUTH --auth-parameters file://wrong-sign-in.json --query AuthenticationResult --output json > rejected-login.json
Espera NotAuthorizedException: Incorrect username or password. El comando termina intencionadamente con un código distinto de cero; continúa con el siguiente paso después de leer ese rechazo exacto. Un error de conexión o de transporte de autenticación no demuestra un rechazo por contraseña incorrecta. No sobrescribas tus tokens válidos con este resultado fallido. La comprobación automática del paso valida de forma independiente los tokens emitidos y el resultado GetUser en vivo; observa manualmente el error específico de contraseña incorrecta.

Validar tokens firmados y renovar la sesión
En este paso, verificarás la firma del token y su destinatario previsto, renovarás la sesión y distinguirás el inicio de sesión de la protección de rutas de API.
Un JWT contiene datos codificados de cabecera y claims, o declaraciones, además de una firma. Decodificarlo por sí solo no demuestra quién lo emitió. JWKS es el conjunto de claves públicas de firma del emisor; RS256 utiliza una firma RSA que puede verificarse con esas claves públicas.
Lee el ejemplo ordinario suministrado de validación de aplicación; no contiene contraseñas ni tokens literales:
cat verify_tokens.py
El ejemplo recupera el JWKS público de tu grupo desde su endpoint preparado del espacio de trabajo, verifica RS256 y el ID de clave y después comprueba el emisor, la hora actual, token_use y el cliente de aplicación. El emisor firmado usa la identidad del grupo de Cognito. El token de acceso identifica al cliente con client_id; el token de ID usa aud. Ejecútalo con el archivo guardado de tokens y los ID reales de grupo y cliente:
/home/labex/project/client-venv/bin/python verify_tokens.py tokens.json "$POOL_ID" "$CLIENT_ID"
Espera resúmenes seguros de access e id, cada uno con RS256 y current_time_valid: true. También cambia un byte de firma en memoria y confirma el rechazo antes de aceptar los claims; no se guarda ningún token manipulado. El alcance aws.cognito.signin.user.admin del token de acceso permite operaciones de autoservicio de usuarios de Cognito. Este alcance no es acceso de administrador de AWS, una regla de propiedad de pedidos ni un alcance de negocio personalizado.
Crea parámetros privados de renovación a partir del token original de renovación. Esto escribe en un archivo y no expone el valor:
jq '{REFRESH_TOKEN:.RefreshToken}' tokens.json > refresh-parameters.json
Obtén nuevos tokens de acceso y de ID sin enviar de nuevo la contraseña del usuario:
aws cognito-idp initiate-auth --client-id "$CLIENT_ID" --auth-flow REFRESH_TOKEN_AUTH --auth-parameters file://refresh-parameters.json --query AuthenticationResult --output json > refreshed.json
Valida los tokens renovados mediante las mismas comprobaciones de clave pública y claims:
/home/labex/project/client-venv/bin/python verify_tokens.py refreshed.json "$POOL_ID" "$CLIENT_ID"
Espera resúmenes válidos de acceso e ID para el mismo grupo y cliente. La respuesta de renovación no tiene por qué contener otro token de renovación; conserva la respuesta privada original hasta la limpieza.
El inicio de sesión por sí solo no cambia la API pública preparada. Encuentra su ID generado y envía una solicitud pública de salud sin token de portador:
API_ID=$(aws apigatewayv2 get-apis \
--query "Items[?Name=='labex-a04'].ApiId | [0]" \
--output text)
echo "$API_ID"
printf '%s\n' "$API_ID" > api-id.txt
curl -i "http://127.0.0.1:8081/api/$API_ID/health"
Espera HTTP 200 y healthy: true. AWS View sigue mostrando autorización NONE para todas las rutas y ningún elemento de pedido. La autenticación del usuario tuvo éxito, pero la API todavía no exige un token. La siguiente unidad añade autorización JWT de rutas; un token válido tampoco establece automáticamente la propiedad de un pedido concreto.
La renovación continúa la sesión iniciada para el mismo cliente de aplicación. No cambia la autorización de las rutas de API ni concede acceso a un pedido. Distingue estas decisiones al comparar los resúmenes de identidad renovados con la respuesta de salud que sigue siendo pública.
Eliminar los recursos de inicio de sesión y API
En este paso, eliminarás los recursos de inicio de sesión del laboratorio y los componentes del backend conservando el grupo, la tabla y los registros de referencia ajenos a él.
Tu inventario es labex-a04-users de pool-id.txt, orders-client de client-id.txt, el usuario labex-demo, el ID de API de api-id.txt, labex-a04-orders-api, su grupo de registros de función, labex-a04-orders y la política OrdersData del rol. Elimina únicamente estos recursos indicados.
Elimina el usuario sintético y después el cliente de aplicación y el grupo del laboratorio:
aws cognito-idp admin-delete-user --user-pool-id "$POOL_ID" --username labex-demo
aws cognito-idp delete-user-pool-client --user-pool-id "$POOL_ID" --client-id "$CLIENT_ID"
aws cognito-idp delete-user-pool --user-pool-id "$POOL_ID"
Elimina la API funcional preparada y sus recursos de backend del laboratorio:
aws apigatewayv2 delete-api --api-id "$API_ID"
aws lambda delete-function --function-name labex-a04-orders-api
aws logs delete-log-group --log-group-name /aws/lambda/labex-a04-orders-api
aws dynamodb delete-table \
--table-name labex-a04-orders \
--query TableDescription.TableName \
--output text
aws iam delete-role-policy --role-name labex-a04-execution --policy-name OrdersData
Consulta correctamente los inventarios nativos; los fallos de transporte no demuestran ausencia:
aws cognito-idp list-user-pools --max-results 60 --query 'UserPools[].Name'
aws apigatewayv2 get-apis --query 'Items[].Name'
aws lambda list-functions --query 'Functions[].FunctionName'
aws dynamodb list-tables --query TableNames
Espera únicamente el grupo y la tabla de referencia, con listas vacías de API y funciones. AWS View debe mostrar el mismo estado y conservar el elemento de referencia e INFO platform reference keep unchanged. El rol de ejecución preparado conserva FunctionLogs.
Elimina tus archivos privados de autenticación, incluidas las entradas suministradas de contraseña sintética. rm -f elimina únicamente los archivos locales enumerados explícitamente:
rm -f tokens.json access-token.txt id-token.txt refreshed.json refresh-parameters.json rejected-login.json sign-in.json wrong-sign-in.json demo-password.json
Eliminar únicamente archivos locales no revoca la sesión del lado del servidor. Aquí también se eliminaron el usuario sintético, el cliente y el grupo; este laboratorio no afirma proporcionar un mecanismo general de cierre de sesión o revocación JWT. Conserva los recursos de referencia ajenos al laboratorio hasta la limpieza del autor y el apagado de la VM.
Resumen
Creaste un directorio de usuarios de aplicación y un cliente público, aprovisionaste un usuario sintético, iniciaste sesión y observaste un rechazo por contraseña incorrecta. Verificaste firmas RS256 reales y claims de emisor, cliente, tiempo y tipo, leíste la identidad del usuario en vivo y renovaste tokens de acceso e ID. Distinguiste usuarios de Cognito de identidades IAM y el inicio de sesión de la autorización de API; después eliminaste recursos del laboratorio y archivos privados conservando las referencias.
Para ampliar este tema, consulta la referencia de AWS: Propósitos de los tokens del grupo de usuarios; Firmas JWT y validación de declaraciones; Actualización de sesión y flujos de tokens de actualización.



