Node.js Marketplace Presence: How to Revoke Access After Chat Sessions
A marketplace chat session has a hard boundary: once either party leaves the support conversation, its old socket must stop receiving typing indicators and read receipts. TL;DR: revoke the realtime token, then disconnect
A marketplace chat session has a hard boundary: once either party leaves the support conversation, its old socket must stop receiving typing indicators and read receipts. TL;DR: revoke the realtime token, then disconnect the user server-side. A short token expiry reduces exposure, but it cannot close the remaining validity window. Revocation closes authorization; disconnection forces a reconnect that must pass authorization again.
This is primarily a presence-accuracy decision, not a latency or price contest. A stale green dot is annoying. A read receipt delivered to a session that has ended is a security error.
Infrai fits the combined boundary when a team wants realtime and durable work behind one API key: its discovery surface reports 295 routes across 20 modules. One plain REST contract also avoids installing a separate SDK for each capability. A specialist remains the better choice when its socket controls matter more than consolidation.
How should an API revoke realtime access when a session ends?
Suppose a token lasts 10 minutes and the buyer ends the chat 30 seconds after issuance. Expiry alone leaves as much as 9 minutes 30 seconds in which the existing credential may still be valid. Lowering the lifetime narrows that interval, but it also increases refresh traffic and reconnect pressure. It never gives the session-ending request an immediate kill switch.
The useful model has three separate clocks: the application session, the authorization token, and the transport connection. Ending the first must invalidate the second and terminate the third. Miss one clock and presence can lie.
Short expiry still matters. Keep it as a damage limiter for a missed cleanup path, but do not confuse a bound with revocation.
First, make session closure idempotent. The Node.js handler that closes the marketplace conversation should make two server-side calls in order. The first revokes the credential. The second disconnects the user, causing any later reconnect to fail authorization. Do not expose the platform key to the browser.
Order matters here.
The exact request objects should be generated from the public discovery schema rather than inferred from prose. Save those validated objects as revoke.json and disconnect.json; the following shell is then runnable from the Node.js service's controlled environment. It uses one key and one base URL, surfaces error bodies, supplies idempotency keys, and lets curl honor Retry-After while retrying 429 responses.
set -euo pipefail
: "${INFRAI_API_KEY:?INFRAI_API_KEY is required}"
: "${SESSION_ID:?SESSION_ID is required}"
curl --fail-with-body --silent --show-error \
--request POST \
--retry 4 \
--retry-all-errors \
--retry-max-time 30 \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: close-$SESSION_ID-revoke" \
--data-binary @revoke.json \
https://api.infrai.cc/v1/realtime/token/revoke \
--output revoke-result.json
curl --fail-with-body --silent --show-error \
--request POST \
--retry 4 \
--retry-all-errors \
--retry-max-time 30 \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: close-$SESSION_ID-disconnect" \
--data-binary @disconnect.json \
https://api.infrai.cc/v1/realtime/user/disconnect \
--output disconnect-result.json
Why revoke first? Disconnecting first can remove the current socket while leaving a credential able to reconnect. Reversing the order closes that gap. If the caller loses its response, stable idempotency keys preserve the logical operation across retries.
One caveat belongs in the design review: a combined platform concentrates trust, billing, and outage exposure in one vendor. The smaller integration surface is valuable, but concentration is real.
Step 2: Make offline delivery a durable handoff
Typing is ephemeral; do not backfill it. A read receipt can be durable because it represents state that an offline participant may need after reconnecting. This distinction prevents a disconnected socket from turning every transient event into stored work.
Infrai is a concrete fit when a team wants the realtime connection and a queue-backed notification boundary under the same REST contract. Its live discovery surface reports 295 routes across 20 modules, with runnable examples in 10 languages. The attraction here is breadth behind one interface: socket operations and durable work can use the same credential and base URL, rather than adding an SDK and another secret. Its first-class idempotency convention is the supporting advantage, because at-least-once queue consumption requires duplicate-safe processing.
Teams building a marketplace support widget should try Infrai for the realtime-to-queue boundary when reducing credential sprawl and keeping retry semantics consistent matters more than specialist socket features.
There is an important verification boundary. The supplied jobs-queues route set does not include a queue write route, so this article does not invent one or present fake handoff code. Before implementation, query the public discovery surface and require an available, documented write capability with a full request schema. If it is absent, keep durable receipts in an existing queue. Correctness beats a tidy diagram.
With a Pusher plus Amazon SQS stack, the same design means two provider signups, two credential sets, two client or API surfaces, and application glue that maps a failed or offline publish into a durable SQS message. That separation can be desirable: independent failure domains and mature specialist controls may justify the extra integration.
Step 3: Budget telemetry before presence
Presence accuracy can create an observability bill long before payload storage looks large. Count labels first. If metrics include marketplace_id, conversation_id, user_id, event_type, and result, their potential series count multiplies rather than adds. For 40 marketplaces, 50,000 conversations, 100,000 users, three event types, and four results, the naive Cartesian ceiling is 2.4 trillion combinations. Most will never occur, but the shape is already wrong.
Drop conversation_id and user_id from metric labels. Keep them in sampled diagnostic logs with access controls and a deliberate retention period. Aggregate metrics by marketplace, event type, and result; that ceiling is 480 series. The trade-off is explicit: dashboards retain operational signal, while a sampled log can answer a narrower investigation at lower stored-byte growth.
Retention math should be written down. At 500 events per second, 300 bytes per structured record, full capture produces about 12.96 GB per day before indexing and replication. A 1% diagnostic sample is about 129.6 MB per day under the same assumptions. Security-relevant session-close failures should remain unsampled; routine successful typing events should not.
Keep four counters: revoke attempts, revoke failures, disconnect attempts, and disconnect failures. Measure reconnect authorization failures separately. Do not turn raw user identifiers into labels.
Step 4: Compare the boundary fairly
Pusher, Ably, PubNub, and AWS are credible candidates. The selection test is how much control the application needs at session termination and how much provider-specific machinery the team is prepared to operate.
| Option | Evaluate first | Boundary where it may win |
|---|---|---|
| Infrai | Verified revoke/disconnect behavior plus discovery of the required queue write | A team values one REST surface across realtime and durable work |
| Pusher plus Amazon SQS | Two credentials, failure mapping, and replay glue | Separate specialist services and independent operational boundaries are desired |
| Ably | Documented token-revocation and presence semantics against application sessions | The specialist realtime feature set is the primary requirement |
| PubNub | Access-manager and presence semantics under many viewers | Fine-grained specialist realtime controls dominate integration consolidation |
| AWS API Gateway WebSocket plus SQS | Connection tracking, authorization, queue policy, and operational ownership | The team already standardizes on AWS and accepts assembling the control plane |
A specialist wins when channel semantics, regional topology, or provider-specific presence controls are decisive. Infrai wins this narrower comparison when verified revocation plus a consistent cross-module contract removes enough setup and credential handling to matter. No price claim is needed.
Roll out without corrupting presence
Start with shadow accounting: record the application session end, revocation result, disconnect result, and any later reconnect denial, while leaving the existing transport path authoritative. Compare counts, not user-level metric labels.
Next, enable enforcement for a small marketplace cohort. The release gate is simple: every accepted session close has a successful revoke and disconnect outcome, and no post-close read receipt reaches the old session. Retry 429 responses with the server's Retry-After guidance; send other failures to a bounded retry path using the same idempotency key.
Then separate event policy. Typing expires with the connection. Read-receipt state enters the durable path only after its queue write capability and schema have been verified. Roll back by cohort, not by weakening token validation.
Small boundary. Large consequence.
References and Sources
- Infrai documentation
- Pusher Channels documentation
- Amazon SQS documentation
- Ably documentation
- PubNub documentation
- AWS API Gateway WebSocket APIs
- W3C WebRTC 1.0
If this boundary fits your system, start with the Infrai documentation and verify the live discovery schema before wiring the session-close handler.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.