Skip to content

Latest commit

 

History

History
189 lines (143 loc) · 8.34 KB

File metadata and controls

189 lines (143 loc) · 8.34 KB
title Configuring CORS
subtitle Control browser access to your router
description Manage browser access to your Apollo GraphOS Router or Apollo Router Core with CORS configuration options, including origin whitelisting, wildcard origins, and credential passing.

This article describes CORS configuration that's specific to the GraphOS Router and Apollo Router Core. For a more general introduction to CORS and common considerations, see the following sections:

By default, the router enables only GraphOS Studio to initiate browser connections to it. If your supergraph serves data to other browser-based applications, you need to do one of the following in the cors section of your router's YAML config file:

  • Add the origins of those web applications to the router's list of allowed policies.

    • Use this option if there is a known, finite list of web applications that consume your supergraph.
  • Add a regex that matches the origins of those web applications to the router's list of allowed policies.

    • This option comes in handy if you want to match origins against a pattern, see the example below that matches subdomains of a specific namespace.
  • Enable the allow_any_origin option.

    • Use this option if your supergraph is a public API with arbitrarily many web app consumers.
    • With this option enabled, the router sends the wildcard (*) value for the Access-Control-Allow-Origin header. This enables any website to initiate browser connections to it (but they can't provide cookies or other credentials).
  • If clients need to authenticate their requests with cookies, you must use either origins, match_origins, or the combination of both options. When using both options, note that origins is evaluated before match_origins.

The following snippet includes an example of each option (use either allow_any_origin, or origins and/or match_origins):

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 GraphOS Studio url: `https://studio.apollographql.com`)
  #
  # An origin is a combination of scheme, hostname and port.
  # It does not have any path section, so no trailing slash.
  policies:
    - origins:
        - https://www.your-app.example.com
        - https://studio.apollographql.com # Keep this so GraphOS Studio can run queries against your router
      match_origins:
        - "^https://([a-z0-9]+[.])*api[.]example[.]com$" # any host that uses https and ends with .api.example.com

You can also disable CORS entirely by setting policies to an empty list:

cors:
  policies: []

If your router serves exclusively non-browser-based clients, you probably don't need to modify the default CORS configuration.

Passing credentials

If your router requires requests to include a user's credentials (e.g., via 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.

To allow browsers to pass credentials to the router, set allow_credentials to true, like so:

cors:
  policies:
    - origins:
        - https://www.your-app.example.com
        - https://studio.apollographql.com
  allow_credentials: true

To support credentialed requests, your router's config file must specify individual origins. If your router enables allow_any_origin, your browser will refuse to send credentials.

Additionally, you'll need to configure the router to forward the Cookie header to some (or all) of your subgraphs:

headers:
  all:
    request:
      - propagate:
          named: cookie

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

CORS private network access

By default, browsers block any requests sent to a device or service on a private network. If your router requires requests to a device or service on a private network, you need to enable this behavior in your CORS configuration.

To enable private network access with CORS, your router must return the Access-Control-Allow-Private-Network HTTP header with a value of true. To do so, add the private_network_access with an empty access_id value in the policies of your cors config.

cors:
  policies:
    - origins:
        - https://www.your-app.example.com
        - https://studio.apollographql.com
      private_network_access:
        access_id:

Optionally, you can specify the access_id and access_name subfields to identify what is being accessed in the private network when the browser prompts the user for permission. These fields return the Private-Network-Access-ID and Private-Network-Access-Name HTTP headers, respectively, along with the specified strings.

cors:
  policies:
    - origins:
        - https://www.your-app.example.com
        - https://studio.apollographql.com
      private_network_access:
        access_id: "01:23:45:67:89:0A"
        access_name: "mega-corp device"

Policy inheritance

Individual policies within the policies array inherit global CORS settings unless explicitly overridden:

  • Allow credentials: Policies inherit the global allow_credentials setting unless they specify their own value
  • Allow headers: Policies inherit global headers if their allow_headers is empty, otherwise use policy-specific headers
  • Expose headers: Policies inherit global headers if their expose_headers is empty, otherwise use policy-specific headers
  • Methods: Policies have three inheritance states:
    • Not specified (null): Inherits global methods
    • Empty array ([]): No methods allowed for this policy
    • Specific values: Uses those exact methods
  • Max age: Policies inherit the global max_age unless they specify their own value

All cors options

The following snippet shows all CORS configuration defaults for the router:

#
# CORS (Cross Origin Resource Sharing)
#
cors:

  # Set to true to allow any origin
  allow_any_origin: false

  # List of accepted origins
  # (Ignored if allow_any_origin is set to true)
  #
  # An origin is a combination of scheme, hostname and port.
  # It does not have any path section, so no trailing slash.
  policies:
    - origins:
        - https://studio.apollographql.com # Keep this so GraphOS Studio can still run queries against your router
      # Enable private network access for the router
      private_network_access:
        access_id:

  # Set to true to add the `Access-Control-Allow-Credentials` header
  allow_credentials: false

  # The headers to allow.
  # Not setting this mirrors a client's received `access-control-request-headers`
  # This is equivalent to allowing any headers,
  # except it will also work if allow_credentials is set to true
  allow_headers: []

  # Allowed request methods
  methods:
    - GET
    - POST
    - OPTIONS

  # Which response headers are available to scripts running in the
  # browser in response to a cross-origin request.
  expose_headers: []

  # Adds the Access-Control-Max-Age header
  # Can be set to a duration in time units
  # If not set, the header is not included
  max_age: 2h

Response Vary header

A plugin may set a response Vary header. If, after all plugins are processed, there is no response Vary header, then the router will add one with a value of "origin".