Enable CORS OPTIONS Request over Browser Access
Enable CORS OPTIONS Request over Browser Access
Cross-Origin Resource Sharing (CORS) is an HTTP-header mechanism that lets a server specify external origins allowed to access its resources. CORS uses a preflight request where the browser asks the server if it will permit the actual request, including the HTTP method and headers to be used.
Browsers send a preflight OPTIONS request before initiating a CORS request, which cannot include authentication cookies. The Browser Access feature is designed to enforce authentication for all incoming requests. As a result, any unauthenticated requests are automatically redirected to an Identity Provider (IdP) for authentication.
This security measure may impact Private Apps that rely on Cross-Origin Resource Sharing (CORS) Options requests. When such requests are routed through the Browser Access solution, they are unable to carry authentication cookies due to the nature of the CORS protocol. Consequently, these requests are treated as unauthenticated and are redirected to the IdP for authentication.
If CORS is a use case, Netskope recommends enabling the CORS OPTIONS Request Support feature (a tenant-level flag), which will allow unauthenticated OPTIONS requests to be permitted.
Note
Contact Netskope Support to get this feature enabled.
Enablement
To use this feature, enable the Allow Unauthenticated CORS toggle to allow Cross-Origin Resource Sharing (CORS) OPTIONS requests within the Browser Access App Definition.
Note
This option will be available only when the feature flag is enabled for a tenant.
How does this Work?
Here’s an example for a CORS preflight request:
OPTIONS /doc HTTP/1.1 Host: bar.company.com Origin: https://foo.company.com Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type <..> HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://foo.company.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type <..>
In the above example, the primary domain (origin) is foo.company.com, and the secondary domain is bar.company.com. This use case involves foo.company.com requesting a resource from bar.company.com. During this process, there is a preflight OPTIONS request followed by a GET request for the intended resource from bar.company.com.
The sequence of transactions is:
- Request #0 : GET foo.company.com (no authentication cookie)
This request gets directed to the IdP, and after authentication, Browser Access sets a cookie for the domain company.com. - Request #1: GET foo.company.com (with authentication cookie set for the domain company.com)
This request returns a javascript with the fetch API to fetch a resource from bar.company.com. - Request #2 : OPTIONS bar.company.com. (No authentication cookie.)
Origin: foo.company.com.
With the Allow Unauthenticated CORS feature enabled on the secondary domain (like bar.company.com) application definition, the OPTIONS request gets forwarded to the destination even without an authentication cookie. - Request #3 : GET bar.company.com (with authentication cookie set for the domain company.com).
Prerequisites
- Both requests foo.company.com (primary) and bar.company.com (secondary) must originate from the same source egress (public) IP.
- If the primary (origin) and secondary (CORS resource) domains are the same (example, foo.company.com and bar.company.com), it is expected that the fetch request contains the credentials: ‘include’ option. An example javascript fetch with this header is shown below:
fetch('https://app-api.subdomain.domain.com/api/data', { method: 'GET' credentials: 'include', // Include cookies headers: { 'Content-Type': 'application/json', // Other headers if needed }, })
- In the HTTP response to the CORS resource, this HTTP header must be included: Access-Control-Allow-Credentials: true
This header will enable the browser to add the authentication cookie for the GET request to the CORS resource request (after the OPTIONS preflight request succeeds).
Important to Note
- It is expected that both foo.company.com (primary) and bar.company.com (secondary) are defined as Browser Access Applications and allowed by a policy. Only the secondary domain (bar.company.com), the CORS resource domain, would require the Allow Unauthenticated CORS feature to be enabled.
- It is expected that the foo.company.com (origin) domain is authenticated and has a valid authentication cookie via Browser Access for the CORS resource (bar.company.com) OPTIONS request to be allowed unauthenticated.