> ## Documentation Index
> Fetch the complete documentation index at: https://firespark.cloud/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Inspeccionar token

> Comprueba si un access token de Storefront de Fire spark sigue vigente para que un proxy de un socio pueda reutilizarlo en sus propios endpoints.

Usa este endpoint cuando un socio corre su propia API junto a Storefront y quiere aceptar el **mismo** access token de cliente que Fire spark ya emitió. El socio no emite un token ni recibe el secreto de firma de Fire spark. Envía el token aquí; Fire spark verifica la firma y la expiración.

La solicitud es pública, como el [intercambio de token](https://firespark.cloud/docs/es/storefront-api/oauth/exchange/post.md). Siempre responde `200`. `active` indica si el token sigue vivo.

## Cuándo usar introspección

Usa este endpoint cuando:

* Un canal ya intercambió un ID token OIDC por un access token de Fire spark
* Un proxy o API propia del socio necesita proteger sus rutas con ese mismo token
* El socio solo debe confirmar que el token es real y que sigue dentro de su hora de vida

> [!TIP]
>
> No verifiques el JWT en local. Los access tokens de Storefront se firman con
> un secreto privado de Fire spark. La introspección es la forma soportada para
> que un servidor del socio los compruebe.

## Cómo lo usa el proxy del socio

**1. El canal obtiene un access token de Fire spark**

El cliente autentica al customer con tu proveedor de identidad y llama a
[`POST /oauth/exchange`](https://firespark.cloud/docs/es/storefront-api/oauth/exchange/post). Fire spark
devuelve un token Bearer que dura una hora.

**2. El cliente llama al proxy del socio**

El mismo header `Authorization: Bearer` llega al endpoint del socio. El
socio no decodifica ni confía en el token por su cuenta.

**3. El proxy inspecciona el token**

El proxy envía el token a `POST /oauth/introspect`. Fire spark comprueba la
firma, `aud` y `exp`.

**4. El proxy autoriza su propia ruta**

Si `active` es `true`, compara `merchant_id` y `env` con el tenant del socio
y atiende la solicitud. Cachea el resultado hasta `exp`.

```mermaid theme={null}
sequenceDiagram
  participant Client as Cliente
  participant Proxy as Proxy del socio
  participant Spark as Fire spark
  Client->>Spark: POST /oauth/exchange
  Spark-->>Client: access_token
  Client->>Proxy: Authorization Bearer access_token
  Proxy->>Spark: POST /oauth/introspect
  Spark-->>Proxy: active, merchant_id, exp
  Proxy-->>Client: Respuesta del socio
```

## Solicitud de introspección

Envía un `POST` a `/oauth/introspect` con `Content-Type: application/json`. Esta ruta no requiere header `Authorization`.

```javascript Proxy del socio theme={null}
const token = request.headers.get("authorization")?.replace("Bearer ", "");

const response = await fetch(
  "https://firespark.cloud/api/storefront/v1/oauth/introspect",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ token })
  }
);

const { data } = await response.json();
if (!data.active) {
  return new Response("Unauthorized", { status: 401 });
}
if (data.merchant_id !== MERCHANT_ID) {
  return new Response("Forbidden", { status: 403 });
}
```

```bash cURL theme={null}
curl -X POST "https://firespark.cloud/api/storefront/v1/oauth/introspect" \
  -H "Content-Type: application/json" \
  -d '{ "token": "FIRESPARK_ACCESS_TOKEN" }'
```

```json Activo theme={null}
{
  "data": {
    "active": true,
    "sub": "customer-external-id",
    "customer_id": "customer-external-id",
    "merchant_id": "11111111-1111-4111-8111-111111111111",
    "env": "22222222-2222-4222-8222-222222222222",
    "oauth_app_id": "33333333-3333-4333-8333-333333333333",
    "token_type": "Bearer",
    "exp": 1770000000,
    "env_is_prod": 1
  }
}
```

```json Inactivo theme={null}
{
  "data": {
    "active": false
  }
}
```

### Cuerpo de la solicitud

| Campo | Requerido | Descripción |
| - | - | - |
| `token` | Sí | El access token de Storefront emitido por [`POST /oauth/exchange`](https://firespark.cloud/docs/es/storefront-api/oauth/exchange/post). |

### Campos de la respuesta

| Campo | Cuándo | Descripción |
| - | - | - |
| `active` | Siempre | `true` cuando la firma es válida, `aud` es `storefront` y el token no expiró. |
| `sub` | Activo | Identificador del cliente tomado del `sub` del ID token original. |
| `customer_id` | Activo | El mismo valor que `sub`. |
| `merchant_id` | Activo | Comercio ligado al token. Compáralo con el tenant del socio. |
| `env` | Activo | Ambiente ligado al token. |
| `oauth_app_id` | Activo | App del proveedor de identidad que emitió el ID token original. |
| `token_type` | Activo | Siempre `Bearer`. |
| `exp` | Activo | Expiración Unix en segundos. Cachea el resultado de la introspección hasta ese instante. |
| `env_is_prod` | Activo, si se conoce | `1` en producción, `0` en caso contrario. |

> [!NOTE]
>
> Tokens expirados, falsificados o mal formados devuelven `{ "active": false }`
> con HTTP `200`. El cuerpo no indica el motivo. Si falta `token`, la validación
> responde `400`.

## Caché

Un token vigente sigue siéndolo hasta `exp`. Hoy no hay lista de revocación, así que una caché con clave el token y retención hasta `exp` equivale a una introspección nueva.

```javascript Cachear hasta exp theme={null}
const cached = cache.get(token);
if (cached && cached.exp > Math.floor(Date.now() / 1000)) {
  return cached;
}
const { data } = await introspect(token);
if (data.active) cache.set(token, data);
return data;
```

## Propiedades de seguridad

* **Sin tokens emitidos por el socio:** El único access token es el que Fire spark emitió en el exchange.
* **Sin secreto de firma compartido:** Los socios nunca reciben `AUTH_SECRET`. No pueden falsificar tokens de Storefront.
* **Ligado al comercio:** Compara siempre `merchant_id` (y `env`) antes de servir datos del socio. Un token válido de otro comercio no debe pasar.
* **Vida corta:** Los tokens expiran a la hora. Vuelve a intercambiarlos desde el canal cuando se refresque la sesión del IdP.

> [!WARNING]
>
> Llama siempre a este endpoint por HTTPS. No registres access tokens en logs.
> Trata una respuesta activa como prueba de los claims de cliente y comercio —
> autoriza las acciones propias del socio en tu lado.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.