notes 2026-09-20 · 3 min read · updated 2026-09-20

WebSockets, gRPC and GraphQL Authorization

Persistent connections few teams review, protobuf and reflection, and persisted queries: what authorization looks like after the handshake or the hash.

WebSockets, gRPC and GraphQL Authorization

These three move authorization away from the request line, which is exactly where most testing and most logging still look for it.

WebSockets

An application may protect every HTTP endpoint and then open a WebSocket that trusts any message sent after the handshake. WebSocket begins as an HTTP upgrade and then maintains a persistent bidirectional connection. Cookies, tokens and Origin participate in the initial handshake. Authorization still needs to exist per message and per object. An authenticated connection must not become a free pass to every channel, userId or action. I test handshake, Origin, token lifetime, reconnect behavior, subscription identifiers and message authorization with two accounts. Cross-Site WebSocket Hijacking appears when authentication relies on cookies and the handshake does not protect origin or CSRF-equivalent context.

1
2
3
4
5
6
7
GET /chat HTTP/1.1
Host: app.example.test
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://evil.example.test

gRPC

gRPC can carry an entire API over HTTP/2 without exposing a single REST route to a traditional scanner. gRPC uses service definitions written in Protocol Buffers. Methods have request and response types defined by the .proto schema. Server reflection can reveal services and methods at runtime. Even without reflection, mobile apps and binaries may carry useful descriptors. I identify HTTP/2, test reflection, recover proto descriptors and then test authorization method by method using different identities. Metadata headers carry authentication. Misconfigured interceptors may protect some services while missing new methods or health and reflection endpoints.

1
2
grpcurl -plaintext 10.10.10.20:50051 list
grpcurl -plaintext 10.10.10.20:50051 describe

GraphQL Persisted Queries

A persisted query replaces a GraphQL document with a hash. That reduces client payload size but does not turn the operation into a secret. Automatic Persisted Queries associate a hash with query text. Other systems store server-side operation allowlists. Hashes may appear in mobile apps, JavaScript bundles and logs. Authorization still belongs in the resolvers of the final operation. I extract hashes, observe registration behavior and test operations with lower-privileged accounts without indiscriminate brute force. Persisted queries can reduce arbitrary-query surface. If a privileged operation accepts a normal token, the issue remains BFLA or BOLA.

1
{"extensions":{"persistedQuery":{"version":1,"sha256Hash":"..."}},"variables":{}}

gRPC Reflection

Reflection gives you the service map. The finding appears when a mapped method accepts an identity that should not perform that action. Reflection exposes service and method descriptors to tools such as grpcurl. Authentication usually arrives through metadata and interceptors. New methods may fall outside common policy through registration or matcher mistakes. I enumerate descriptors, build valid requests and compare authorization with two identities. Disabling reflection reduces discovery but does not fix a method lacking authorization. It is separate hardening.

1
2
grpcurl -plaintext api.example.test:50051 list
grpcurl -plaintext api.example.test:50051 describe package.AdminService

WebSocket Authentication

A WebSocket connection may live for hours. The token used during the handshake may expire ten minutes later and the application needs to decide what that means. WebSocket authentication may use cookies, query tokens, subprotocols or the first message. Each choice has different leakage and lifecycle properties. Authorization needs to exist per subscription, room, object and action. Reconnect and token refresh also change state. I test mid-connection expiry, tenant switching, subscription identifiers and session revocation. Validating only the handshake may leave an old connection alive after password reset or role changes. The threat model should define revalidation.

Connect with a short-lived lab token, hold the socket open past its expiry, then repeat a protected subscription.

References

This post is licensed under CC BY 4.0 by the author.