Reputation: 928
We have an api endpoint that redirects to another server. It's called via XHR and seems to work fine in most browsers, except for Safari (specifically on iOS).
The error I'm getting in the console is: Cross-origin redirection denied by Cross-Origin Resource Sharing policy
We have CORS on the page that does the redirection and on the other server. The redirection page sets:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: false
The other server has:
Access-Control-Allow-Origin: *
How can I allow redirection in the CORS policy?
Upvotes: 12
Views: 34451
Reputation: 8083
Did you try?
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: "Origin, X-Requested-With, Content-Type, Accept"
Access-Control-Allow-Methods: *
For more check : http://enable-cors.org/
Upvotes: 1
Reputation: 25204
The W3C specification and other authoritative sources directly forbid wildcard Access-Control-Allow-Origin
when used with Access-Control-Allow-Credentials: true
.
Note: The string "*" cannot be used for a resource that supports credentials.
https://www.w3.org/TR/cors/#resource-requests
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials
If credentials mode is "include", then
Access-Control-Allow-Origin
cannot be*
.
https://fetch.spec.whatwg.org/#cors-protocol-and-credentials
Because your question lacks details, let's make some definitions:
First of all, I think, you want to make a workaround. As long as you told all endpoint are under your control, so you either:
It is also important to report a bug to WebKit tracker if it really violates the spec. To easier reproduce the case I made a CherryPy app, which you could attach to the report. The step to run it:
/etc/hosts
corsredirect.py
Run these commands in terminal
virtualenv -p python3 venv
. venv/bin/activate
pip install cherrypy
python corsredirect.py
Point your browser to http://domain-a:8080 and push the button
There's the app.
#!/usr/bin/env python3
'''
Add localhost aliases in /etc/hosts for "domain-a", "domain-b", "domain-c".
The flow is: [domain-a] --CORS-GET--> [domain-b] --redirect--> [domain-c].
Open as http://domain-a:8080/
'''
import cherrypy
def cors():
cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'
cherrypy.tools.cors = cherrypy._cptools.HandlerTool(cors)
class App:
@cherrypy.expose
def index(self):
return '''<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=utf-8' http-equiv='content-type'>
<title>CORS redirect test</title>
</head>
<body>
<button>make request</button>
<script type='text/javascript'>
document.querySelector('button').onclick = function()
{
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain-b:8080/redirect', true);
xhr.onload = function()
{
var text = xhr.responseText;
console.log('success', text);
};
xhr.onerror = function()
{
console.error('failure');
};
xhr.send();
};
</script>
</body>
</html>
'''
@cherrypy.expose
@cherrypy.config(**{'tools.cors.on': True})
def redirect(self):
raise cherrypy.HTTPRedirect('http://domain-c:8080/endpoint')
@cherrypy.expose
@cherrypy.config(**{'tools.cors.on': True})
@cherrypy.tools.json_out()
def endpoint(self):
return {'answer': 42}
if __name__ == '__main__':
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}
cherrypy.quickstart(App(), '/', config)
Upvotes: 11
Reputation: 41
For just about anything other than a "Simple request", the authoritative sources deny wildcard for the "Access-Control-Allow-Origin" header and require you to explicitly set the header "Access-Control-Allow-Headers".
Here is what Mozilla states for "Simple request":
The only allowed methods are:
- GET
- HEAD
- POST
Apart from the headers set automatically by the user agent (e.g. Connection, User-Agent, etc.), the only headers which are allowed to be manually set are:
- Accept
- Accept-Language
- Content-Language
- Content-Type
The only allowed values for the Content-Type header are:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
When your request doesn't meet the "Simple Request" requirements you probably fall into "Preflighted Requests".
methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
As for credentialed requests -
Important note: when responding to a credentialed request, server must specify a domain, and cannot use wild carding. Access-Control-Allow-Origin: *
Since you didn't provide the actual HTTP requests and responses from your page and servers I will have to make some assumptions. I am assuming that your page is loaded under the domain foo.example and that your API is under the same foo.example domain and that your "other" server is on the domain bar.example.
You likely need to setup your page to make a redirect request to the "other" server with these Headers:
Access-Control-Request-Method: GET, OPTIONS
Access-Control-Request-Headers: x-requested-with, Content-Type, CUSTOM-HEADER
You then likely need to setup your "other" server to respond to an Options request with:
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: x-requested-with, Content-Type, CUSTOM-HEADER
Then your page should be able to finish the request.
Upvotes: 1
Reputation: 1203
If you can change your url, you can get a try with a proxy pass configuration on your Apache. The call will look like to be on the same domain but it will not. https://httpd.apache.org/docs/current/fr/mod/mod_proxy.html
Upvotes: 1
Reputation: 545
I was running into a similar problem hosting my API on a Heroku app. On Chrome and Firefox, requests to my API from another domain were working perfectly, but on Safari, I was getting a frustrating "Cross-origin redirection denied by Cross-Origin Resource Sharing policy".
After some researching, it seems there might be a bug in Safari that prevents some redirects with CORS. I was able to get around this by requesting the Heroku app directly (myapp.herokuapp.com/api
) instead of to my domain (mydomain.com/api
).
If you've got a setup where there are redirects to your API, requesting the root domain directly might help.
Upvotes: 1
Reputation: 56
You need to set the "Access-Control-Allow-Methods" header.
Access-Control-Allow-Methods: *
Upvotes: 0