--- title: Subscriptions subtitle: Adding subscriptions to Apollo Server --- Subscriptions are GraphQL operations that watch events emitted from Apollo Server. The native Apollo Server supports GraphQL subscriptions without additional configuration. All integrations that allow HTTP servers, such as express and Hapi, also provide GraphQL subscriptions. ## Subscriptions Example Subscriptions depend on use of a publish and subscribe primitive to generate the events that notify a subscription. `PubSub` is a factory that creates event generators that is provided by all supported packages. `PubSub` is an implementation of the `PubSubEngine` interface, which has been adopted by a variety of additional [event-generating backends](#PubSub-Implementations). ```js const { PubSub } = require('apollo-server'); const pubsub = new PubSub(); ``` Subscriptions are another root level type, similar to Query and Mutation. To start, we need add to add the `Subscription` type to our schema: ```js line=2-4 const typeDefs = gql` type Subscription { postAdded: Post } type Query { posts: [Post] } type Mutation { addPost(author: String, comment: String): Post } type Post { author: String comment: String } ` ``` Inside our resolver map, we add a Subscription resolver that returns an `AsyncIterator`, which listens to the events asynchronously. To generate events in the example, we notified the `pubsub` implementation inside of our Mutation resolver with `publish`. This `publish` call can occur outside of a resolver if required. ```js line=4-9,17 const POST_ADDED = 'POST_ADDED'; const resolvers = { Subscription: { postAdded: { // Additional event labels can be passed to asyncIterator creation subscribe: () => pubsub.asyncIterator([POST_ADDED]), }, }, Query: { posts(root: any, args: any, context: any) { return postController.posts(); }, }, Mutation: { addPost(root: any, args: any, context: any) { pubsub.publish(POST_ADDED, { postAdded: args }); return postController.addPost(args); }, }, }; ``` ## Context with Subscriptions The function to create a context for subscriptions includes `connection`, while the function for Queries and Mutations contains the arguments for the integration, in express's case `req` and `res`. This means that the context creation function needs to check the input. This is especially important, since the auth tokens are handled differently depending on the transport: ```js const server = new ApolloServer({ schema, context: async ({ req, connection }) => { if (connection) { // check connection for metadata return {}; } else { // check from req const token = req.headers.authorization || ""; return { token }; } }, }); ``` As you can see Apollo Server 2.0 allows realtime data without invasive changes to existing code. For a full working example please have a look to [this repo](https://github.com/daniele-zurico/apollo2-subscriptions-how-to) provided by [Daniele Zurico](https://github.com/daniele-zurico/apollo2-subscriptions-how-to) ## Authentication Over WebSocket To support an authenticated transport, Apollo Server provides lifecycle hooks, including `onConnect` to validate the connection. On the client, `SubscriptionsClient` supports adding token information to `connectionParams` ([example](/docs/react/advanced/subscriptions.html#authentication)) that will be sent with the first WebSocket message. In the server, all GraphQL subscriptions are delayed until the connection has been fully authenticated and the `onConnect` callback returns a truthy value. The `connectionParams` argument in the `onConnect` callback contains the information passed by the client and can be used to validate user credentials. The GraphQL context can also be extended with the authenticated user data to enable fine grain authorization. ```js const { ApolloServer } = require('apollo-server'); const { resolvers, typeDefs } = require('./schema'); const validateToken = authToken => { // ... validate token and return a Promise, rejects in case of an error }; const findUser = authToken => { return tokenValidationResult => { // ... finds user by auth token and return a Promise, rejects in case of an error }; }; const server = new ApolloServer({ typeDefs, resolvers, subscriptions: { onConnect: (connectionParams, webSocket) => { if (connectionParams.authToken) { return validateToken(connectionParams.authToken) .then(findUser(connectionParams.authToken)) .then(user => { return { currentUser: user, }; }); } throw new Error('Missing auth token!'); }, }, }); server.listen().then(({ url, subscriptionsUrl }) => { console.log(`🚀 Server ready at ${url}`); console.log(`🚀 Subscriptions ready at ${subscriptionsUrl}`); }); ``` The example above validates the user's token that is sent with the first initialization message on the transport, then it looks up the user and returns the user object as a Promise. The user object found will be available as `context.currentUser` in your GraphQL resolvers. In case of an authentication error, the Promise will be rejected, which prevents the client's connection.