Aller au contenu

Appairage & appareils

L’appairage relie un utilisateur (côté backend) à un appareil portant l’app Bloonio Authenticator. Il se déroule en deux temps : le backend prépare l’appairage (signé HMAC #1) et reçoit un pairing_proof court ; l’appareil échange ce proof contre un device_session_token longue durée.

1. l'utilisateur scanne le QR (handler d'appairage existant du backend)
2. backend ── HMAC #1 ─► POST /api/v1/relay/prepare-pairing
← { pairing_proof (JWT ~5 min), expires_in }
3. le backend renvoie pairing_proof à l'appareil avec sa charge d'appairage habituelle
4. appareil ── Bearer pairing_proof ─► POST /api/v1/device/register-token
← { device_session_token (JWT ~30 jours), pairing }
5. l'appareil persiste device_session_token et l'utilise pour refresh-token / unpair
  1. Le backend prépare l’appairage (HMAC #1).

    Après authentification de l’utilisateur dans votre flux d’appairage QR, appelez prepare-pairing. Au moins un de user_email / user_phone est requis ; user_socket_hash, backend_user_id et display_name sont obligatoires.

    Fenêtre de terminal
    curl $BASE_URL/api/v1/relay/prepare-pairing \
    -X POST \
    -H "X-Bloonio-Tenant-Id: tnt_..." \
    -H "X-Bloonio-Timestamp: 1718966400000" \
    -H "X-Bloonio-Signature: <hex_hmac_sha256>" \
    -H "Content-Type: application/json" \
    -d '{
    "user_socket_hash": "9f86d081884c7d659a2feaa0c55ad015",
    "backend_user_id": "507f1f77bcf86cd799439011",
    "user_email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "display_name": "Example",
    "display_logo_url": "https://example.com/logo.png"
    }'
    {
    "success": true,
    "status_code": 201,
    "message": "Pairing prepared. Forward pairing_proof to the device.",
    "data": { "pairing_proof": "eyJhbGciOi...", "expires_in": 300 }
    }
  2. Le backend transmet le pairing_proof à l’appareil.

    Renvoyez-le à l’appareil aux côtés de votre charge utile d’appairage existante. Le proof est un JWT valable ~5 minutes (PAIRING_PROOF_TTL_SECONDS, 300 s par défaut) — une fenêtre de transfert unique.

  3. L’appareil enregistre son jeton FCM (Bearer pairing_proof).

    L’appareil échange le proof contre un device_session_token longue durée et reçoit les infos publiques de l’appairage. platform vaut ios ou android.

    Fenêtre de terminal
    curl $BASE_URL/api/v1/device/register-token \
    -X POST \
    -H "Authorization: Bearer eyJhbGciOi..." \
    -H "Content-Type: application/json" \
    -d '{
    "fcm_token": "fcm-token-value-here",
    "platform": "android",
    "app_version": "1.4.0",
    "os_version": "14"
    }'
    {
    "success": true,
    "status_code": 201,
    "message": "Device token registered.",
    "data": {
    "device_session_token": "eyJhbGciOi...",
    "expires_in": 2592000,
    "pairing": {
    "tenant_id": "tnt_...",
    "user_socket_hash": "9f86d081884c7d659a2feaa0c55ad015",
    "display_name": "Example",
    "display_logo_url": "https://example.com/logo.png",
    "created_at": "2026-06-21T...",
    "last_seen_at": null
    }
    }
    }
  4. L’appareil persiste le device_session_token.

    Ce JWT (~30 jours, DEVICE_SESSION_TOKEN_TTL_SECONDS, 2 592 000 s par défaut) authentifie les appels suivants : rafraîchissement du jeton FCM et désappairage.

Quand le jeton FCM tourne localement sur l’appareil, appelez refresh-token avec le device_session_token.

Fenêtre de terminal
curl $BASE_URL/api/v1/device/refresh-token \
-X POST \
-H "Authorization: Bearer eyJhbGciOi..." \
-H "Content-Type: application/json" \
-d '{ "new_fcm_token": "new-fcm-token-value" }'
{ "success": true, "status_code": 200, "message": "Token refreshed", "data": null }

Deux chemins de révocation, selon le côté qui agit.

L’utilisateur retire le compte depuis l’appareil. Authentifié par le device_session_token. Sans corps.

Fenêtre de terminal
curl $BASE_URL/api/v1/device/unpair \
-X POST \
-H "Authorization: Bearer eyJhbGciOi..."
{ "success": true, "status_code": 200, "message": "Device unpaired", "data": null }