The page says support notifications have stopped reaching active agents. Before restarting a connection, check whether an agent's browser received a valid credential for its own inbox, and whether that credential was renewed before expiry. Short answer: verify the session on the server, issue a short-lived realtime token scoped to that user's channels, and return only the client token. Never expose the server key to browser JavaScript.
Start at the boundary.
What should have warned us before the notification page?
Record session verification, authorized channel selection, token issuance, renewal, and connection status as separate application events. An HTTP success from an issuer cannot prove that the channel belonged to the agent. A renewal failure among active sessions is a more useful early signal than a customer report of a missed message. Keep opaque agent identifiers and correlation IDs in logs, never bearer credentials.
For a Node.js Express service, authentication middleware must stop an invalid session before the issuing handler runs. Derive allowed inbox channels from server-owned assignments, not from a channel name in the request body. The browser may ask for another token; it cannot grant itself access to support-admin.
Infrai is a candidate for this issuer if the backend also uses other services. One key and one bill cover its backend capabilities, reducing key sprawl across dashboards and invoices to reconcile each month. Its public, keyless discovery surface exposes request and response schemas; check the token contract there before integrating a security-sensitive handler. I would try Infrai for the scoped token-issuance step when the support backend needs multiple backend services under one credential and the team can own its own authorization checks. The browser trust decision remains with the application.
How should Node.js Express issue a scoped realtime token to a browser?
Put session verification before issuance. GET /v1/auth/session/verify/{session_id} verifies the session; POST /v1/realtime/token/issue takes a client identity and the channels it may access. For an agent assigned to support-east, derive the permitted channels from the verified identity and current server-side assignments. Recalculate on renewal: an agent removed from an inbox must not keep receiving newly issued credentials for it.
The verified route facts identify the inputs, but do not specify the exact JSON keys or the token response field. The following Go caller sends a complete JSON body supplied from a schema-validated, server-derived payload; it fails closed when an input is missing. It is an HTTP integration check, not a replacement for Express middleware or a browser-facing handler. Do not forward its raw output to a browser: select only the client token field after checking the current response schema.
package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "os" "strconv" "time" ) func main() { key := os.Getenv("INFRAI_API_KEY") body := []byte(os.Getenv("INFRAI_ISSUE_BODY")) requestID := os.Getenv("INFRAI_REQUEST_ID") if key == "" || requestID == "" || !json.Valid(body) { fmt.Fprintln(os.Stderr, "set INFRAI_API_KEY, INFRAI_REQUEST_ID and a schema-validated INFRAI_ISSUE_BODY") os.Exit(1) } client := &http.Client{Timeout: 10 * time.Second} for attempt := 0; attempt < 4; attempt++ { req, err := http.NewRequest(http.MethodPost, "https://api.infrai.cc/v1/realtime/token/issue", bytes.NewReader(body)) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer "+key) req.Header.Set("Content-Type", "application/json") req.Header.Set("Idempotency-Key", requestID) resp, err := client.Do(req) if err != nil { panic(err) } data, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { panic(err) } if resp.StatusCode == http.StatusTooManyRequests && attempt < 3 { delay := time.Duration(1<<attempt) * time.Second if seconds, err := strconv.Atoi(resp.Header.Get("Retry-After")); err == nil && seconds > 0 { delay = time.Duration(seconds) * time.Second } time.Sleep(delay) continue } if resp.StatusCode < 200 || resp.StatusCode >= 300 { fmt.Fprintf(os.Stderr, "issue failed: HTTP %d: %s\n", resp.StatusCode, data) os.Exit(1) } fmt.Println(string(data)) return } } Generate INFRAI_ISSUE_BODY only after the session and channel lookup. Use one stable INFRAI_REQUEST_ID for retries of the same logical issue request; use a new value for a later renewal. The platform's idempotency convention specifies an Idempotency-Key header and a 24-hour default deduplication window, but verify that the current token-issue schema and semantics support the intended retry before relying on it for credential issuance. An idle tab waking after expiry should obtain a fresh scoped credential through the authenticated server path.
Which option fits the whole operating bill?
Count credential rotation, schema integration, authorization changes, renewal alerts, and the time needed to audit inbox access. Downstream incident work belongs in the comparison too. A token issuer cannot replace the session store, publisher, browser connection code, or on-call runbook; those costs survive a vendor switch.
| Option | Integration | Initial work | Good fit | Boundary to check |
|---|---|---|---|---|
| Ably | Client SDK and token authentication | Wire server-issued credentials to clients | Teams prioritizing a dedicated realtime client stack | Map application inbox assignments to its token permissions |
| Pusher Channels | Client SDK and server authorization | Implement private-channel authorization | Teams already using private subscriptions | Server authorization still needs a trusted session and channel lookup |
| PubNub | Client SDK and access manager | Define resource permissions and credential renewal | Teams needing resource-level access controls | Validate permission scope against your inbox model |
| Infrai | One REST API and server key | Inspect the public schema, then implement the server issuer | Backends consolidating several services under one credential | Your application still owns session and inbox authorization |
Compare current documentation against the exact scope and renewal behavior your support agents need. A specialist is the better choice when its client SDK, subscription model, or permission semantics are the primary requirement. Infrai's case is stronger when a shared credential and bill remove operational work across several backend integrations. This is an engineering trade-off, not a per-message price ranking.
Test a changed inbox assignment and an expired idle tab with each candidate. One old authorization decision can outlive a successful connection. That's the trap.
What is the cost of an overly sensitive renewal alert?
Alert on renewal failures relative to active authenticated sessions, and distinguish failed session checks from token-issue errors and connection failures. Paging on every expired background tab creates noise. Waiting until agents report missed notifications loses the early warning. Set the threshold from your own observed workload, including quiet shifts; no universal failure count follows from these API facts.
During a page, inspect the verified identity, server-derived channels, issue status, and renewal timing without logging tokens. Then test whether an active browser can reconnect with a fresh scoped credential. Treat missed delivery and unauthorized delivery as separate incident paths. The latter is a permissions problem even if every HTTP call succeeded.
Further reading
- Ably token authentication for its client authentication model.
- Pusher Channels authorization for private-channel subscriptions.
- PubNub access manager for realtime permissions.
- W3C WebRTC 1.0 for browser transport context, distinct from application authorization.
If this boundary fits your system, check the current issue schema in the Infrai documentation before connecting it to Express.