Docs
Try Apollo Studio

Configuring CORS in the Apollo Router

Control access to your server's resources


Cross-Origin Resource Sharing (CORS) is an HTTP-header-based protocol that enables a server to dictate which origins can access its resources. Put another way, your server can specify which websites can tell a user's browser to talk to your server, and precisely which types of HTTP requests are allowed.

Apollo Router's default CORS behavior enables only the Apollo studio to tell a user's browser to connect to your server.

If your Apollo Router is serving data for web applications, you want to either add it to the list of allowed origins, or switch to allow_any_origin.

⚠️ If your app is only visible on a private network and uses network separation for security, the default CORS behavior is not secure. See Specifying origins for more information.

By default, websites running on domains that differ from your server's domain can't pass cookies with their requests. For details on enabling cross-origin cookie passing for authentication, see Passing credentials with CORS.

Why use CORS?

Most developers know about CORS because they run into the all-too-common CORS error. CORS errors usually occur when you set up an API call or try to get your separately hosted server and client to talk to each other. To better understand what CORS is and why we use it, we'll briefly go over some background context.

Internet users should always exercise caution when installing any new software on their devices. But when it comes to browsing the web, we navigate to different sites all the time, letting our browsers load content from those sites along the way. This comes with inherent risks.

As web developers, we don't want a user's browser to do anything fishy to our server while the user is visiting another website. Browser security mechanisms (e.g., CORS or SOP) can give developers peace of mind by enabling a website's server to specify which browser origins can request resources from that server.

The origin of a piece of web content consists of that content's domain, protocol, and port. The same-origin policy (SOP) is a security mechanism that restricts scripts on one origin from interacting with resources from another origin. This means that scripts on websites can interact with resources from the same origin without jumping through any extra hoops.

If two URLs differ in their domain, protocol, or port, then those URLs come from two different origins:

# Same origin
http://example.com:8080/ <==> http://example.com:8080/
# Different origin (difference in domain, protocol, and port)
http://example.com:8080/ =X= https://example1.com:8081/

However, as we all know, the internet is an exciting place full of resources that can make websites better (importing images, extra fonts, making API calls, and so on). Developers needed a new protocol to relax SOP and safely share resources across different origins.

Cross-Origin Resource Sharing is the mechanism that allows a web page to share resources across different origins. CORS provides an extra layer of protection by enabling servers and clients to define HTTP headers that specify which external clients' scripts can access their resources.

Note that both SOP and CORS are related to browser security. Neither prevents other types of software from requesting resources from your server.

Choosing CORS options for your project

When thinking about configuring CORS for your application, there are two main settings to consider:

  • Which origins can access your server's resources
  • Whether your server accepts user credentials (i.e., cookies) with requests

Specifying origins

CORS uses specific HTTP request headers as part of its protocol, including Access-Control-Allow-Origin. The Access-Control-Allow-Origin header (ACAO) enables a server to dictate which origins can use scripts to access that server's resources.

Depending on what you're building, the origins you specify in your CORS configuration might need to change when you're ready to deploy your application.

Applications on private networks

If your browser is running your API on a private network (i.e., not on the public internet) and it relies on the privacy of that network for security, we strongly recommend specifying which origins can access your server's resources.

If you instead rely on allow_any_origin, while your personal computer is on your private network, a script on any website could potentially make your browser talk to your private API. Some browsers, such as Chrome, have features under development to solve this problem. But in the meantime, all servers on private networks should always specify origins in their CORS configuration.

APIs that require cookies

If your API needs to accept cross-origin cookies with requests, you must specify origins in your CORS configuration. Otherwise, cross-origin cookies are automatically disabled. This is not a security vulnerability, but it does prevent your API from successfully providing cookies.

For examples, see Passing credentials with CORS.

APIs with known consumers

If you create an API on the public internet to serve resources to your own websites or apps, you want to specify which origins can access your server's resources.

Public or embedded APIs

If you create a public API or an API to embed in websites you don't control yourself, you probably want to allow any origin to access your server's resources. You can set allow_any_origin in your router.yml configuration:

server:
cors:
allow_any_origin: true

Using allow_any_origin makes the router send the wildcard (*) value for the ACAO header, which enables any website to tell a user's browser to send an arbitrary request (without cookies or other credentials) to your server and read that server's response.

APIs with non browser consumers

The default Apollo Server CORS behavior should suit your use case, and https://studio.apollographql.com/sandbox/explorer allows you to run queries against your Apollo Router. You can always specify origins in your CORS configuration later.

Configuring CORS options for Apollo Server

By default, the Apollo Router only allows requests from https://studio.apollographql.com. If your Apollo Router is serving data for web applications, you want to either add their origin to the list of allowed origins, or switch to allow_any_origin.

If you need to pass credentials to your server (e.g., via cookies), you can't use the allow_any_origin flag. You must provide specific origins. For examples, see Passing credentials with CORS.

The Apollo Router has a cors section in the yml configuration, which you can use to change your server's default CORS behavior:

server:
cors:
origins: # ...or set a list of allowed origins
- https://www.your-app.example.com/
- https://studio.apollographql.com/ # So the Apollo studio can still run queries against your router

The example above enables CORS requests from https://www.your-app.example, along with https://studio.apollographql.com.

Note if you plan to use Apollo Studio Explorer as a GraphQL web IDE you should include https://studio.apollographql.com in your list of valid origins.

To disable CORS entirely, set origins to an empty list:

server:
cors:
origins: []

Passing credentials with CORS

If your server requires requests to include a user's credentials (e.g., cookies), you need to modify your CORS configuration to tell the browser those credentials are allowed.

You can enable credentials with CORS by setting the Access-Control-Allow-Credentials HTTP header to true.

You must specify an origin to enable credentialed requests. If your server sends the * wildcard value for the Access-Control-Allow-Origin HTTP header, your browser will refuse to send credentials.

To enable your browser to pass credentials with the Apollo Router:

  1. Use the cors section to specify origins
  2. Set allow_credentials to true:
server:
cors:
origins: # ...or set a list of allowed origins
- https://www.your-app.example.com/
- https://studio.apollographql.com/ # So the Apollo studio can still run queries against your router
allow_credentials: true

For examples of sending cookies and authorization headers from Apollo Client, see Authentication.

Here's a summary of all the supported CORS configuration:

router.yaml
server:
#
# CORS (Cross Origin Resource Sharing)
#
cors:
# Set to true to allow any origin
# (Defaults to false)
allow_any_origin: true
# List of accepted origins
# (Ignored if allow_any_origin is true)
# (Defaults to the Apollo Studio url: `https://studio.apollographql.com`)
origins:
- https://www.your-app.example.com/
- https://studio.apollographql.com/ # So the Apollo studio can still run queries against your router
# Set to true to add the `Access-Control-Allow-Credentials` header
# (Defaults to false)
allow_credentials: true
# The headers to allow.
# If this field is not set, CORS will default to the `mirror_request` mode,
# which mirrors the received `access-control-request-headers`
# (This is equivalent to allowing any headers)
allow_headers: [ Content-Type, Authorization, x-my-custom-required-header, x-and-an-other-required-header ]
# Allowed request methods
# (Defaults to [ GET, POST, OPTIONS ])
methods: [ POST, OPTIONS ]
# Which response headers are available to scripts running in the
# browser in response to a cross-origin request.
# (Defaults to empty array)
expose_headers: []
Edit on GitHub
Previous
Overview
Next
CSRF prevention