# Comment une application se connecte à OpenPlatform : le lancement et la vérification

> La poignée de main exacte entre OpenPlatform et une application : l’adresse avec laquelle elle est ouverte, comment l’application signe sa requête vers /verify/ et les données d’utilisateur qu’elle reçoit en retour.

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

Quand un utilisateur ouvre une application, OpenPlatform ne lui envoie ni mot de passe ni cookie. Il lui envoie une **adresse de lancement à usage unique**, et l’application rappelle OpenPlatform pour savoir qui est l’utilisateur. Cette page suit le code (`schemas/account.js`, action `Account/run`, et `controllers/verify.js`).

## 1. Le lancement

Quand l’utilisateur clique sur une application, le portail appelle l’API `run/{appid}`. OpenPlatform :

1. vérifie que l’application figure dans la liste de l’utilisateur (sinon `App not found`) et qu’elle n’est pas désactivée ;
2. crée une session de l’application (table `tbl_app_session`) qui expire selon le réglage `app_session_expire` (un jour par défaut) ;
3. construit l’**adresse de vérification** : l’`url` de la plateforme + `/verify/?token=` + l’identifiant de la session joint à l’identifiant de l’installation par `X`, suivi de `X` et d’une somme de contrôle (`FUNC.checksum`, qui utilise le secret `saltchecksum`) ;
4. dérive les deux jetons de cette session à partir des secrets partagés de l’application :
   - `reqtoken` = le MD5 de l’adresse de vérification salée avec le `reqtoken` de l’application, en minuscules ;
   - `restoken` = le MD5 de ce `reqtoken` salé avec le `restoken` de l’application ;
5. ouvre l’application à son `url` avec un paramètre de requête supplémentaire : `openplatform=<verification address>~<reqtoken>`.

Pour une application marquée comme signet, il n’y a pas d’échange : l’adresse reçoit `ssid=<session checksum>` à la place.

## 2. La vérification

L’application prend la valeur de `openplatform`, qui est l’adresse de vérification, un `~` et le `reqtoken` de la session, et :

1. calcule **son propre** `restoken` : le MD5 du `reqtoken` salé avec le `restoken` qu’elle partage avec OpenPlatform ;
2. appelle en `GET` la valeur entière de `openplatform` (le `~` et le `reqtoken` restent dans la query string) avec l’en-tête `x-token` fixé à ce `restoken`.

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

1. découpe le jeton de la requête au dernier `~` (la partie qui suit est le `reqtoken` qu’il a envoyé) et refuse l’appel quand l’en-tête ou le jeton manque ;
2. vérifie la somme de contrôle de l’identifiant de session, lit la session et compare les deux secrets (`reqtoken` et le `restoken` de l’en-tête) ; toute différence donne `Invalid token` ;
3. si l’application a une liste d’adresses autorisées, vérifie l’adresse de l’appelant (`Not allowed IP address`) ;
4. lit l’utilisateur et refuse un utilisateur désactivé (`User has been disabled`) ou inactif (`User is inactive`) ;
5. s’assure que l’utilisateur a les liens de notification de cette application (table `tbl_user_app`) ;
6. construit la réponse et la fait passer par la transformation `verify` de la plateforme, de sorte qu’un déploiement puisse ajouter des champs.

La réponse est un objet JSON. Les valeurs vides en sont retirées. Ses principaux champs sont :

| Champ | Ce que c’est |
|---|---|
| `id`, `name`, `email`, `photo`, `gender`, `reference` | qui est l’utilisateur (`photo` est une adresse absolue) |
| `language`, `color`, `interface`, `darkmode`, `sounds` | les préférences (la langue et la couleur de la plateforme quand l’utilisateur n’en a pas) |
| `sa` | l’utilisateur est administrateur de la plateforme |
| `permissions` | les chaînes `value` des permissions de l’utilisateur dans cette application |
| `groups` | les ids des groupes de l’utilisateur |
| `appid`, `ssid` | l’application et la somme de contrôle de sa session |
| `openplatformid`, `openplatform` | l’identifiant et l’adresse de l’installation |
| `iframe` | `true` sauf si l’application est externe |
| `notify` | l’adresse où envoyer les notifications, quand l’utilisateur les accepte ([notifications](/en/openplatform/notifications-and-public-api/)) |
| `platform` | le `name` et le `logo` de la plateforme, ses `groups` et les applications de l’utilisateur |

La réponse est conservée dans un cache en mémoire indexé par le jeton de la session (la partie avant le `~`) et le cache est vidé toutes les deux minutes. Un appel avec un jeton présent dans ce cache reçoit sa réponse depuis lui, avant que les secrets soient comparés à nouveau ; une vérification répétée dans ce délai est donc peu coûteuse.

## 3. Redemander plus tard

`GET /session/` prend le `ssid` que l’application a reçu (elle accepte aussi `openplatformid`, `token` et `session` comme nom du paramètre), vérifie sa somme de contrôle et renvoie l’utilisateur (`id`, `language`, `name`, `color`, `sa`, `isonline`) tant que la session de l’utilisateur n’a pas expiré.

## Ce qu’il faut retenir en construisant l’application

- N’envoyez jamais les secrets partagés au navigateur : seul le serveur de l’application en a besoin.
- Vérifiez sur le **serveur** et créez votre propre session à partir de la réponse ; le paramètre `openplatform` sert pour un seul lancement.
- Utilisez les `permissions` de la réponse, pas un rôle envoyé par le navigateur.
- Total.js 5 possède un client natif pour cette famille de protocoles : voir [OPENCLIENT](/en/total5/openclient-protocol/).
