Solicitar Cambio de Contraseña (Paso 1)
Inicia una sesión de cambio de contraseña y genera un token de validación temporal.
Inicia una sesión de cambio de contraseña y genera token de validación
Contexto de Uso
Este endpoint inicia el proceso de cambio de contraseña creando una sesión temporal en Redis que:
- Tiene validez de 5 minutos
- Genera un validationToken único (UUID v4)
- Detecta automáticamente si el usuario tiene 2FA habilitado
- Reutiliza sesiones válidas existentes (previene duplicados)
Este es el Paso 1 de un proceso de dos pasos:
Flujo de Dos Pasos
Paso 1: Request (Este endpoint)
- Crea sesión temporal en Redis (5 minutos)
- Genera
validationTokenúnico (UUID v4) - Determina si se requiere verificación 2FA
- No requiere credenciales en este paso
Paso 2: Execute (Ver documentación)
- Valida el
validationTokenobtenido aquí - Verifica contraseña actual del usuario
- Valida código 2FA (si está habilitado)
- Ejecuta el cambio de contraseña
- Limpia sesión temporal automáticamente
Autenticación requerida: JWT Token válido en header Authorization: Bearer <token>
Validación de Entrada
Autenticación JWT Requerida
Este endpoint requiere un JWT token válido en el header:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
No requiere body en la petición - toda la información se extrae del JWT:
userIdobtenido dereq.user.userIdemailobtenido dereq.user.sub.email
El Guard JwtAuthGuard:
- Valida automáticamente el token
- Si falla, retorna
401 Unauthorized - Si pasa, extrae información del usuario
Tipos de Respuesta
Respuesta para Usuario SIN 2FA
Sesión Creada - Solo Contraseñas
Código 1010 - Sesión de cambio de contraseña creada exitosamente.
{
"event": {
"code": 1010,
"message": "Password change session created"
},
"data": {
"requiresVerification": true,
"verificationType": "PASSWORD_ONLY",
"message": "Please provide current password and new password",
"fields": ["currentPassword", "newPassword"],
"validationToken": "550e8400-e29b-41d4-a716-446655440000"
}
}
Información de la respuesta:
verificationType:PASSWORD_ONLY- Solo se requieren contraseñasfields: Lista de campos necesarios en el Paso 2validationToken: UUID v4 válido por 5 minutosrequiresVerification: Siempretrue
Almacenamiento en Redis:
// Clave: passwordChange:{validationToken}
// Valor: { userId, email, has2FA: false, createdAt }
// TTL: 300000 ms (5 minutos)
Próximos pasos:
- Guardar
validationTokentemporalmente - Solicitar contraseña actual y nueva al usuario
- Usar el token en el Paso 2 (execute)
Respuesta para Usuario CON 2FA
Sesión Creada - Requiere 2FA
Código 1010 - Sesión creada, se requiere verificación 2FA adicional.
{
"event": {
"code": 1010,
"message": "Password change session created"
},
"data": {
"requiresVerification": true,
"verificationType": "2FA_REQUIRED",
"message": "Please provide current password, new password, and 2FA code",
"fields": ["currentPassword", "newPassword", "twoFACode"],
"validationToken": "550e8400-e29b-41d4-a716-446655440000"
}
}
Información de la respuesta:
verificationType:2FA_REQUIRED- Se necesitan contraseñas + código 2FAfields: IncluyetwoFACodeadicionalvalidationToken: UUID v4 válido por 5 minutos- Usuario debe abrir su app autenticadora
Almacenamiento en Redis:
// Clave: passwordChange:{validationToken}
// Valor: { userId, email, has2FA: true, createdAt }
// TTL: 300000 ms (5 minutos)
Próximos pasos:
- Guardar
validationTokentemporalmente - Solicitar contraseña actual, nueva y código 2FA
- Usuario debe obtener código TOTP de su app (Google Authenticator, Authy, etc.)
- Usar el token y código en el Paso 2 (execute)
Errores Posibles
Usuario No Encontrado
Código 4040 - El usuario del JWT no existe en la base de datos.
{
"code": 4040,
"message": "User not found"
}
Causas posibles:
- Email en JWT no corresponde a ningún usuario
- Usuario fue eliminado después de obtener el JWT
- Base de datos inconsistente
Acción requerida:
- Usuario debe cerrar sesión e iniciar sesión nuevamente
- Verificar integridad de la base de datos
Ejemplos de Implementación
JavaScript
async function requestPasswordChange(accessToken) {
try {
const response = await fetch('https://api.swapbits.co/auth/account/password/request', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const result = await response.json();
if (result.event.code === 1010) {
console.log('Sesión creada:', result.data.verificationType);
console.log('Token:', result.data.validationToken);
console.log('Campos requeridos:', result.data.fields);
// Guardar token para el Paso 2
sessionStorage.setItem('validationToken', result.data.validationToken);
sessionStorage.setItem('requires2FA', result.data.verificationType === '2FA_REQUIRED');
return result.data;
}
} catch (error) {
console.error('Error:', error);
throw error;
}
}
TypeScript
interface PasswordChangeSession {
requiresVerification: boolean;
verificationType: 'PASSWORD_ONLY' | '2FA_REQUIRED';
message: string;
fields: string[];
validationToken: string;
}
async function requestPasswordChange(accessToken: string): Promise<PasswordChangeSession> {
const response = await fetch('https://api.swapbits.co/auth/account/password/request', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
const result = await response.json();
if (result.event.code !== 1010) {
throw new Error(result.message || 'Error al solicitar cambio de contraseña');
}
return result.data;
}
Python
import requests
def request_password_change(access_token: str) -> dict:
"""Solicita inicio de sesión de cambio de contraseña"""
url = 'https://api.swapbits.co/auth/account/password/request'
headers = {'Authorization': f'Bearer {access_token}'}
response = requests.post(url, headers=headers)
result = response.json()
if result.get('event', {}).get('code') == 1010:
data = result['data']
print(f"Tipo: {data['verificationType']}")
print(f"Token: {data['validationToken']}")
print(f"Campos: {', '.join(data['fields'])}")
return data
else:
raise Exception(result.get('message', 'Error desconocido'))
cURL
curl -X POST 'https://api.swapbits.co/auth/account/password/request' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN'
Proceso Interno
Flujo del Endpoint
1. Autenticación
// Guard valida JWT automáticamente
const userId = req.user.userId;
const email = req.user.sub.email;
2. Buscar Usuario
const user = await userModel.findOne({ email });
if (!user) throw new NotFoundException({ code: 4040 });
3. Verificar Sesión Existente
// Reutiliza token si ya existe sesión válida
const existingToken = await redis.get(`userToPasswordChange:${userId}`);
if (existingToken) {
const session = await redis.get(`passwordChange:${existingToken}`);
if (session) return existingToken; // Reutiliza
}
4. Detectar Estado 2FA
const has2FA = user.oauth2?.twofa?.is_enabled || false;
5. Generar Token
import { v4 as uuidv4 } from 'uuid';
const validationToken = uuidv4();
6. Almacenar en Redis
const sessionData = {
userId: user._id,
email: user.email,
has2FA,
createdAt: new Date()
};
await redis.setex(
`passwordChange:${validationToken}`,
300, // 5 minutos
JSON.stringify(sessionData)
);
await redis.setex(
`userToPasswordChange:${userId}`,
300,
validationToken
);
7. Retornar Respuesta
return {
event: { code: 1010, message: "Password change session created" },
data: {
requiresVerification: true,
verificationType: has2FA ? '2FA_REQUIRED' : 'PASSWORD_ONLY',
message: has2FA
? "Please provide current password, new password, and 2FA code"
: "Please provide current password and new password",
fields: has2FA
? ['currentPassword', 'newPassword', 'twoFACode']
: ['currentPassword', 'newPassword'],
validationToken
}
};
Códigos de Respuesta
| Código | HTTP Status | Descripción | Acción |
|---|---|---|---|
| 1010 | 200 | Sesión creada exitosamente | Continuar al Paso 2 |
| 4040 | 404 | Usuario no encontrado | Reautenticar usuario |
Probar esta API
API Explorer
Enlaces Relacionados
Proceso de Cambio de Contraseña
- Ejecutar Cambio (Paso 2) - PATCH /auth/account/password
Autenticación y Seguridad
- Login - POST /auth/login
- Configurar 2FA - Activar autenticación de dos factores
- Verificar 2FA - Validar código TOTP
- Olvidé mi Contraseña - Recuperar cuenta sin acceso
Gestión de Cuenta
- Eliminar Cuenta - Eliminación permanente