# Cómo se conecta una aplicación a OpenPlatform: el lanzamiento y la verificación

> El apretón de manos exacto entre OpenPlatform y una aplicación: la dirección con la que se abre, cómo la aplicación firma su petición a /verify/ y los datos del usuario que recibe.

Framework: openplatform
Product: OpenPlatform (openplatform@5)
Language: es
Content-SHA256: ddc0052d69cab4d2750e0ffc6a5a58a01975426851e125bb9d17666abacab9ed
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: 
Review: not-recorded

Cuando un usuario abre una aplicación, OpenPlatform no le envía una contraseña ni una cookie. Le envía una **dirección de lanzamiento de un solo uso**, y la aplicación vuelve a llamar a OpenPlatform para saber quién es el usuario. Esta página sigue el código (`schemas/account.js`, acción `Account/run`, y `controllers/verify.js`).

## 1. El lanzamiento

Cuando el usuario hace clic en una aplicación, el portal llama a la API `run/{appid}`. OpenPlatform:

1. comprueba que la aplicación está en la lista del usuario (si no, `App not found`) y que no está deshabilitada;
2. crea una sesión de la aplicación (tabla `tbl_app_session`) que caduca según el ajuste `app_session_expire` (un día por defecto);
3. construye la **dirección de verificación**: la `url` de la plataforma + `/verify/?token=` + el identificador de la sesión unido al identificador de la instalación con `X`, seguido de `X` y una suma de comprobación (`FUNC.checksum`, que usa el secreto `saltchecksum`);
4. deriva los dos tokens de esa sesión a partir de los secretos compartidos de la aplicación:
   - `reqtoken` = el MD5 de la dirección de verificación con la sal del `reqtoken` de la aplicación, en minúsculas;
   - `restoken` = el MD5 de ese `reqtoken` con la sal del `restoken` de la aplicación;
5. abre la aplicación en su `url` con un parámetro de consulta adicional: `openplatform=<verification address>~<reqtoken>`.

Para una aplicación marcada como marcador no hay apretón de manos: la dirección recibe `ssid=<session checksum>` en su lugar.

## 2. La verificación

La aplicación toma el valor de `openplatform`, que es la dirección de verificación, un `~` y el `reqtoken` de la sesión, y:

1. calcula **su propio** `restoken`: el MD5 del `reqtoken` con la sal del `restoken` que comparte con OpenPlatform;
2. llama con `GET` al valor completo de `openplatform` (el `~` y el `reqtoken` se quedan en la query string) con la cabecera `x-token` puesta a ese `restoken`.

Entonces OpenPlatform (`controllers/verify.js`):

1. divide el token de la consulta en el último `~` (la parte posterior es el `reqtoken` que envió) y rechaza la llamada cuando falta la cabecera o el token;
2. comprueba la suma de comprobación del identificador de sesión, lee la sesión y compara ambos secretos (`reqtoken` y el `restoken` de la cabecera); cualquier diferencia es `Invalid token`;
3. si la aplicación tiene una lista de direcciones permitidas, comprueba la dirección del llamante (`Not allowed IP address`);
4. lee al usuario y rechaza a un usuario deshabilitado (`User has been disabled`) o inactivo (`User is inactive`);
5. se asegura de que el usuario tiene los enlaces de notificación de esta aplicación (tabla `tbl_user_app`);
6. construye la respuesta y la pasa por la transformación `verify` de la plataforma, de modo que un despliegue pueda añadir campos.

La respuesta es un objeto JSON. Los valores vacíos se descartan. Sus campos principales son:

| Campo | Qué es |
|---|---|
| `id`, `name`, `email`, `photo`, `gender`, `reference` | quién es el usuario (`photo` es una dirección absoluta) |
| `language`, `color`, `interface`, `darkmode`, `sounds` | las preferencias (el idioma y el color de la plataforma cuando el usuario no tiene) |
| `sa` | el usuario es administrador de la plataforma |
| `permissions` | las cadenas `value` de los permisos del usuario en esta aplicación |
| `groups` | los ids de los grupos del usuario |
| `appid`, `ssid` | la aplicación y la suma de comprobación de su sesión |
| `openplatformid`, `openplatform` | el identificador y la dirección de la instalación |
| `iframe` | `true` salvo que la aplicación sea externa |
| `notify` | la dirección a la que enviar notificaciones, cuando el usuario las acepta ([notificaciones](/en/openplatform/notifications-and-public-api/)) |
| `platform` | el `name` y el `logo` de la plataforma, sus `groups` y las aplicaciones del usuario |

La respuesta se guarda en una caché en memoria con clave el token de la sesión (la parte anterior al `~`) y la caché se vacía cada dos minutos. Una llamada con un token que está en esa caché se responde desde ella, antes de volver a comparar los secretos, de modo que una verificación repetida en ese tiempo es barata.

## 3. Preguntar de nuevo más tarde

`GET /session/` recibe el `ssid` que recibió la aplicación (también acepta `openplatformid`, `token` y `session` como nombre del parámetro), comprueba su suma de comprobación y devuelve al usuario (`id`, `language`, `name`, `color`, `sa`, `isonline`) mientras la sesión del usuario no haya caducado.

## Qué recordar al construir la aplicación

- Nunca envíes los secretos compartidos al navegador: solo los necesita el servidor de la aplicación.
- Verifica en el **servidor** y crea tu propia sesión a partir de la respuesta; el parámetro `openplatform` es para un solo lanzamiento.
- Usa los `permissions` de la respuesta, no un rol que envíe el navegador.
- Total.js 5 tiene un cliente nativo para esta familia de protocolos: consulta [OPENCLIENT](/en/total5/openclient-protocol/).
