Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS request with Preflight and redirect: disallowed. Workarounds?

I'm designing an API that allows the user to authenticate (using tokens) and that contains redirects within the same domain. Now, for an unauthenticated request to an endpoint that returns 303,

GET /documents/123  --> 303 redirect to `/documents/abc` GET /documents/abc  --> 200 

everything works out nicely.

Let's do an authenticated request to the same endpoint where the Authorization header is sent. This makes the request a preflighted request and the browser does a preflight OPTIONS request, i.e.

OPTIONS /documents/123   --> 204 (everything okay, please proceed) GET /documents/123       --> 303 redirect to `/documents/abc` 

At this point, instead of GETting the actual resource at /documents/abc, the browser yields

XMLHttpRequest cannot load http://localhost:8000/people/username/nschloe.  The request was redirected to 'http://localhost:8000/people/YDHa-B2FhMie',  which is disallowed for cross-origin requests that require preflight. 

This behavior is in accordance with the standard:

7.1.5 Cross-Origin Request with Preflight

If the response has an HTTP status code that is not in the 2xx range

Apply the network error steps.

This seems to mean that one cannot do redirects for authenticated resources, even if the redirect is on the same domain (localhost).

Can this really be true? Is there a common workaround?

like image 362
Nico Schlömer Avatar asked Jan 22 '16 14:01

Nico Schlömer


People also ask

How do I fix redirect is not allowed for a preflight request?

When you see this error, it means your code is triggering your browser to send a CORS preflight OPTIONS request, and the server's responding with a 3xx redirect. To avoid the error, your request needs to get a 2xx success response instead.

Does CORS apply to redirect?

Simple CORS requests will follow redirects. Preflight requests will not follow redirects. If the redirect is to the same server as the original request, the Origin header will stay the same. Otherwise, the Origin header will be set to null .

What is CORS preflight request?

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers. It is an OPTIONS request, using three HTTP request headers: Access-Control-Request-Method , Access-Control-Request-Headers , and the Origin header.


1 Answers

The original standard does preclude redirect after a successful CORS preflight. Quoting § 7.1.5.3:

This is the actual request. Apply the make a request steps and observe the request rules below while making the request.

  • If the response has an HTTP status code of 301, 302, 303, 307, or 308 Apply the cache and network error steps.

Due to your efforts (thanks!), on August 4 2016 the standard was updated to allow redirect after successful CORS preflight check.

Until browsers catch up, the only feasible options seem to be one or a combination of:

  1. Issue redirects only for simple requests.
  2. Issue a 305 redirect, with your own URL in the Location header as the "proxy". Be prepared for limited browser support, as 305 is deprecated.
  3. Do a fake "redirect":
  • return HTML with meta refresh and/or Javascript Location change.
  • return HTML that has a viewport-filling iframe with the redirect target as the iframe's source.
  • display a link that the user has to click in order to access the content.
like image 169
bishop Avatar answered Sep 21 '22 20:09

bishop