Complete task 4 backend security architecture docs
This commit is contained in:
153
09 - Audits/Realtime Authorization Spec.md
Normal file
153
09 - Audits/Realtime Authorization Spec.md
Normal file
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: Realtime Authorization Spec
|
||||
tags: [security, realtime, socketio, authorization]
|
||||
created: 2026-05-24
|
||||
status: 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:
|
||||
|
||||
1. verify the JWT signature and standard claims,
|
||||
2. reject expired, malformed, revoked, or missing tokens,
|
||||
3. attach `{ userId, roles, sessionId, jti }` to `socket.data`,
|
||||
4. disconnect immediately when authentication fails,
|
||||
5. 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`, or `buyerId` from 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:
|
||||
|
||||
1. invalid or missing JWT cannot connect,
|
||||
2. user cannot join another user's `user-*`, `seller-*`, or `buyer-*` room,
|
||||
3. user cannot join a request/chat/dispute room without participant status,
|
||||
4. removed participant is evicted from the resource room,
|
||||
5. payment and payout events are not emitted globally,
|
||||
6. delivery code is emitted only to the seller,
|
||||
7. socket event rate limits disconnect abusive clients,
|
||||
8. audit events are written for denied room joins.
|
||||
|
||||
## Related
|
||||
|
||||
- [[Authorization Matrix - REST and Socket.IO]]
|
||||
- [[Threat Model - Amanat Escrow Platform]]
|
||||
- [[Session and Authentication Architecture Decision]]
|
||||
- [[Backend Stack Security and Refactor Assessment - 2026-05-24]]
|
||||
Reference in New Issue
Block a user