UDT-001: Login (scaffolding + JWT RS256 end-to-end) #1

Merged
dmolinari merged 14 commits from feature/UDT-001 into main 2026-04-14 14:44:28 +00:00
Showing only changes of commit 6c4d572111 - Show all commits

134
docs/smoke-test-udt-001.md Normal file
View File

@@ -0,0 +1,134 @@
# Smoke Test — UDT-001 Login
Manual checklist para verificar la integración completa del flujo de login.
## Pre-requisitos
- SQL Server TECNICA3 con base `SIGCM2` y seed admin ejecutado (`database/seeds/S001__seed_admin.sql`)
- Claves RSA generadas: `scripts/generate-keys.ps1` ya corrido
- `src/api/SIGCM2.Api/appsettings.Development.json` configurado con connection string y rutas de claves
- Node.js 18+ instalado
- .NET 10 SDK instalado
## Pasos
### 1. Arrancar el backend
Abrir Terminal 1 en la raíz del repositorio:
```bash
dotnet run --project src/api/SIGCM2.Api
```
Verificar que la consola muestre algo similar a:
```
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
```
### 2. Arrancar el frontend
Abrir Terminal 2:
```bash
cd src/web
npm run dev
```
Verificar que la consola muestre:
```
VITE v8.x.x ready in Xms
➜ Local: http://localhost:5173/
```
### 3. Verificar redirect a /login
- Abrir `http://localhost:5173` en el navegador
- Debe redirigir automáticamente a `http://localhost:5173/login`
- Debe mostrar el formulario de login con campos **Usuario** y **Contraseña**
**Esperado**: Formulario visible, sin errores en consola del navegador.
### 4. Login con credenciales válidas
- Ingresar `admin` en el campo **Usuario**
- Ingresar `@Diego550@` en el campo **Contraseña**
- Hacer click en **Ingresar**
**Esperado**: Botón se deshabilita brevemente mientras carga.
### 5. Verificar Network tab — POST /api/v1/auth/login
- Abrir DevTools → pestaña **Network**
- Buscar la request `POST /api/v1/auth/login`
- Verificar:
- Status: `200 OK`
- Response body contiene: `accessToken`, `refreshToken`, `expiresIn`, `usuario`
- `usuario.username` = `"admin"`, `usuario.rol` = `"admin"`
**Esperado**: Respuesta 200 con JWT válido.
### 6. Verificar LocalStorage — auth-storage
- DevTools → pestaña **Application** → Storage → Local Storage → `http://localhost:5173`
- Buscar clave `auth-storage`
- Verificar que el JSON contenga:
```json
{
"state": {
"user": { "username": "admin", "rol": "admin", ... },
"accessToken": "eyJ..."
}
}
```
**Esperado**: Token y datos de usuario persistidos correctamente.
### 7. Verificar redirect a Dashboard
- Luego del login exitoso, la URL debe cambiar a `http://localhost:5173/`
- Debe mostrarse: **"SIG-CM2 — Dashboard — Bienvenido al SIG-CM2."**
**Esperado**: Placeholder de Dashboard visible.
### 8. Verificar firma JWT en jwt.io
- Copiar el valor de `accessToken` del LocalStorage
- Abrir [https://jwt.io](https://jwt.io)
- Pegar el token en el campo "Encoded"
- En "VERIFY SIGNATURE" → sección "Public Key or Certificate": pegar el contenido de `src/api/SIGCM2.Api/keys/public.pem`
- Verificar:
- Header: `"alg": "RS256"`
- Payload contiene: `sub`, `name` (= `"admin"`), `rol` (= `"admin"`), `permisos` (= `["*"]`), `iss`, `aud`, `exp`
- Footer muestra: **"Signature Verified"** (fondo azul)
**Esperado**: Firma RS256 válida, claims correctos.
### 9. Probar login fallido
- Volver a `http://localhost:5173/login` (o hacer logout si hubiera botón)
- Ingresar `admin` / `wrongpass`
- Hacer click en **Ingresar**
- Verificar en **Network**: `POST /api/v1/auth/login` → Status `401`
- Verificar en la UI: mensaje de error visible con texto **"Credenciales inválidas"** (sin stack trace)
**Esperado**: Error visible en UI, sin exposición de detalles internos.
---
## Resultado esperado global
| Paso | Resultado |
|------|-----------|
| 1. Backend arranca en :5000 | ✅ / ❌ |
| 2. Frontend arranca en :5173 | ✅ / ❌ |
| 3. Redirect a /login | ✅ / ❌ |
| 4. Login con admin/@Diego550@ | ✅ / ❌ |
| 5. Network: POST 200 + JWT | ✅ / ❌ |
| 6. LocalStorage: auth-storage con token | ✅ / ❌ |
| 7. Redirect a / Dashboard | ✅ / ❌ |
| 8. JWT verificado en jwt.io (RS256) | ✅ / ❌ |
| 9. Login fallido: error en UI, 401 en Network | ✅ / ❌ |