Follow-along: Configure auth in MCP
First stop the rover dev process with Ctrl+C. You'll also need to stop the MCP Inspector process.
For this follow-along, we'll be using a coprocessor to help the router with authentication. It needs a GraphOS license.
❗ For this workshop, we'll provide the license in the form of an APOLLO_KEY and APOLLO_GRAPH_REF environment variable. In a real-world scenario, you should generate your own key and keep it secret. For the purposes of streamlining this workshop, we'll share the same key with participants and delete it shortly after the workshop.
Start the rover dev command again, this time with the APOLLO_KEY and APOLLO_GRAPH_REF environment variables below:
APOLLO_KEY=service:airlock-instructor-demo:4rHv-Jl2di83lU0r7lGRnw APOLLO_GRAPH_REF=airlock-instructor-demo@current rover dev --supergraph-config graph/supergraph.yaml --router-config graph/router.yaml --mcp mcp/mcp.yaml
⚠️ Important note
The example graph and key for this workshop is now unavailable so you will not be able to follow along. This workshop companion is still available for reference purposes.
This workshop companion was designed to be used alongside an instructor for GraphQL Summit 2025. If you would like to learn on your own time at your own pace, check out the Odyssey course instead: Agentic GraphQL: MCP for the Enterprise
Configure the router for auth
For the router, we're going to:
- enable JWT authentication, using Auth0 as our identity provider
- require authentication for all requests
- connect to a coprocessor that will process the valid JWT and set the appropriate scopes for the request
Open up the
graph/router.yamlfile in your code editor.Add the following snippet to enable JWT authentication. We've already set up Auth0 as our identity provider with the necessary configuration.
graph/router.yamlauthentication:router:jwt:jwks:- url: https://dev-4gnj48muikmjespc.us.auth0.com/.well-known/jwks.jsonAdd the following snippet to configure authorization. (This should be at the top-level of the YAML file, at the same level as the
authenticationkey.)graph/router.yamlauthorization:require_authentication: truedirectives:enabled: truereject_unauthorized: falseThe
require_authenticationkey configures whether to require authentication for all requests. We'll set it totrueto require authentication for all requests.The
directiveskey configures the authorization directives. We'll set it totrueto enable the use of authorization directives in the schema we'll use later on.The
reject_unauthorizedkey configures whether to reject an entire query if any authorization directive failed. We'll set it tofalseto allow the query to return partial results.Add the following snippet to connect to the coprocessor that will process the valid JWT and set the appropriate scopes for the request. (This should also be at the top-level of the YAML file, at the same level as the
authorizationkey.)graph/router.yamlcoprocessor:url: https://airlock-auth-coprocessor-ed3c378ab968.herokuapp.com/router:request:headers: truecontext: allsubgraph:all:request:headers: truebody: truecontext: allCheck out the documentation for more information on using coprocessors for authentication.
Test the router
Rover will automatically pick up the config changes and reload. (Remember, you need to run
rover devwith the graph credentials located the top of the lesson.)Head over to Sandbox and try running the same query as before.
query GetListingDetails {listing(id: "listing-1") {idtitledescriptionnumOfBedscostPerNightlocationTypephotoThumbnailamenities {namecategory}}}You should get an error.
{"errors": [{"message": "unauthenticated","extensions": {"code": "AUTH_ERROR"}}]}
Our graph is locked down! Everything is protected behind JWT authentication.
Configure the MCP server for auth
Run the MCP Inspector again with
npx @modelcontextprotocol/inspector@0.16.7 http://127.0.0.1:5000/mcp --transport http.Try running the same tool as before:
GetListingDetails. You should now get an error!Open up the
mcp/mcp.yamlfile in your code editor.Find the
transportkey. Add theauthconfig nested under thetransportkey. It should be at the same level as thetypekey.mcp.yamltransport:type: streamable_httpauth:servers:- https://dev-4gnj48muikmjespc.us.auth0.comaudiences:- https://airlock-api.demoresource: http://127.0.0.1:5000/mcpscopes:- openid- host:view- guest:booking
servers: the list of upstream delegated OAuth servers.audiences: the list of accepted audiences from upstream signed JWTsresource: the URL pointing to this MCP server.scopes: the list of queryable OAuth scopes from the upstream OAuth servers
Check out the documentation for more information on configuring the MCP server for auth.
Test the MCP server
Stop the
rover devprocess withCtrl+Cand run it again to pick up the new MCP config changes.Start the MCP Inspector again with
npx @modelcontextprotocol/inspector@0.16.7 http://127.0.0.1:5000/mcp --transport http.Click Open Auth Settings and we'll walk through the Guided OAuth flow together.
Note: You can decode what's included in your JWT using jwt.io.
For future work, you can skip the Guided OAuth flow and click Connect to automatically kick off the OAuth flow.
For logging in, you can use the following credentials for two different accounts:
Host:
Username: host@example.comPassword: host123!
Guest:
Username: guest@example.comPassword: guest456!
- Try running the same tool as before:
GetListingDetailswithlisting-1as the listing ID. You should now see the data returned!