Saltar al contenido principal

Consultar Estadísticas de Intentos PIN

Endpoint para obtener información detallada sobre los intentos de verificación PIN del usuario autenticado, incluyendo intentos fallidos, estado de bloqueo y tiempo restante.


GET/auth/pin/attempts

Obtiene estadísticas detalladas de intentos de verificación PIN

📤 Respuesta

{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
  "hasAttempts": false,
  "attempts": 0,
  "maxAttempts": 5,
  "remainingAttempts": 5,
  "lastAttempt": null,
  "isBlocked": false,
  "blockedUntil": null
}
}

Flujo de Consulta de Estadísticas

El proceso de consulta de estadísticas de intentos incluye varios pasos:

1. Validación de Autenticación

  • Verificación del token JWT del usuario
  • Confirmación de que el usuario existe y está activo
  • Validación de permisos para acceder a las estadísticas

2. Recopilación de Datos

  • Consulta de intentos fallidos recientes
  • Cálculo de intentos restantes y estado de bloqueo
  • Determinación del tiempo restante de bloqueo (si aplica)

3. Procesamiento de Respuesta

  • Formateo de fechas y horas para claridad
  • Preparación de respuesta estructurada con metadatos útiles
  • Inclusión de información para UI y debugging

Tipos de Respuesta

Respuestas Exitosas

Sin Intentos Fallidos

Código 1001 - El usuario no tiene intentos fallidos registrados.

{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": false,
"attempts": 0,
"maxAttempts": 5,
"remainingAttempts": 5,
"lastAttempt": null,
"isBlocked": false,
"blockedUntil": null
}
}

Campos de respuesta:

  • hasAttempts: false (sin intentos fallidos)
  • attempts: 0 (ningún intento fallido)
  • remainingAttempts: 5 (todos los intentos disponibles)
  • lastAttempt: null (no hay último intento)
  • isBlocked: false (no bloqueado)
  • blockedUntil: null (no tiempo de bloqueo)

Con Intentos Fallidos pero No Bloqueado

Código 1001 - El usuario tiene intentos fallidos pero aún puede intentar.

{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": true,
"attempts": 2,
"maxAttempts": 5,
"remainingAttempts": 3,
"lastAttempt": "2025-01-20T14:40:00.000Z",
"isBlocked": false,
"blockedUntil": null
}
}

Campos de respuesta:

  • hasAttempts: true (tiene intentos fallidos)
  • attempts: 2 (número de intentos fallidos)
  • remainingAttempts: 3 (intentos restantes)
  • lastAttempt: timestamp del último fallo
  • isBlocked: false (aún puede intentar)

Usuario Bloqueado por Intentos Fallidos

Código 1001 - El usuario está bloqueado temporalmente.

{
"code": 1001,
"message": "PIN attempt statistics retrieved successfully",
"data": {
"hasAttempts": true,
"attempts": 5,
"maxAttempts": 5,
"remainingAttempts": 0,
"lastAttempt": "2025-01-20T14:42:00.000Z",
"isBlocked": true,
"blockedUntil": "2025-01-20T14:57:00.000Z"
}
}

Campos de respuesta:

  • hasAttempts: true (tiene intentos fallidos)
  • attempts: 5 (máximo de intentos alcanzado)
  • remainingAttempts: 0 (sin intentos restantes)
  • isBlocked: true (usuario bloqueado)
  • blockedUntil: timestamp hasta cuándo está bloqueado

Errores de Autenticación

Sin Token Válido

Código 401 - No se proporcionó un token JWT válido.

{
"statusCode": 401,
"message": "Unauthorized"
}

Ciclo de Intentos y Bloqueos

Estados de Intentos

Estado Inicial

Sin intentos fallidos:

  • hasAttempts: false
  • attempts: 0
  • remainingAttempts: 5
  • lastAttempt: null
  • isBlocked: false
  • blockedUntil: null

Intentos Fallidos (1-4)

Con intentos fallidos pero no bloqueado:

  • hasAttempts: true
  • attempts: 1-4 (número de fallos)
  • remainingAttempts: 4-1 (intentos restantes)
  • lastAttempt: timestamp del último fallo
  • isBlocked: false
  • blockedUntil: null

Bloqueo por Intentos Excedidos

Después de 5 intentos fallidos:

  • hasAttempts: true
  • attempts: 5
  • remainingAttempts: 0
  • lastAttempt: timestamp del último fallo
  • isBlocked: true
  • blockedUntil: timestamp + 15 minutos

Gestión del Ciclo

Reinicio de Intentos

Los intentos se resetean en los siguientes casos:

  • Verificación exitosa: PIN correcto resetea inmediatamente
  • Expiración del bloqueo: Después de 15 minutos se desbloquea automáticamente
  • Actualización de PIN: Nuevo PIN resetea el contador
  • Revocación de sesiones: Puede afectar según configuración

Duración del Bloqueo

Bloqueo temporal:

  • Duración: 15 minutos desde el último intento fallido
  • Desbloqueo automático: No requiere intervención manual
  • Nuevo bloqueo: Si se intenta durante el bloqueo, se reinicia el contador
  • Persistencia: El bloqueo se mantiene hasta expiración

Campos de Respuesta Detallados

Campos Principales

  • hasAttempts: boolean - Indica si hay intentos fallidos registrados
  • attempts: number - Número actual de intentos fallidos consecutivos (0-5)
  • maxAttempts: number - Siempre 5, límite máximo de intentos
  • remainingAttempts: number - Intentos restantes antes del bloqueo (5-attempts)

Campos de Tiempo

  • lastAttempt: string|null - ISO timestamp del último intento fallido
  • isBlocked: boolean - Estado actual de bloqueo
  • blockedUntil: string|null - ISO timestamp hasta cuándo está bloqueado

Estados Especiales

  • lastAttempt: null cuando no hay intentos fallidos previos
  • blockedUntil: null cuando no está bloqueado
  • attempts: nunca excede maxAttempts (5)
  • remainingAttempts: nunca es negativo

Validaciones y Restricciones

Autenticación Requerida

  • JWT Token: Obligatorio en header Authorization
  • Bearer Token: Formato Bearer <accessToken>
  • Usuario válido: Token debe corresponder a usuario existente y activo

Estado del Usuario

  • Usuario activo: Debe estar activo en el sistema
  • PIN configurado: No es estrictamente necesario para consultar estadísticas
  • Acceso propio: Solo puede consultar sus propias estadísticas

Rate Limiting

  • Consultas frecuentes: Permitidas para monitoreo en tiempo real
  • Sin límites estrictos: Endpoint informativo, no consume intentos
  • Auditoría completa: Todas las consultas quedan registradas

Ejemplos de Implementación

JavaScript/TypeScript

Consultar estadísticas de intentos PIN con Fetch API
const getPINAttempts = async (accessToken) => {
try {
const response = await fetch('https://api.swapbits.co/auth/pin/attempts', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`
}
});

const result = await response.json();

if (result.code === 1001) {
console.log('Estadísticas obtenidas exitosamente');
console.log('Intentos fallidos:', result.data.attempts);
console.log('Intentos restantes:', result.data.remainingAttempts);
console.log('Bloqueado:', result.data.isBlocked);

if (result.data.isBlocked) {
console.log('Bloqueado hasta:', result.data.blockedUntil);
}

return {
success: true,
attempts: result.data
};
} else {
console.error('Error al obtener estadísticas:', result.message);
return { success: false, error: result.message };
}

} catch (error) {
console.error('Error de conexión:', error);
throw error;
}
};

// Uso
getPINAttempts('your-jwt-token-here');

TypeScript con tipos seguros

Consulta de estadísticas con tipos
interface PINAttemptsResponse {
code: number;
message: string;
data: {
hasAttempts: boolean;
attempts: number;
maxAttempts: number;
remainingAttempts: number;
lastAttempt: string | null;
isBlocked: boolean;
blockedUntil: string | null;
};
}

const getPINAttempts = async (accessToken: string): Promise<PINAttemptsResponse> => {
const response = await fetch('https://api.swapbits.co/auth/pin/attempts', {
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});

if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Failed to get PIN attempts');
}

return response.json();
};

// Función de alto nivel para mostrar estado
const displayPINAttemptsStatus = async (accessToken: string) => {
try {
const result = await getPINAttempts(accessToken);

if (result.data.isBlocked) {
const blockedUntil = new Date(result.data.blockedUntil!);
const remainingMinutes = Math.ceil((blockedUntil.getTime() - Date.now()) / (1000 * 60));

return {
status: 'blocked',
message: `Cuenta bloqueada. ${remainingMinutes} minutos restantes.`,
attempts: result.data.attempts,
remainingAttempts: result.data.remainingAttempts,
blockedUntil: blockedUntil
};
} else if (result.data.hasAttempts) {
return {
status: 'warning',
message: `${result.data.remainingAttempts} intentos restantes antes del bloqueo.`,
attempts: result.data.attempts,
remainingAttempts: result.data.remainingAttempts,
lastAttempt: result.data.lastAttempt ? new Date(result.data.lastAttempt) : null
};
} else {
return {
status: 'good',
message: 'Sin intentos fallidos.',
attempts: 0,
remainingAttempts: 5,
lastAttempt: null
};
}
} catch (error) {
console.error('Error getting PIN attempts:', error);
return { status: 'error', message: error.message };
}
};

Python

Consultar estadísticas de intentos PIN con requests
import requests
from typing import Dict, Optional
from datetime import datetime

def get_pin_attempts(access_token: str) -> Dict:
"""
Consultar estadísticas de intentos PIN

Args:
access_token: Token JWT de acceso

Returns:
Diccionario con las estadísticas de intentos
"""
url = 'https://api.swapbits.co/auth/pin/attempts'
headers = {
'Authorization': f'Bearer {access_token}'
}

try:
response = requests.get(url, headers=headers, timeout=10)
result = response.json()

if result['code'] == 1001:
print("Estadísticas obtenidas exitosamente")
data = result['data']

# Procesar fechas
last_attempt = None
if data['lastAttempt']:
last_attempt = datetime.fromisoformat(data['lastAttempt'].replace('Z', '+00:00'))

blocked_until = None
if data['blockedUntil']:
blocked_until = datetime.fromisoformat(data['blockedUntil'].replace('Z', '+00:00'))

return {
'success': True,
'has_attempts': data['hasAttempts'],
'attempts': data['attempts'],
'max_attempts': data['maxAttempts'],
'remaining_attempts': data['remainingAttempts'],
'last_attempt': last_attempt,
'is_blocked': data['isBlocked'],
'blocked_until': blocked_until
}

else:
print(f"Error: {result['message']}")
return {
'success': False,
'error': result['message']
}

except requests.exceptions.RequestException as e:
print(f"Error de conexión: {e}")
return {
'success': False,
'error': str(e)
}

# Ejemplo de uso
if __name__ == '__main__':
result = get_pin_attempts('your-jwt-token-here')

if result['success']:
if result['is_blocked']:
print(f"Cuenta bloqueada hasta: {result['blocked_until']}")
else:
print(f"Intentos fallidos: {result['attempts']}")
print(f"Intentos restantes: {result['remaining_attempts']}")
else:
print(f"Error: {result['error']}")

cURL

Consultar estadísticas de intentos PIN
curl -X GET 'https://api.swapbits.co/auth/pin/attempts' \
-H 'Authorization: Bearer YOUR_JWT_TOKEN'
Consultar y procesar respuesta
#!/bin/bash

ACCESS_TOKEN="your-jwt-token-here"

response=$(curl -s -X GET 'https://api.swapbits.co/auth/pin/attempts' \
-H "Authorization: Bearer $ACCESS_TOKEN")

code=$(echo $response | jq -r '.code')
message=$(echo $response | jq -r '.message')

if [ "$code" = "1001" ]; then
echo "Estadísticas obtenidas exitosamente"

has_attempts=$(echo $response | jq -r '.data.hasAttempts')
attempts=$(echo $response | jq -r '.data.attempts')
remaining=$(echo $response | jq -r '.data.remainingAttempts')
is_blocked=$(echo $response | jq -r '.data.isBlocked')

echo "Intentos fallidos: $attempts"
echo "Intentos restantes: $remaining"

if [ "$is_blocked" = "true" ]; then
blocked_until=$(echo $response | jq -r '.data.blockedUntil')
echo "Cuenta bloqueada hasta: $blocked_until"
else
echo "Cuenta no bloqueada"
fi

else
echo "Error: $message"
fi

Próximos Pasos

Después de Consultar Estadísticas

Una vez obtenidas las estadísticas de intentos:

Si la cuenta no está bloqueada:

  1. Mostrar intentos restantes al usuario
  2. Advertir sobre el riesgo de bloqueo
  3. Permitir intentos de verificación PIN
  4. Actualizar UI en tiempo real

Si la cuenta está bloqueada:

  1. Mostrar tiempo restante de bloqueo
  2. Deshabilitar intentos de verificación
  3. Actualizar contador regresivo
  4. Notificar cuando se desbloquee automáticamente

Para gestionar el estado:

  1. Usar Verificar PIN para intentar verificación
  2. Consultar periódicamente para actualizar estado
  3. Mostrar feedback claro al usuario
  4. Implementar lógica de reintento inteligente

Probar esta API

API Explorer

Visita el API Explorer - Intentos PIN para hacer pruebas interactivas con este endpoint en tiempo real.

En el API Explorer podrás:

  • Consultar estadísticas de intentos actuales
  • Ver diferentes estados (sin intentos, con intentos, bloqueado)
  • Probar respuestas para diferentes escenarios
  • Simular el ciclo completo de intentos y bloqueos
  • Experimentar con consultas en tiempo real

Enlaces Relacionados


Notas Importantes

Consideraciones de Seguridad

  • Endpoint informativo: No consume intentos, solo consulta estado
  • Auditoría completa: Todas las consultas quedan registradas
  • Acceso restringido: Solo el propietario puede ver sus estadísticas
  • Información sensible: Datos de intentos requieren protección
  • Feedback útil: Ayuda a prevenir bloqueos y mejorar UX