# Verificar la identidad en el widget

Firma en tu servidor el userId de cada persona con el secreto del widget para que nadie lea ni escriba los tickets de otra cambiando ese valor.

La clave del widget va en tu página, así que cualquiera puede copiarla, y el `userId` lo pone el navegador. Sin más, quien copie la clave puede leer y escribir los tickets de otra persona con solo cambiar ese valor. La verificación de identidad lo impide: tu **servidor**, que sabe quién ha iniciado sesión, firma el `userId` con el **secreto del widget**, y UTILIA OS comprueba la firma en cada petición antes de enseñar o tocar los tickets de esa persona.

## Cómo funciona

**Una petición del widget con la identidad verificada**

Participantes: Tu servidor, Navegador y UTILIA OS.

1. Tu servidor → Navegador: Página con userId y userSignature. La firma es el HMAC-SHA256 del userId con el secreto del widget.
2. Navegador → UTILIA OS: Petición del widget con X-Utilia-User-Signature. Junto a la clave de la aplicación y el userId.
3. UTILIA OS (por su cuenta): Recalcula la firma con el secreto y la compara.
4. UTILIA OS → Navegador (respuesta): Los tickets de esa persona. Sin una firma válida, 403.

_El secreto nunca sale de tu servidor: a la página solo llega la firma._

El secreto del widget es distinto de la clave de API de la aplicación y de su clave de firma de los avisos. Cada aplicación tiene el suyo.

## Antes de empezar

- La versión **1.2.0** del widget (`@utilia-os/widget`), que trae la opción `userSignature` y sus atributos. Todavía no está publicada: hasta entonces, el widget que instalas no manda la firma. Por eso las aplicaciones nuevas nacen en **Solo avisar**: no bloquea a nadie y te deja ver qué fallaría.
- El permiso «Editar las aplicaciones creadas por la empresa» para generar el secreto y cambiar el modo. Generar el secreto pide además la verificación en dos pasos.
- Un servidor que pinte la página del widget sabiendo quién ha iniciado sesión.

## Paso a paso

1. **Genera el secreto del widget**

   Abre la aplicación en **Ajustes › Creadas por tu empresa** y entra en **Configuración › Ajustes**, pestaña **Widget**. En el bloque **Verificación de identidad**, pulsa **Generar el secreto** o, si ya hay uno, **Renovar el secreto**, y confirma con tu segundo paso.

   El secreto (empieza por `utw_`) se enseña **una sola vez**: cópialo y pulsa **Ya lo he guardado**.
2. **Guárdalo en tu servidor**

   En una variable de entorno o en tu gestor de secretos, como `UTILIA_WIDGET_SECRET`. Nunca en la página, en el repositorio ni en una aplicación móvil.
3. **Firma el userId al pintar la página**

   La firma es el HMAC-SHA256 del `userId` con el secreto, en hexadecimal. Calcúlala sobre el mismo valor exacto que le pasas al widget.

   **Node.js**

   ```javascript
   import { createHmac } from 'node:crypto';

   const userSignature = createHmac('sha256', process.env.UTILIA_WIDGET_SECRET)
     .update(user.id)
     .digest('hex');
   ```

   **PHP**

   ```php
   $userSignature = hash_hmac('sha256', $user->id, getenv('UTILIA_WIDGET_SECRET'));
   ```

   **Python**

   ```python
   import hashlib
   import hmac
   import os

   user_signature = hmac.new(
       os.environ["UTILIA_WIDGET_SECRET"].encode(), user.id.encode(), hashlib.sha256
   ).hexdigest()
   ```
4. **Pásale la firma al widget**

   Junto al `userId`, con la forma de instalarlo que uses:

   - Etiqueta de script: `data-user-signature="..."`.
   - Paquete npm: la opción `userSignature`.
   - Componente web: el atributo `user-signature`.

   El widget la manda en la cabecera `X-Utilia-User-Signature` de cada petición.
5. **Elige el modo**

   En el mismo bloque, **Cómo se comprueba**: empieza por **Solo avisar** y, cuando todas las páginas del widget manden la firma, cambia a **Obligatoria**.

## Los tres modos

**Cómo se comprueba la identidad**

### Desactivada (No se comprueba)

Quien conozca el identificador de una persona puede escribir en su nombre.

### Solo avisar (Para probar)

Se comprueba y se registra el fallo, sin bloquear nada.

### Obligatoria (Recomendado · Recomendado)

Sin una firma válida, la petición se rechaza con 403.

Se comprueba en las peticiones que llevan un `userId` hechas con una clave publicada: la de una aplicación con dominios autorizados, o una que se ha usado desde un navegador. Desde tu servidor, con la clave de una aplicación sin dominios autorizados, no se comprueba: esa clave es secreta y quien la usa ya es tu servidor. Las conexiones de eventos en tiempo real quedan atadas al `userId` con el que se pidió su pase.

## Si ya usas el widget

Las aplicaciones creadas antes de que existiera la verificación están en **Desactivada**: siguen funcionando como siempre, y su diagnóstico avisa con [`widget-identity-not-verified`](https://os.utilia.ai/docs/developers/getting-started/testing#widget-identity-not-verified). Para pasar a la verificación sin cortes:

1. Actualiza el widget a la 1.2.0.
2. Genera el secreto y firma el `userId` en tu servidor.
3. Pon el modo en **Solo avisar** mientras despliegas la firma en todas las páginas que cargan el widget.
4. Cambia a **Obligatoria**. Si alguna página quedó sin firmar, sus peticiones aparecen rechazadas en la pestaña **Pruebas** de la aplicación.

Las aplicaciones nuevas nacen en **Solo avisar** y sin secreto. Cuando vayas a firmar, genera el secreto en el panel del widget (se enseña una sola vez) y, con el widget 1.2.0 firmando, pasa a **Obligatoria**.

## Renovar el secreto

Al renovarlo, el anterior deja de valer en el acto. Con el modo en **Obligatoria**, hasta que tu servidor firme con el nuevo, el widget no identifica a nadie. Para renovarlo sin cortes, pasa antes a **Solo avisar**, renueva, actualiza tu servidor y vuelve a **Obligatoria**.

## Si algo falla

- **`403 WIDGET_IDENTITY_REQUIRED`**: la petición no trae la firma. Comprueba que pasas `userSignature` al widget y que usas la versión 1.2.0. Ver [el error](https://os.utilia.ai/docs/developers/getting-started/errors-and-retries#widget_identity_required).
- **`403 WIDGET_IDENTITY_INVALID`**: la firma no corresponde a ese `userId`. Se calculó con un secreto que ya no vale, para otro usuario o sobre otro valor. Ver [el error](https://os.utilia.ai/docs/developers/getting-started/errors-and-retries#widget_identity_invalid).
- **`403 WIDGET_IDENTITY_SECRET_MISSING`**: el modo es **Obligatoria** y la aplicación no tiene secreto. Genéralo. Ver [el error](https://os.utilia.ai/docs/developers/getting-started/errors-and-retries#widget_identity_secret_missing).
- **«Con la verificación obligatoria y sin secreto, el widget no identifica a nadie.»**: lo dice el bloque cuando falta el secreto. Pulsa **Generar el secreto**.
