Analizador JWT

Herramienta para analizar y validar tokens JWT

Resumen de la herramienta: Herramienta de Análisis JWT

JWT (JSON Web Token) es un formato de token compacto y seguro para URL que se utiliza para transferir información de forma segura entre partes. Se utiliza principalmente en autenticación web, autenticación de API, intercambio de información y otros escenarios, siendo una de las tecnologías importantes en el desarrollo web moderno.

¿Qué es Herramienta de Análisis JWT?

Herramienta de Análisis JWT analiza contenido estructurado y resalta campos clave para depuración.

Cómo usarlo

  1. Pega el contenido a analizar.
  2. La herramienta extrae y muestra campos.
  3. Copia los campos que necesitas.

Casos de uso comunes

  • Revisar campos clave en integraciones
  • Depurar estructura y formato
  • Documentar o demostrar datos estructurados

❓ Preguntas frecuentes

P1: ¿Falló el análisis?
R: Asegura que el formato esté completo.

P2: ¿Faltan campos?
R: Verifica que la entrada los contenga.

P3: ¿Valida firmas?
R: Solo analiza; la validación requiere claves.

✨ Características Principales

  • 🔍 Análisis Completo: Análisis detallado de Header, Payload y Signature
  • Validación de Formato: Verificación automática de la exactitud de la estructura JWT
  • 📊 Visualización: Información estructurada mostrada en formato JSON
  • 🔧 Soporte de Depuración: Verificación y depuración de tokens durante el desarrollo
  • 📋 Copia con Un Clic: Los resultados de análisis se pueden copiar directamente

📖 Ejemplos de Uso

JWT Estándar

JWT de Entrada:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikp1YW4gUMOpcmV6IiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Resultado de Análisis:

Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:

{
  "sub": "1234567890",
  "name": "Juan Pérez",
  "iat": 1516239022
}

Signature:

SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Payload Complejo

JWT de Entrada (Claims Complejos):

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMzQ1In0.eyJpc3MiOiJodHRwczovL2F1dGgudG9vbG1pLmNvbSIsInN1YiI6InVzZXJfMTIzNDUiLCJhdWQiOlsiYXBpLnRvb2xtaS5jb20iLCJhZG1pbi50b29sbWkuY29tIl0sImV4cCI6MTY4NzUzNjAwMCwiaWF0IjoxNjg3NDQ5NjAwLCJuYmYiOjE2ODc0NDk2MDAsImp0aSI6ImFiY2RlZi0xMjM0NTYiLCJuYW1lIjoiTWFyw61hIEdhcmPDrWEiLCJlbWFpbCI6Im1hcmlhQGV4YW1wbGUuY29tIiwicm9sZXMiOlsidXNlciIsImFkbWluIl0sInBlcm1pc3Npb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSJdfQ.signature_here

Resultado de Análisis:

Header:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "12345"
}

Payload:

{
  "iss": "https://auth.toolmi.com",
  "sub": "user_12345",
  "aud": ["api.toolmi.com", "admin.toolmi.com"],
  "exp": 1687536000,
  "iat": 1687449600,
  "nbf": 1687449600,
  "jti": "abcdef-123456",
  "name": "María García",
  "email": "maria@example.com",
  "roles": ["user", "admin"],
  "permissions": ["read", "write", "delete"]
}

🎯 Escenarios de Aplicación

1. Sistema de Autenticación Web

Autenticación de usuarios usando JWT:

// Proceso de inicio de sesión
const iniciarSesion = async (email, contraseña) => {
  try {
    const respuesta = await fetch('/api/auth/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email, contraseña })
    });

    if (respuesta.ok) {
      const datos = await respuesta.json();
      const token = datos.token;
      
      // Guardar JWT en almacenamiento local
      localStorage.setItem('authToken', token);
      
      // Analizar contenido del token
      const payload = analizarJWT(token);
      console.log('Información del usuario:', payload);
      
      return { exito: true, usuario: payload };
    } else {
      throw new Error('Error al iniciar sesión');
    }
  } catch (error) {
    console.error('Error de inicio de sesión:', error);
    return { exito: false, error: error.message };
  }
};

// Función de análisis JWT
const analizarJWT = (token) => {
  try {
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
    
    return JSON.parse(jsonPayload);
  } catch (error) {
    console.error('Error de análisis JWT:', error);
    return null;
  }
};

// Verificar estado de autenticación
const verificarEstadoAuth = () => {
  const token = localStorage.getItem('authToken');
  if (!token) {
    return { autenticado: false };
  }

  const payload = analizarJWT(token);
  if (!payload) {
    return { autenticado: false };
  }

  // Verificar fecha de expiración del token
  const tiempoActual = Math.floor(Date.now() / 1000);
  if (payload.exp && payload.exp < tiempoActual) {
    localStorage.removeItem('authToken');
    return { autenticado: false, razon: 'expirado' };
  }

  return { 
    autenticado: true, 
    usuario: payload,
    expiraEn: payload.exp 
  };
};

2. Autenticación de API

Uso de JWT en solicitudes de API:

// Clase cliente API
class ClienteAPI {
  constructor(urlBase) {
    this.urlBase = urlBase;
    this.token = localStorage.getItem('authToken');
  }

  // Solicitud con encabezado de autenticación
  async solicitud(endpoint, opciones = {}) {
    const url = `${this.urlBase}${endpoint}`;
    const encabezados = {
      'Content-Type': 'application/json',
      ...opciones.encabezados
    };

    // Agregar token JWT al encabezado Authorization
    if (this.token) {
      encabezados.Authorization = `Bearer ${this.token}`;
    }

    try {
      const respuesta = await fetch(url, {
        ...opciones,
        headers: encabezados
      });

      // Si hay error 401, el token es inválido
      if (respuesta.status === 401) {
        this.manejarNoAutorizado();
        throw new Error('Se requiere autenticación');
      }

      if (!respuesta.ok) {
        throw new Error(`Error HTTP! estado: ${respuesta.status}`);
      }

      return await respuesta.json();
    } catch (error) {
      console.error('Error de solicitud API:', error);
      throw error;
    }
  }

  // Manejo de error de autenticación
  manejarNoAutorizado() {
    localStorage.removeItem('authToken');
    this.token = null;
    // Redirigir a página de inicio de sesión
    window.location.href = '/login';
  }

  // Actualizar token
  actualizarToken(nuevoToken) {
    this.token = nuevoToken;
    localStorage.setItem('authToken', nuevoToken);
  }

  // Obtener perfil de usuario
  async obtenerPerfilUsuario() {
    return await this.solicitud('/api/user/profile');
  }

  // Obtener datos
  async obtenerDatos(endpoint) {
    return await this.solicitud(endpoint);
  }

  // Actualizar datos
  async actualizarDatos(endpoint, datos) {
    return await this.solicitud(endpoint, {
      method: 'PUT',
      body: JSON.stringify(datos)
    });
  }
}

// Ejemplo de uso
const clienteApi = new ClienteAPI('https://api.toolmi.com');

// Obtener perfil de usuario
clienteApi.obtenerPerfilUsuario()
  .then(perfil => {
    console.log('Perfil de usuario:', perfil);
  })
  .catch(error => {
    console.error('Error al obtener perfil:', error);
  });

3. Renovación de Token

Sistema de renovación automática de JWT:

// Gestor de renovación de token
class GestorToken {
  constructor() {
    this.tokenAcceso = localStorage.getItem('tokenAcceso');
    this.tokenRenovacion = localStorage.getItem('tokenRenovacion');
    this.promesaRenovacion = null;
  }

  // Obtener token de acceso
  obtenerTokenAcceso() {
    return this.tokenAcceso;
  }

  // Verificar si el token ha expirado
  tokenExpirado(token) {
    if (!token) return true;

    try {
      const payload = this.analizarJWT(token);
      const tiempoActual = Math.floor(Date.now() / 1000);
      
      // Considerar expirado 5 minutos antes de la fecha de expiración
      return payload.exp < (tiempoActual + 300);
    } catch (error) {
      return true;
    }
  }

  // Análisis JWT
  analizarJWT(token) {
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
      return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
    
    return JSON.parse(jsonPayload);
  }

  // Renovar token de acceso
  async renovarTokenAcceso() {
    if (this.promesaRenovacion) {
      return this.promesaRenovacion;
    }

    this.promesaRenovacion = this.realizarRenovacion();
    
    try {
      const resultado = await this.promesaRenovacion;
      return resultado;
    } finally {
      this.promesaRenovacion = null;
    }
  }

  async realizarRenovacion() {
    if (!this.tokenRenovacion) {
      throw new Error('No hay token de renovación');
    }

    try {
      const respuesta = await fetch('/api/auth/refresh', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          tokenRenovacion: this.tokenRenovacion
        })
      });

      if (!respuesta.ok) {
        throw new Error('Error al renovar token');
      }

      const datos = await respuesta.json();
      
      this.tokenAcceso = datos.tokenAcceso;
      this.tokenRenovacion = datos.tokenRenovacion;
      
      localStorage.setItem('tokenAcceso', this.tokenAcceso);
      localStorage.setItem('tokenRenovacion', this.tokenRenovacion);

      return this.tokenAcceso;
    } catch (error) {
      // Si falla la renovación, cerrar sesión
      this.cerrarSesion();
      throw error;
    }
  }

  // Obtener token de acceso válido (renovar si es necesario)
  async obtenerTokenAccesoValido() {
    if (!this.tokenExpirado(this.tokenAcceso)) {
      return this.tokenAcceso;
    }

    return await this.renovarTokenAcceso();
  }

  // Cerrar sesión
  cerrarSesion() {
    this.tokenAcceso = null;
    this.tokenRenovacion = null;
    localStorage.removeItem('tokenAcceso');
    localStorage.removeItem('tokenRenovacion');
  }
}

// Ejemplo de uso
const gestorToken = new GestorToken();

// Verificar token antes de solicitud API
const hacerSolicitudAutenticada = async (url, opciones = {}) => {
  try {
    const token = await gestorToken.obtenerTokenAccesoValido();
    
    const respuesta = await fetch(url, {
      ...opciones,
      headers: {
        ...opciones.headers,
        'Authorization': `Bearer ${token}`
      }
    });

    return respuesta;
  } catch (error) {
    console.error('Error de solicitud autenticada:', error);
    // Redirigir a página de inicio de sesión
    window.location.href = '/login';
  }
};

🔧 Detalles Técnicos

Estructura JWT

JWT está compuesto por tres partes:

1. Header (Encabezado)

{
  "alg": "HS256",    // Algoritmo de firma
  "typ": "JWT"       // Tipo de token
}

2. Payload (Carga útil)

{
  "iss": "issuer",           // Emisor
  "sub": "subject",          // Sujeto
  "aud": "audience",         // Audiencia
  "exp": 1234567890,         // Fecha de expiración
  "iat": 1234567890,         // Tiempo de emisión
  "nbf": 1234567890,         // No válido antes de
  "jti": "jwt-id"            // ID JWT
}

3. Signature (Firma)

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

Claims Estándar

Claims estándar utilizados en JWT:

  • iss (Issuer): Emisor del token
  • sub (Subject): Sujeto del token (generalmente ID de usuario)
  • aud (Audience): Audiencia del token
  • exp (Expiration Time): Fecha de expiración (timestamp Unix)
  • iat (Issued At): Tiempo de emisión
  • nbf (Not Before): Tiempo de inicio de validez
  • jti (JWT ID): Identificador único del JWT

💡 Consejos de Uso

  • Verificación de Expiración: Verificar la fecha de expiración del token con el claim exp
  • Seguridad: No incluir información confidencial en el payload
  • Verificación de Firma: Siempre verificar la firma en entorno de producción
  • Tamaño del Token: Prestar atención a que el payload no sea demasiado grande

⚠️ Notas Importantes

  • Información Confidencial: El payload de JWT no está cifrado, por lo que no debe incluir información confidencial
  • Verificación de Firma: Esta herramienta solo analiza, no verifica firmas
  • Fecha de Expiración: No usar tokens expirados
  • Lugar de Almacenamiento: Prestar atención al lugar de almacenamiento de tokens en el navegador (prevención XSS)

🚀 Cómo Usar

  1. Entrada JWT: Pegue el token JWT a analizar en el cuadro de entrada
  2. Análisis Automático: Header, Payload y Signature se analizan automáticamente al ingresar
  3. Verificación de Resultados: Verifique la información detallada de cada parte en formato JSON
  4. Uso de Copia: Use el botón "Copiar" para copiar los resultados de análisis al portapapeles
  5. Uso en Depuración: Use para verificación y depuración de tokens durante el desarrollo

Consejo: Esta herramienta procesa localmente en el lado del cliente y no envía tokens JWT al servidor, garantizando la seguridad.