5.9 KiB
title, tags, created, status
| title | tags | created | status | ||||
|---|---|---|---|---|---|---|---|
| Realtime Authorization Spec |
|
2026-05-24 | advisory |
Realtime Authorization Spec
This document defines the target authorization model for Socket.IO events in the escrow platform. It closes Taskmaster subtask 4.4 alongside Authorization Matrix - REST and Socket.IO.
1. Decision
Socket.IO must use the same trust boundary as REST:
- every socket connection is authenticated during the handshake,
- room membership is derived by the server,
- clients cannot subscribe to rooms by supplying arbitrary user, request, chat, seller, or buyer IDs,
- server-to-client emissions are targeted to authorized rooms only,
- sensitive payment, payout, dispute, delivery-code, and chat payloads are never sent through global broadcasts.
2. Handshake Authentication
Client connects with an access token in handshake.auth.token.
Server requirements:
- verify the JWT signature and standard claims,
- reject expired, malformed, revoked, or missing tokens,
- attach
{ userId, roles, sessionId, jti }tosocket.data, - disconnect immediately when authentication fails,
- log authentication failures without recording token values.
Refresh tokens are not accepted by Socket.IO. Clients must refresh through REST and reconnect with a fresh access token.
3. Server-Derived Base Rooms
On successful connection the server may join only rooms derivable from the authenticated principal:
| Room | Eligibility | Source |
|---|---|---|
user-{userId} |
authenticated user | JWT subject |
seller-{userId} |
authenticated user with seller role | JWT roles or user record |
buyer-{userId} |
authenticated user with buyer role | JWT roles or user record |
sellers |
authenticated seller | JWT roles or user record |
buyers |
authenticated buyer | JWT roles or user record |
Clients must not provide userId, sellerId, or buyerId to join these rooms.
4. Resource Rooms
Resource rooms require database authorization before join.
| Room | Eligibility | Authorization Query |
|---|---|---|
request-{requestId} |
buyer, selected seller, assigned admin/moderator | purchase request participant check |
chat-{chatId} |
chat participant or assigned support/admin user | chat participant check |
dispute-{disputeId} |
dispute party, assigned moderator, admin | dispute participant/assignment check |
template-checkout-{checkoutId} |
checkout owner or service-controlled UI session | checkout ownership check |
Membership must be rechecked when ownership or state changes. If a request, chat, or dispute loses a participant, the server must remove that user's sockets from the associated room.
5. Client Event Policy
Allowed client-originated events:
| Event | Required Authorization | Notes |
|---|---|---|
join-request-room |
participant check | May remain only as a request for server validation. |
leave-request-room |
current membership | User may leave an allowed room. |
join-chat-room |
participant check | May remain only as a request for server validation. |
leave-chat-room |
current membership | User may leave an allowed room. |
typing-start / typing-stop |
current chat-{chatId} membership |
userId in payload is ignored; server derives sender. |
Removed or deprecated client-originated events:
| Event | Replacement |
|---|---|
join-user-room |
server auto-join on handshake |
join-seller-room / join-buyer-room |
server auto-join from authenticated role |
user-online |
server emits presence after authenticated connection |
6. Emission Policy
Server emissions must target the narrowest authorized room:
| Data Class | Allowed Target |
|---|---|
| user notifications | user-{recipientId} |
| buyer/seller offer updates | relevant user-*, buyer-*, seller-*, or request-* room |
| payment status | buyer and seller user rooms, request room if both parties may see it |
| payout status | seller user room and admin operations room only |
| delivery code | seller user room only |
| chat messages | chat-{chatId} |
| dispute events | dispute-{disputeId} and assigned admin/moderator room |
Global payment and payout events are prohibited because they expose financial metadata to unrelated users.
7. Payload Rules
- Never trust
userId,role,sellerId, orbuyerIdfrom socket payloads. - Derive sender identity from
socket.data.userId. - Do not emit delivery verification codes to buyer-visible rooms.
- Redact wallet addresses, tx hashes, and provider references unless the target user is a party to the transaction or an authorized operator.
- Keep payload schemas consistent with REST read permissions.
8. Rate Limiting and Audit
Socket event rate limits:
| Event Class | Limit |
|---|---|
| room join attempts | 30 per 15 minutes per user |
| typing events | 120 per minute per socket |
| chat message events | same policy as REST chat message creation |
| failed authorization checks | 10 per 15 minutes per user, then disconnect |
Audit log required for:
- failed room authorization checks,
- admin/moderator joins to dispute or request rooms,
- attempts to join user/seller/buyer rooms for another principal,
- global payment or payout emission rejection.
9. Tests
Minimum verification before launch:
- invalid or missing JWT cannot connect,
- user cannot join another user's
user-*,seller-*, orbuyer-*room, - user cannot join a request/chat/dispute room without participant status,
- removed participant is evicted from the resource room,
- payment and payout events are not emitted globally,
- delivery code is emitted only to the seller,
- socket event rate limits disconnect abusive clients,
- audit events are written for denied room joins.