# Como uma aplicação se liga ao OpenPlatform: o lançamento e a verificação

> O aperto de mão exato entre o OpenPlatform e uma aplicação: o endereço com que é aberta, como a aplicação assina o seu pedido a /verify/ e os dados do utilizador que recebe.

Framework: openplatform
Product: OpenPlatform (openplatform@5)
Language: pt
Content-SHA256: 7e78764d50a71fdbe41a064d7eb0c697fcbc0959ebb939dcd7887ea196ec1f8f
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: 
Review: not-recorded

Quando um utilizador abre uma aplicação, o OpenPlatform não lhe envia uma palavra-passe nem um cookie. Envia-lhe um **endereço de lançamento de utilização única**, e a aplicação volta a chamar o OpenPlatform para saber quem é o utilizador. Esta página segue o código (`schemas/account.js`, ação `Account/run`, e `controllers/verify.js`).

## 1. O lançamento

Quando o utilizador clica numa aplicação, o portal chama a API `run/{appid}`. O OpenPlatform:

1. verifica que a aplicação está na lista do utilizador (caso contrário `App not found`) e que não está desativada;
2. cria uma sessão da aplicação (tabela `tbl_app_session`) que expira segundo a definição `app_session_expire` (um dia por predefinição);
3. constrói o **endereço de verificação**: o `url` da plataforma + `/verify/?token=` + o identificador da sessão unido ao identificador da instalação com `X`, seguido de `X` e de uma soma de verificação (`FUNC.checksum`, que usa o segredo `saltchecksum`);
4. deriva os dois tokens dessa sessão a partir dos segredos partilhados da aplicação:
   - `reqtoken` = o MD5 do endereço de verificação com o sal do `reqtoken` da aplicação, em minúsculas;
   - `restoken` = o MD5 desse `reqtoken` com o sal do `restoken` da aplicação;
5. abre a aplicação no seu `url` com um parâmetro de consulta extra: `openplatform=<verification address>~<reqtoken>`.

Para uma aplicação marcada como marcador não há aperto de mão: o endereço recebe `ssid=<session checksum>` em seu lugar.

## 2. A verificação

A aplicação toma o valor de `openplatform`, que é o endereço de verificação, um `~` e o `reqtoken` da sessão, e:

1. calcula o **seu próprio** `restoken`: o MD5 do `reqtoken` com o sal do `restoken` que partilha com o OpenPlatform;
2. chama com `GET` o valor completo de `openplatform` (o `~` e o `reqtoken` ficam na query string) com o cabeçalho `x-token` definido com esse `restoken`.

O OpenPlatform então (`controllers/verify.js`):

1. divide o token da consulta no último `~` (a parte seguinte é o `reqtoken` que enviou) e recusa a chamada quando falta o cabeçalho ou o token;
2. verifica a soma de verificação do identificador de sessão, lê a sessão e compara ambos os segredos (`reqtoken` e o `restoken` do cabeçalho); qualquer diferença é `Invalid token`;
3. se a aplicação tem uma lista de endereços permitidos, verifica o endereço do chamador (`Not allowed IP address`);
4. lê o utilizador e recusa um utilizador desativado (`User has been disabled`) ou inativo (`User is inactive`);
5. garante que o utilizador tem as ligações de notificação desta aplicação (tabela `tbl_user_app`);
6. constrói a resposta e passa-a pela transformação `verify` da plataforma, para que uma instalação possa acrescentar campos.

A resposta é um objeto JSON. Os valores vazios são removidos. Os seus campos principais são:

| Campo | O que é |
|---|---|
| `id`, `name`, `email`, `photo`, `gender`, `reference` | quem é o utilizador (`photo` é um endereço absoluto) |
| `language`, `color`, `interface`, `darkmode`, `sounds` | as preferências (o idioma e a cor da plataforma quando o utilizador não tem) |
| `sa` | o utilizador é administrador da plataforma |
| `permissions` | as cadeias `value` das permissões do utilizador nesta aplicação |
| `groups` | os ids dos grupos do utilizador |
| `appid`, `ssid` | a aplicação e a soma de verificação da sua sessão |
| `openplatformid`, `openplatform` | o identificador e o endereço da instalação |
| `iframe` | `true` a menos que a aplicação seja externa |
| `notify` | o endereço para onde enviar notificações, quando o utilizador as aceita ([notificações](/en/openplatform/notifications-and-public-api/)) |
| `platform` | o `name` e o `logo` da plataforma, os seus `groups` e as aplicações do utilizador |

A resposta é guardada numa cache em memória com chave o token da sessão (a parte antes do `~`) e a cache é limpa a cada dois minutos. Uma chamada com um token que está nessa cache é respondida a partir dela, antes de os segredos voltarem a ser comparados; uma verificação repetida nesse tempo é por isso barata.

## 3. Perguntar de novo mais tarde

`GET /session/` recebe o `ssid` que a aplicação recebeu (também aceita `openplatformid`, `token` e `session` como nome do parâmetro), verifica a sua soma de verificação e devolve o utilizador (`id`, `language`, `name`, `color`, `sa`, `isonline`) enquanto a sessão do utilizador não tiver expirado.

## O que lembrar ao construir a aplicação

- Nunca envie os segredos partilhados para o navegador: só o servidor da aplicação precisa deles.
- Verifique no **servidor** e crie a sua própria sessão a partir da resposta; o parâmetro `openplatform` serve para um só lançamento.
- Use as `permissions` da resposta, não um papel que o navegador envie.
- O Total.js 5 tem um cliente nativo para esta família de protocolos: veja [OPENCLIENT](/en/total5/openclient-protocol/).
