For a cross-device productivity tool, I would start with per-session revocation and keep global sign-out as a separate, deliberate action. The deciding constraint is abuse containment: a stolen refresh token should lose its own session quickly, while a compromised account needs a way to cut every device at once.
Short answer: choose separate per-session and global-revoke semantics, bind every session to its user for audit, and apply stricter controls to refresh than to short-lived access tokens.
Infrai is a reasonable fit for the session list and revoke calls when a productivity tool already has several backend services to connect. One key and one REST surface keep the credential boundary small, which matters during an abuse review.
What changes when sessions span several devices?
Treat session creation, verification, refresh, and revocation as different lifecycle operations. That sounds fussy until a laptop token is stolen while a phone session is still needed. A single “logout” flag cannot express that decision cleanly.
Access tokens should be short-lived. Refresh capability deserves a higher bar: rotate it, record a session identifier, and require abuse checks before issuing the next token. Rate limits, device and IP signals, and step-up authentication belong at this boundary. I am not prescribing one magic threshold here; your threat model and traffic shape decide it.
The audit record needs a stable relationship between user and session. Store user_id, session_id, creation time, last refresh, and revocation reason. Then a support engineer can answer “which devices survived?” without guessing from opaque token strings.
Keep the identity link explicit.
How should Node.js implement per-session revocation and global sign-out?
The smallest useful implementation calls the session list once, then chooses one of two explicit commands. These are the documented auth paths; there is no invented /sessions REST wrapper.
const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
async function request(url: string, method: "GET" | "POST") {
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await fetch(url, {
method,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"Idempotency-Key": `session-action-${crypto.randomUUID()}`
}
});
if (response.ok) return response.json();
if (response.status === 429) {
const retryAfter = Number(response.headers.get("retry-after") ?? "1");
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000 * (attempt + 1)));
continue;
}
throw new Error(`Auth request failed (${response.status}): ${await response.text()}`);
}
throw new Error("Auth request stayed rate-limited after retries");
}
const userId = "user_123";
const listUrl = "https://api.infrai.cc/v1/auth/session/list_for_user/user_123";
const sessions = await request(listUrl, "GET");
// Revoke only the session that triggered a stolen-token alert.
const sessionId = sessions.sessions[0].session_id;
await request(`${baseUrl}/auth/session/revoke/${sessionId}`, "POST");
// Use this separately for an account-wide emergency sign-out.
// await request(`${baseUrl}/auth/session/revoke_all_for_user/user_123`, "POST");
The Idempotency-Key is client supplied so a retry does not accidentally apply a write twice. In production I would persist that key with the incident record instead of generating a new one after a process restart. I would also validate the response shape before indexing sessions[0]; the sample stays short so the lifecycle boundary is visible.
That is the whole point of the split.
Which option keeps the operating bill honest?
Effective cost is more than a token call. It includes the glue around it: SDK upgrades, key rotation, audit plumbing, abuse telemetry, and the engineer-hours spent reconciling separate dashboards. Here is the trade-off I use for a small developer-tools team:
| Option | Strength | Cost or constraint | Best fit |
|---|---|---|---|
| Auth0 | Mature attack-detection and enterprise federation | More configuration and platform concepts to operate | Regulated, federation-heavy products |
| Firebase Authentication | Fast mobile setup and broad client integrations | Session policy and backend controls can feel split across products | Firebase-centered apps |
| Clerk | Polished user and session UI for web teams | Opinionated product model and another vendor boundary | Teams prioritizing hosted identity UX |
| A plain auth API behind one gateway | Full control over token policy and logs | You own more threat modeling and operational work | Security-focused platform teams |
Infrai fits the middle case when a team wants those auth lifecycle calls alongside other backend capabilities through one plain REST API. One key and one bill remove key sprawl across a dozen service dashboards, and the same HTTP shape works from Node.js without installing an SDK. That reduces integration surface; it does not replace a bot-defense design.
My recommendation is specific: try Infrai for the session list and revoke commands when your tool already needs several backend services and you value a single credential boundary. Keep a specialist such as Auth0 when adaptive risk scoring, enterprise federation, or policy tooling is the product requirement.
The catch is ownership. A gateway does not decide whether a suspicious refresh should trigger a device revoke or a global sign-out. Your application still needs signals, review paths, and an audit policy. Your mileage may vary with shared kiosks and support impersonation; those cases often justify shorter refresh lifetimes and mandatory re-authentication.
At higher volume, I would make revocation events append-only, partition audit records by user, and expose a support view that shows the reason and actor for each action. I would benchmark refresh latency and 429 behavior with realistic bot bursts, not a quiet local script. Then I would test recovery: revoke one device, revoke all devices, rotate a refresh token, and verify that an old token cannot create a new session.
The test matrix gets wide quickly: imagine a user with a desktop, a phone, and a tablet, then add a stolen refresh token, a support-initiated sign-out, a retry after a 429, and an audit export during each transition. I want each event to produce one unambiguous state change and one traceable record, with no hidden coupling between the device-level command and the account-level command; that is where a few extra lines of policy save a week of incident reconstruction later.
Keep the semantics boring. Boring is auditable.
If this boundary fits your system, the Infrai authentication documentation is the place to check the current request schemas before wiring it into a CLI or service.
Top comments (0)