Cross-origin Resource Sharing (CORS)

How to enable Cross-origin Resource Sharing (CORS) on a Banyan-secured web service

  • Updated on Apr 25, 2022
  • 10 minutes to read
  • Contributors

This article describes features that require Banyan Netagent v1.25.0+.

Banyan Netagent does not directly set CORS response headers (such as Access-Control-Allow-Origin, Access-Control-Allow-Methods, etc.) to allow selective cross-origin access to a service. Instead, it assumes that the backend application server sets these CORS response headers correctly. Netagent then enables CORS by exempting specific HTTP requests from its TrustCookie check so it may reach the backend server.

Overview

Cross-Origin Resource Sharing (CORS) allows JavaScript on a web page served on an origin domain to make XML HTTP Requests (XHR a.k.a AJAX) for resources from an external domain, outside of the origin domain.

For example, a web app served on the origin domain domain-a.com is always allowed make same-origin requests to resources served on domain-a.com. However, requests to resources on the external domain domain-b.com are cross-origin.

If Banyan is used to secure the external domain, cross-origin requests need explicit CORS configurations to work. This is because when a request is made to a Banyan-protected service, Banyan first checks if there is a valid TrustCookie. If an end user accesses a Banyan-protected service on domain-a.com with a valid TrustCookie but has not yet obtained a valid TrustCookie for domain-b.com, then Banyan drops the CORS request for domain-b.com.

Simple and Preflighted CORS

There are two types of CORS requests - Simple and Preflighted.

  • Simple CORS Requests do not trigger a preflight sequence using the HTTP OPTIONS method.
  • Preflighted CORS Requests trigger a preflight sequence from the browser to the external domain via the HTTP OPTIONS method. This OPTIONS preflight sequence establishes what methods and headers are supported by the external domain.

Most modern CORS scenarios are Preflighted and involve a preflight sequence via the HTTP OPTIONS method.

CORS With Credentials

By default, browsers do NOT send HTTP Cookies and HTTP Authentication headers when making CORS requests. Most modern CORS scenarios use the Requests With Credentials capability to enhance the security of CORS via authentication. To enable the Requests With Credentials capability, two conditions must be met:

  1. The CORS server at the external domain must be configured to allow credentials via the Access-Control-Allow-Credentials header.
  2. The web application at the origin domain must make XHR CORS requests with the withCredentials property set.

The Access-Control-Allow-Credentials header works in conjunction with the XMLHttpRequest.withCredentials property so CORS requests can use credentials such cookies, authorization headers, and TLS client certificates.

The HTTP OPTION preflight requests never use HTTP Cookies and HTTP Authentication headers, regardless of whether CORS With Credentials is enabled or not.

Multi-domain Services

In Banyan, multi-domain services refer to the use of a wildcard (*) to create a single service definition that applies to all the subdomains of a higher-level domain. For example, a single service definition for *.foo.example.com would apply to app.foo.example.com, api.foo.example.com, games.foo.example.com, etc. The issued TrustCookie will be valid for all subdomains.

Since many CORS strategies involve a web frontend (e.g., ui.foo.example.com) and an API backend (e.g., api.foo.example.com) served as subdomains, you can leverage Banyan’s multi-domain service capabilities to securely support CORS.


Setup

You can configure Banyan to allow CORS requests by exempting specific HTTP requests from its TrustCookie check, via the OIDC exemptions feature, so CORS requests may reach the backend server.

The sections below details how to enable CORS for most common scenarios. Refer to the HostedService Spec Syntax for a complete description of the OIDC exemption capabilities for use in more advanced scenarios.

1. Multi-Domain Service, CORS With Credentials enabled

In this scenario, the origin domain (e.g., domain-a.foo.example.com) and the external domain (e.g., domain-b.foo.example.com) are both subdomains of a higher-level domain (e.g., foo.example.com). In addition, the CORS server on the external domain has CORS With Credentials enabled.

To configure Banyan to allow this CORS scenario, complete the following:

  1. Register a Standard Website multi-domain service at *.foo.example.com.

  2. In the Exemptions, select Add CORS Exemption.

  3. Configure the CORS Exemption to exempt ORIGIN requests. This will automatically trigger an exemption with OPTIONS as its Valid Method, but it won’t be visible in the UI.

The Banyan TrustCookie obtained when the end user browses to the domain-a.foo.example.com origin domain will be scoped to foo.example.com, valid for all subdomains of foo.example.com. All subsequent CORS requests to the external domain will use the TrustCookie and will be successfully validated by Netagent.

2. Multi-Domain Service, CORS With Credentials NOT enabled

In this scenario, the origin domain (e.g., domain-a.foo.example.com) and the external domain (e.g., domain-b.foo.example.com) are both subdomains of a higher-level domain (e.g., foo.example.com).

However, the CORS server on the external domain at domain-b.foo.example.com does NOT have CORS With Credentials enabled. Also, the CORS server responds only to GET and POST requests to an API path /api/v1/ when the request contains a valid authentication token submitted via a header called X-Secret-Auth.

Since CORS With Credentials is not enabled, requests to the CORS server will not contain the Banyan-issued TrustCookie. You have to explicitly exempt requests to the CORS server, locked down to the API path.

To configure Banyan to allow this CORS scenario:

  1. Register a Standard Website multi-domain service at *.foo.example.com.

  2. In the Exemptions, select Add CORS Exemption.

  3. Configure the CORS Exemption to exempt requests to the API path:

When you add a CORS exemption, the console UI automatically populates your service spec with an exemption that has ‘OPTIONS’ configured as its method. To see this exemption, download the service spec JSON.

The Banyan TrustCookie is obtained when the end user browses to the domain-a.foo.example.com origin domain. We have exempted API requests from the origin domain to the external domain that contain the X-Secret-Auth header.

3. Single domain Services, CORS With Credentials NOT enabled

In this scenario, the origin domain (e.g., domain-a.foo.example.com) and the external domain (e.g., domain-b.bar.example.com) cannot be covered under the same higher-level domain.

In addition, the CORS server on the external domain at domain-b.bar.example.com does NOT have CORS With Credentials enabled. Also, the CORS server responds only to GET and POST requests to an API path /api/v1/ when the request contains a valid authentication token submitted via a header called X-Secret-Auth. Since CORS With Credentials is not enabled, requests to the CORS server will not contain the Banyan-issued TrustCookie. You have to explicitly exempt requests to the CORS server, locked down to the API path.

To configure Banyan to allow this CORS scenario:

  1. Register a Standard Hosted Website Service for that external domain at domain-b.bar.example.com to which CORS requests are being made.

  2. In the Exemptions, select Add CORS Exemption.

  3. Configure a CORS exemption to exempt requests to the API path:

We have exempted API requests from the origin domain that contain the X-Secret-Auth header. Note, you can leave the target field in this scenario set to * because this service definition only applies to a single external domain domain-b.bar.example.com.

Can’t find what you’re looking for?

We’re happy to help. Contact our team.