Cliente API

Session Tokens

Cómo usar session tokens de corta duración para autenticar solicitudes del frontend del plugin hacia tu servidor backend.

Los session tokens son JWTs de corta duración (expiración en 5 minutos) que prueban que una solicitud proviene de un usuario autenticado dentro del admin de Whatalo. Son el puente entre el frontend de tu plugin (iframe) y tu servidor backend.

Los session tokens no otorgan acceso directo a la API de Whatalo. Su propósito es que tu backend sepa que la solicitud entrante es legítima antes de usar tu API key para obtener datos en nombre de ese usuario.

Obtener un Session Token

En el frontend de tu plugin, solicita un token al App Bridge:

import { sessionToken } from "@whatalo/plugin-sdk/bridge";

// Devuelve un token y su tiempo de expiración
const { token, expiresAt } = await sessionToken();

// Enviarlo como Bearer token a tu backend
const response = await fetch("https://tu-backend.com/api/orders", {
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await response.json();

El App Bridge cachea el token y devuelve la copia en caché en llamadas posteriores. Cuando el token tiene 60 segundos o menos hasta su expiración, la próxima llamada a sessionToken() obtiene uno nuevo de forma transparente — no necesitas gestionar esto tú mismo.

Verificar en tu Backend

Usa verifyWhataloSessionToken de @whatalo/plugin-sdk/server para validar el token antes de confiar en la solicitud:

import { verifyWhataloSessionToken } from "@whatalo/plugin-sdk/server";
import { WhataloClient } from "@whatalo/plugin-sdk";

export async function GET(request: Request) {
  const authHeader = request.headers.get("Authorization") ?? "";
  const token = authHeader.replace("Bearer ", "");

  if (!token) {
    return new Response("Falta el header de autorización", { status: 401 });
  }

  // Verificar el token — lanza un error si es inválido o ha expirado
  let claims;
  try {
    claims = verifyWhataloSessionToken(token, process.env.WHATALO_CLIENT_SECRET!);
  } catch (error) {
    return new Response("Session token inválido o expirado", { status: 401 });
  }

  // Token válido — usar la API key para llamar a la API de Whatalo
  const client = new WhataloClient({ apiKey: process.env.WHATALO_API_KEY! });
  const orders = await client.orders.list({ page: 1, per_page: 25 });

  return Response.json(orders);
}

verifyWhataloSessionToken lanza un Error si el token está expirado, la firma no coincide, o la estructura del token es inválida. Captúralo con un bloque try/catch estándar.

Claims del Token

El token decodificado contiene los siguientes claims:

ClaimTipoDescripción
iss"whatalo"Emisor del token — siempre "whatalo"
audstringClient ID de tu plugin
substringID de tienda (igual que storeId)
expnumberTimestamp de expiración (Unix, UTC)
iatnumberTimestamp de emisión (Unix, UTC)
jtistringID único del token — previene ataques de replay
storeIdstringIdentificador público de la tienda
appIdstringID público de tu plugin
scopesstring[]Scopes otorgados por el comerciante al instalar
installationIdstringID del registro de instalación

Verificar Scopes

Si tu endpoint requiere un scope de permiso específico, verifícalo después de validar el token:

const claims = verifyWhataloSessionToken(token, process.env.WHATALO_CLIENT_SECRET!);

if (!claims.scopes.includes("read:orders")) {
  return new Response("Permisos insuficientes", { status: 403 });
}

// Scope confirmado — continuar
const orders = await client.orders.list();

Auto-Refresh

El App Bridge gestiona el ciclo de vida del token automáticamente:

  • Cache hit: Si el token en caché tiene más de 60 segundos restantes, sessionToken() lo devuelve inmediatamente sin una solicitud de red.
  • Refresh proactivo: Si el token tiene 60 segundos o menos, se obtiene uno nuevo antes de devolverlo.
  • Llamadas concurrentes: Múltiples llamadas simultáneas a sessionToken() comparten un solo refresh en vuelo — solo se hace una solicitud de red.

No necesitas almacenar tokens, rastrear tiempos de expiración ni programar lógica de refresh. Llama a sessionToken() antes de cada solicitud a tu backend.

Ejemplo Completo de Solicitud

Un flujo completo frontend-a-backend que obtiene pedidos de la tienda:

import { useEffect, useState } from "react";
import { sessionToken } from "@whatalo/plugin-sdk/bridge";

interface Order {
  id: string;
  status: string;
  total: number;
}

function OrderList() {
  const [orders, setOrders] = useState<Order[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    async function fetchOrders() {
      try {
        // Siempre obtener un session token fresco (o del caché)
        const { token } = await sessionToken();

        const res = await fetch("https://tu-backend.com/api/orders", {
          headers: { Authorization: `Bearer ${token}` },
        });

        if (!res.ok) {
          throw new Error(`Solicitud fallida: ${res.status}`);
        }

        const data = await res.json();
        setOrders(data);
      } catch (err) {
        setError(err instanceof Error ? err.message : "Error al cargar pedidos");
      } finally {
        setLoading(false);
      }
    }

    fetchOrders();
  }, []);

  if (loading) return <p>Cargando pedidos...</p>;
  if (error) return <p>Error: {error}</p>;

  return (
    <ul>
      {orders.map((order) => (
        <li key={order.id}>
          {order.id} — {order.status} — ${order.total}
        </li>
      ))}
    </ul>
  );
}

Notas de Seguridad

  • Siempre verifica en tu backend — nunca confíes en el token sin llamar a verifyWhataloSessionToken. El token está firmado; un token sin verificar no ofrece ninguna garantía de seguridad.
  • Nunca reenvíes el session token a la API de Whatalo — no es aceptado como credencial de la API de Whatalo. Usa tu WHATALO_API_KEY para llamadas a la API de Whatalo.
  • Usa HTTPS en producción — los session tokens solo deben transmitirse sobre conexiones cifradas.
  • No almacenes session tokens del lado del servidor — son de corta duración por diseño. Obtén uno nuevo para cada acción del usuario.
  • Verifica el claim jti para operaciones sensibles — para acciones que no deben repetirse (por ejemplo, crear un pedido), registra los valores jti usados y rechaza los duplicados.

Páginas Relacionadas

On this page