QR login
QR login lets a browser sign in by scanning a QR code with the Bloonio
Authenticator app. The tenant acts as broker: it initiates a session (HMAC #1
signed), shows the QR to the user, then polls the relay until approval. Both
routes are relays to auth_api, which mints the QR and decides the outcome.
Overview
Section titled “Overview”- The browser requests a sign-in; your backend calls
POST /relay/qr-login/initiatewith the browser’s origin. - The relay checks the origin is in the tenant’s allowlist, then returns
session_id,poll_token, and the QR payload. - The front-end displays the QR. The user scans it and approves in the app.
- The browser polls
GET /relay/qr-login/polluntil an approved state or a410 GONE.
Initiate a session
Section titled “Initiate a session”browser_origin must belong to the tenant’s qr_login_allowed_origins. An
empty allowlist disables QR login for that tenant.
curl $BASE_URL/api/v1/relay/qr-login/initiate \ -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 '{ "browser_origin": "https://example.com" }'{ "success": true, "status_code": 200, "message": "QR-login session created.", "data": { "session_id": "...", "poll_token": "...", "qr_payload": "...", "qr_code_str": "...", "signature": "...", "expires": "2026-06-21T..." }}Poll the session
Section titled “Poll the session”Polling is a pass-through: forward the user’s poll request with the
X-QR-Poll-Token header. The relay mirrors auth_api’s status code.
curl "$BASE_URL/api/v1/relay/qr-login/poll?session_id=..." \ -H "X-Bloonio-Tenant-Id: tnt_..." \ -H "X-Bloonio-Timestamp: 1718966400000" \ -H "X-Bloonio-Signature: <hex_hmac_sha256>" \ -H "X-QR-Poll-Token: ..."session_id is 10 to 64 characters long.
Status code semantics
Section titled “Status code semantics”| Code | Meaning |
|---|---|
200 | Pending or approved — the data block mirrors the state returned by auth_api. |
410 GONE | The QR expired, was consumed, or the poll-token is missing / invalid. |
502 | Upstream auth_api unreachable. |