02 Auth DAP IoBase
/Token ou /refresh avec le même token = device en erreur permanent. Recovery = suppression manuelle du device par l'admin Terega + recommencer toute la procédure d'enrôlement. Toute l'architecture ci-dessous existe pour rendre cette situation impossible.
Source de vérité
La doc officielle : Centre d'aide io-base · Procédure d'authentification via le DAP (extraits ci-dessous).
Endpoints DAP
| Endpoint | Méthode | Body | Réponse OK | Réponse KO |
|---|---|---|---|---|
/register |
POST | {"name": "<device_name>"} |
200 + {device_code} |
403 name déjà pris |
/Token |
POST | {"device_code": "<...>", "client_id": "<device_name>"} |
200 + {access_token, refresh_token} |
425 en attente validation admin Terega |
/refresh |
POST | {"refresh_token": "<...>", "client_id": "<device_name>"} |
200 + {access_token, refresh_token} (nouveaux) |
401 refresh_token déjà consommé |
Cycle de vie
Les 5 protections critiques
1 · Mutex single-use
Au début de build_dap_token et build_dap_refresh, on vérifie le flag global.dap_refreshing. Si déjà true, on log DAP_REFRESH_SKIP mutex et on retourne nil. Sinon on le set à true et on continue.
Dans handle_dap_resp, le flag est reset à false aussi bien sur succès que sur échec, garantissant qu'aucun deadlock n'est possible.
2 · Persistance flash
À chaque token update (register, token, refresh), handle_dap_resp propage msg.dap_persist contenant la nouvelle state. fn_persist_dap attache msg.filename = '/mnt/data/luvitred/dap_state.json', le node save dap state (file out, overwriteFile=true) écrit. Format :
{
"device_code": "DC...",
"access_token": "AT...",
"refresh_token": "RT...",
"saved_at": 1714056789
}
3 · Restore au boot
Au démarrage du flow (deploy ou reboot CG) :
inj_load_dap_state(once @startup, +3s)file_load_dap_statelit le JSON depuis flashfn_restore_dap_stateparse via regex (sandbox Lua n'a pas json.decode garanti) et set les globals
Résultat : un reboot CG ne nécessite pas de re-enrôlement Jean-Marc. Les tokens restent valides jusqu'à expiration naturelle.
4 · Retry sur 401
handle_iobase_resp et handle_health_resp émettent msg avec statusCode=401 vers fn_trigger_refresh_on_401 qui filtre, puis émet vers build_dap_refresh. Le mutex protège des refreshes en rafale (par ex. 10 trames qui prennent 401 d'affilée → 1 seul refresh est tiré).
La trame en échec est mise dans la queue offline (queueenabled=true) et sera replay automatiquement avec le nouveau token.
5 · Refresh préventif au retour de WAN
handle_cg_metrics (kind=internet) maintient global.wan_connected. Sur transition false → true, il émet un msg vers build_dap_refresh. Avantage : après une coupure WAN longue (> 50 min, le cron ratera) on est sûr d'avoir un access_token valide avant que la queue ne se déverse → pas de boucle de 401.
Validation par tests
| Scénario | Test | Résultat attendu | Mesuré |
|---|---|---|---|
| Refresh concurrent | Tirer 3 fois en parallèle l'inject DAP refresh |
Mock voit 1 POST /refresh, pas 3 |
delta = 1 |
| Persistance après token | Run register + Token, puis cat /mnt/data/luvitred/dap_state.json |
Fichier 159 bytes avec device_code + access + refresh + saved_at | OK 159 bytes |
| Restore au boot | Tirer load dap @startup (sans refaire register/Token) |
Globals repopulés depuis le fichier flash | DAP_RESTORE_OK age=12s |
| Retry 401 | Force un faux access_token, trigger un health POST | Mock 401 → trigger refresh auto → has_access redevient True (delta DAP=1) | DAP_REFRESH_OK delta=1 |
| WAN false→true | Logique en place (revue de code), pas testé en live (demande coupure WAN) | Trigger refresh préventif | code review only |
Globals utilisés
'host:port' (préfixe http:// ajouté par les builds).name envoyé à /register et client_id envoyé à /Token + /refresh. Default : cloudgate-terega-01.handle_dap_resp sur register OK. Persisté.true pendant un refresh ou Token en cours. Reset par handle_dap_resp.Procédure de premier enrôlement
- Set
global.dap_hostpar inject startup ou console Lua → URL réelle Terega - Tirer l'inject
DAP register(manuel) - Vérifier dans le canvas debug :
DAP_REGISTER_OK device_code=DC... - Demander à Jean-Marc (Terega) de valider le device dans le portail IoBase → « Services et équipements » → « Valider l'équipement »
- Une fois validé, tirer l'inject
DAP get token - Vérifier
DAP_TOKEN_OK token_len=...dans le debug - À partir de là, le cron
DAP refresh(50 min) prend le relais automatiquement