# Как се свързва приложение с OpenPlatform: стартирането и проверката

> Точното ръкостискане между OpenPlatform и приложение: адресът, с който се отваря, как приложението подписва заявката си към /verify/ и данните за потребителя, които получава.

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

Когато потребител отвори приложение, OpenPlatform не му изпраща парола или бисквитка. Изпраща му **адрес за еднократно стартиране**, а приложението се обажда обратно на OpenPlatform, за да научи кой е потребителят. Тази страница следва кода (`schemas/account.js`, действие `Account/run` и `controllers/verify.js`).

## 1. Стартирането

Когато потребителят щракне върху приложение, порталът извиква API `run/{appid}`. OpenPlatform:

1. проверява дали приложението е в списъка на потребителя (иначе `App not found`) и дали не е деактивирано;
2. създава сесия на приложението (таблица `tbl_app_session`), която изтича според настройката `app_session_expire` (по подразбиране един ден);
3. изгражда **адреса за проверка**: `url` на платформата + `/verify/?token=` + идентификаторът на сесията, свързан с идентификатора на инсталацията чрез `X`, последван от `X` и контролна сума (`FUNC.checksum`, която използва тайната `saltchecksum`);
4. извежда двата токена на тази сесия от споделените тайни на приложението:
   - `reqtoken` = MD5 на адреса за проверка със сол `reqtoken` на приложението, с малки букви;
   - `restoken` = MD5 на този `reqtoken` със сол `restoken` на приложението;
5. отваря приложението на неговия `url` с един допълнителен параметър на заявката: `openplatform=<verification address>~<reqtoken>`.

За приложение, отбелязано като отметка, няма ръкостискане: адресът получава вместо това `ssid=<session checksum>`.

## 2. Проверката

Приложението взема стойността на `openplatform`, която е адресът за проверка, един `~` и `reqtoken` на сесията, и:

1. изчислява **собствения си** `restoken`: MD5 на `reqtoken` със сол `restoken`, който споделя с OpenPlatform;
2. извиква с `GET` цялата стойност на `openplatform` (`~` и `reqtoken` остават в query string) със заглавка `x-token`, зададена на този `restoken`.

След това OpenPlatform (`controllers/verify.js`):

1. разделя токена на заявката при последния `~` (частта след него е `reqtoken`, който е изпратил) и отказва извикването, когато липсва заглавката или токенът;
2. проверява контролната сума на идентификатора на сесията, чете сесията и сравнява двете тайни (`reqtoken` и `restoken` от заглавката); всяка разлика е `Invalid token`;
3. ако приложението има списък с разрешени адреси, проверява адреса на извикващия (`Not allowed IP address`);
4. чете потребителя и отказва деактивиран (`User has been disabled`) или неактивен (`User is inactive`) потребител;
5. гарантира, че потребителят има връзките за известия на това приложение (таблица `tbl_user_app`);
6. изгражда отговора и го прекарва през трансформацията `verify` на платформата, така че едно внедряване да може да добави полета.

Отговорът е JSON обект. Празните стойности се пропускат. Основните му полета са:

| Поле | Какво е |
|---|---|
| `id`, `name`, `email`, `photo`, `gender`, `reference` | кой е потребителят (`photo` е абсолютен адрес) |
| `language`, `color`, `interface`, `darkmode`, `sounds` | предпочитанията (езикът и цветът на платформата, когато потребителят няма) |
| `sa` | потребителят е администратор на платформата |
| `permissions` | низовете `value` на правата на потребителя в това приложение |
| `groups` | идентификаторите на групите на потребителя |
| `appid`, `ssid` | приложението и контролната сума на неговата сесия |
| `openplatformid`, `openplatform` | идентификаторът и адресът на инсталацията |
| `iframe` | `true`, освен ако приложението е външно |
| `notify` | адресът, на който да се изпращат известия, когато потребителят ги приема ([известия](/en/openplatform/notifications-and-public-api/)) |
| `platform` | `name` и `logo` на платформата, нейните `groups` и приложенията на потребителя |

Отговорът се пази в кеш в паметта с ключ токена на сесията (частта преди `~`), а кешът се изчиства на всеки две минути. Извикване с токен, който е в този кеш, получава отговор от него, преди тайните да бъдат сравнени отново; повторна проверка в това време е следователно евтина.

## 3. Питане отново по-късно

`GET /session/` приема `ssid`, който приложението е получило (приема и `openplatformid`, `token` и `session` като име на параметъра), проверява контролната му сума и връща потребителя (`id`, `language`, `name`, `color`, `sa`, `isonline`), докато сесията на потребителя не е изтекла.

## Какво да помните при изграждането на приложението

- Никога не изпращайте споделените тайни към браузъра: нужни са само на сървъра на приложението.
- Проверявайте на **сървъра** и създайте собствена сесия от отговора; параметърът `openplatform` е за едно стартиране.
- Използвайте `permissions` от отговора, а не роля, изпратена от браузъра.
- Total.js 5 има вграден клиент за това семейство протоколи: вижте [OPENCLIENT](/en/total5/openclient-protocol/).
