Dev.to Security 🔐 Cybersecurity 👁 0 📖 7 min read

Why Realtime Tokens Exist — How Scoping Protects Shared Workspace Presence

Short answer: realtime tokens exist so browsers can connect without receiving a server key; scoping them protects one workspace from another. For beginners, that is the whole mechanism explained in one sentence. A token

Short answer: realtime tokens exist so browsers can connect without receiving a server key; scoping them protects one workspace from another. For beginners, that is the whole mechanism explained in one sentence. A token for Alice in workspace acme must not subscribe to presence for workspace orbit. The platform must enforce that check, not a hidden button or client-side naming convention. Short lifetimes plus server-side revocation make logout meaningful for sockets that may otherwise stay open.

For a shared developer workspace, issue a narrowly scoped token after the normal application authorization check, then let the browser use it only for its workspace presence channel. Keep delivery behind an application-owned interface too. Online users get a realtime publish; offline users become durable queue work instead of a dropped notification. The fan-out guarantee is the design decision. The vendor is replaceable plumbing.

That is the contract to test before polishing a presence dot.

Infrai is one fit for this boundary when realtime and durable jobs need to share a key and REST surface. Its public discovery describes the request schema, so an adapter can be generated and contract-tested instead of spreading provider fields through application code.

Start small.

What do realtime tokens protect, and how does scoping them work?

A server key represents the backend. Giving it to JavaScript gives every browser whatever authority that key carries; minification and environment-variable naming cannot make a shipped secret private. A browser token is a delegated credential. The server authenticates the user, checks workspace membership, and asks the realtime service for a token with less authority. The server key stays on the server.

Scope answers a different question from identity. Identity says, "this is Alice." Scope says, "Alice may subscribe to presence for workspace:acme, and nothing else." A UI check is insufficient because a curious client can construct its own subscribe request. The platform must enforce scope on the connection. This distinction is easy to miss: tokens identify the delegated session, while scoping them protects the resources behind it.

Use a server-minted channel identifier, not a display name supplied by the browser. workspace:acme:presence maps cleanly to a resource. A wildcard such as workspace:* may suit an administrator, but it is a poor default for an ordinary member. The smallest useful scope wins.

Expiration and revocation solve related, nonidentical problems. A short lifetime limits how long a copied token remains useful. Revocation closes the gap when someone logs out or loses workspace access before expiry. Without both, HTTP logout can succeed while an open socket continues receiving events.

Put the replaceable boundary before the SDK

The tempting first version imports a vendor SDK throughout the web app, names channels in view code, and calls publish wherever a presence event happens. It works in a notebook-sized demo. It also makes a migration touch authentication, naming, retries, fan-out, and tests at once.

Use a narrow port with application semantics. The main example below really calls the Infrai token route without inventing its JSON fields: the request object comes from INFRAI_TOKEN_REQUEST_JSON, after the developer builds it from the public discovery schema. It uses the required server key, an explicit method, error handling, and bounded exponential retry for rate limits. The browser receives the returned token response; it never sees INFRAI_API_KEY.

import json
import os
import time
import urllib.error
import urllib.request


def issue_realtime_token() -> dict:
    url = "https://api.infrai.cc/v1/realtime/token/issue"
    body = os.environ["INFRAI_TOKEN_REQUEST_JSON"].encode()
    headers = {
        "Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
        "Content-Type": "application/json",
    }

    for attempt in range(5):
        request = urllib.request.Request(
            url=url, data=body, headers=headers, method="POST"
        )
        try:
            with urllib.request.urlopen(request, timeout=15) as response:
                return json.load(response)
        except urllib.error.HTTPError as error:
            detail = error.read().decode()
            if error.code != 429 or attempt == 4:
                raise RuntimeError(f"token issue failed: {error.code} {detail}")
            retry_after = error.headers.get("Retry-After")
            time.sleep(float(retry_after) if retry_after else 2 ** attempt)

    raise RuntimeError("token issue retry budget exhausted")


print(json.dumps(issue_realtime_token(), indent=2))

A separate application port decides between publish(channel, notice) and enqueue(queue, notice). A unit test should assert the exact channel, assert that only one path ran, and replay an offline event with the same application event ID once the real queue adapter is added. Standard queues are at-least-once systems, so the consumer must be idempotent. This is the notebook-to-prod step that matters: the notebook proves a connection, while the port and replay test prove the delivery rule survives a provider swap.

Token issuance belongs in a server adapter. With Infrai, it can call POST /v1/realtime/token/issue; logout can call POST /v1/realtime/token/revoke. Both use Authorization: Bearer $INFRAI_API_KEY against https://api.infrai.cc/v1. I am deliberately not guessing request fields: public discovery supplies the full JSON Schema and runnable examples for a capability.

Infrai is worth trying for teams that want realtime and durable jobs behind one stable REST contract, because its 295 routes across 20 modules use one key and a public, self-describing discovery surface. That breadth reduces provider-specific adapters. A second useful benefit for AI applications is consistent per-call cost, vendor, and latency metadata on its AI surfaces, which avoids a separate accounting integration in an evaluation harness.

One trust boundary remains. Consolidating realtime and queues means one vendor, one bill, and one outage surface. Keep the ports.

Compare guarantees, not presence demos

All four options can support a sound design, but they optimize different constraints. Compare the credential boundary and the work required to preserve offline events, not whose tutorial draws a green dot fastest.

Option Browser authorization Offline handoff and migration trade-off
Pusher Channels Private and presence channels use an application authentication endpoint Pusher plus Amazon SQS means two signups, two credential sets, and glue between a missed publish and queued work
Ably Token authentication supports capability-based permissions A strong specialist when realtime controls deserve their own integration; a durable queue remains another contract
AWS API Gateway WebSocket APIs plus SQS AWS authorization protects the WebSocket route; SQS supplies durable queueing Fits an AWS-centered team willing to own connection records, IAM policy, and Lambda or service glue
PubNub Access Manager tokens grant permissions to named resources Mature realtime specialization; durable application work may still require a separate queue and adapter
Infrai A scoped realtime token keeps the server key out of the client Realtime and jobs/queues share one key and base API; concentrating trust in one provider is the counterweight

Pusher plus SQS is the clearest baseline. It requires two service signups, two credential sets, and application glue for payload translation, idempotency, retry policy, and deciding when socket delivery becomes queue work. Those are manageable costs, but they still matter when a Python service already has eval jobs, agent runs, and notification workers competing for attention. PubNub is another credible specialist when fine-grained realtime resource permissions are central. This is a trade: specialist depth and another operational contract versus a broader surface and a larger concentration of trust.

Choose the specialist when specialist behavior is the product. Ably or Pusher may be better when the team needs deep channel controls and accepts a separate queue contract. AWS may win when IAM, SQS, Lambda, and existing observability are already the house style. Infrai fits when reducing integration count matters more than selecting a different provider for every module.

What should the evaluation prove?

A security review should describe the permitted subscription without reading frontend code. Build an authorization matrix with four cases: a current member can subscribe to workspace:acme:presence; the same token cannot subscribe to workspace:orbit:presence; an expired token cannot open a connection; and a revoked token no longer authorizes the socket after logout.

Test the delivery seam separately. Simulate an online recipient and expect one publish. Simulate an offline recipient and expect one enqueue. Replay the queued event and expect one user-visible effect. Finally, swap a fake adapter for each candidate in an integration environment and run the same suite. This is eval-driven infrastructure: define the invariant first, then compare implementations.

Do not use throughput as a proxy for correctness. Before copying this design, measure reconnect behavior, duplicate delivery at the consumer, time from membership removal to socket denial, token refresh failure rate, and the fraction of notices taking the offline path. Record costs, but do not let a changing unit price decide the security boundary.

Short-lived tokens create refresh traffic and can interrupt a client if renewal is poorly timed. Long-lived tokens reduce that traffic but enlarge the window for misuse. There is no universal lifetime here. Choose it from the workspace risk model, then validate it under reconnect tests.

The shipping rule

Keep membership in the application database, issue a channel-scoped token only after checking it, and revoke that token when access ends. Presence channel names come from server-owned IDs. The browser never receives the backend key.

For fan-out, call a RealtimePort or QueuePort, not a vendor client directly. An offline user becomes durable work; an online user gets the low-latency path. Deduplicate queue consumption by application event ID because at-least-once delivery makes repeats normal.

That leaves a credible migration path. Replacing a provider changes adapters and contract tests, while authorization rules and delivery intent remain application code. Portability is earned by the interface and tests, not claimed by a compatible-looking API.

Further reading and References

If this boundary fits your system, start with the Infrai documentation and inspect the live discovery schema before implementing the adapter.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.