website/src/docs/strawberryshake/v16/subscriptions.md
We are still working on the documentation for Strawberry Shake, so help us by finding typos, missing things, or write some additional docs with us.
Subscriptions in GraphQL represent real-time events that are represented as a stream of query responses. In most cases, subscriptions are used over WebSockets but can also be used with other protocols.
For transport questions, please head over to the network docs.
GraphQL subscriptions can be used through reactive APIs like queries. Instead of a single network request, the store will subscribe to the GraphQL response stream and update the store for each new result.
This section will be based on the getting started tutorial.
To create a subscription, we start with everything in Strawberry Shake by creating a GraphQL file.
OnSessionUpdated with the following content.subscription OnSessionUpdated {
onSessionScheduled {
title
}
}
Add the StrawberryShake.Transport.WebSockets package to your project.
Build your project so that the code-generator kicks in.
Configure the transport settings for the WebSocket.
builder.Services
.AddConferenceClient()
.ConfigureHttpClient(client => client.BaseAddress = new Uri("http://localhost:5050/graphql"))
.ConfigureWebSocketClient(client => client.Uri = new Uri("ws://localhost:5050/graphql"));
var session =
ConferenceClient
.OnSessionUpdated
.Watch()
.Subscribe(result =>
{
// do something with the result
});
Remember, session is an IDisposable and will stop receiving events when Dispose is invoked.
When working with GraphQL subscriptions over WebSockets, you may want to authenticate incoming WebSocket connections using JSON Web Tokens. Normally, HTTP headers are sent with each request for standard APIs, but WebSockets behave differently. After a successful HTTP handshake, the protocol is "upgraded" to WebSockets, and additional headers cannot be easily injected for subsequent messages.
Instead, the recommended approach is to send your token via the connection_init message when the WebSocket connection is first established. Hot Chocolate allows you to intercept this initial message, extract the token, and then authenticate the user in a way similar to standard HTTP requests.
An example implementation of this approach can be found in the Hot Chocolate Examples repository.
connection_init Payload: GraphQL subscription clients send a connection_init message when establishing the subscription. This payload can include extra properties (e.g., authorization), which Hot Chocolate can use for authentication.Stub (or "Skip") Authentication Scheme The initial WebSocket upgrade request is directed to a "stub" authentication scheme that simply indicates "no authentication result" for upgrade requests. This prevents the request from failing before you can intercept and handle the token manually.
Forwarding the Default Scheme In standard HTTP scenarios, the default scheme (e.g., JWT bearer) is used to authenticate. However, if the request is recognized as a WebSocket upgrade, the framework forwards it to the "stub" scheme first. That way, you don’t attempt to validate a token at the moment of the upgrade handshake.
Intercepting connection_init
Once the WebSocket is established, the client sends connection_init containing authentication data. A custom SocketSessionInterceptor (or similar) reads the token from connection_init (e.g., under a key like authorization), stores it in the HttpContext, and triggers a fresh authentication attempt-this time using the real JWT bearer scheme.
Hot Chocolate Integration
Hot Chocolate's subscription middleware allows you to plug into the subscription lifecycle. By customizing the session interceptor (OnConnectAsync), you can decide whether to accept or reject the connection based on successful authentication.
Open Nitro
Use a local instance of Nitro (e.g., https://localhost:5095/graphql) to send GraphQL queries and subscriptions.
Retrieve an Access Token
Request a token from your /token endpoint. This endpoint should return a valid JWT that is trusted by your API.
Configure Nitro
connection_init message under an authorization parameter when opening a WebSocket connection.Run Your Subscription Execute the subscription query of your choice. For example:
subscription {
onTimedEvent {
count
isAuthenticated
}
}
The server-side resolver can check isAuthenticated to demonstrate whether the current user is authenticated (based on the token you provided).