I'm trying to build a Ember app with PHP REST framework as my api locally. The Ember app is being served at http://localhost:4200 and the api is being served from just http://localhost. This is causing a CORS issue. I've tried everything that I can think of, but I keep getting an error back saying the request was blocked and that the preflight channel did not succeed. It doesn't succeed in Firefox or Chrome.
I've added the following to the .htaccess file for my api:
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Origin "http://localhost:4200"
Header set Access-Control-Allow-Credentials true
Header set Access-Control-Allow-Headers "accept, content-type"
Here's my request headers:
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://localhost:4200
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
And the response headers:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, content-type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: http://localhost:4200
Connection: close
Content-Type: text/html; charset=utf-8
Date: Fri, 24 Jul 2015 17:10:49 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.12
Set-Cookie: 24fd751c8630b64fcf935a94e8bcef46=qih6pfnqo94d4cgi5b5d79h4i6; path=/
Transfer-Encoding: chunked
X-Powered-By: PHP/5.5.12
p3p: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Any ideas or solutions? Any help is appreciated. Thanks!
Is you your preflight OPTIONS request returning 200? You can try and return a 200 response with your .htaccess like this:
Header always set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header always set Access-Control-Allow-Origin "http://localhost:4200"
Header always set Access-Control-Allow-Credentials true
Header always set Access-Control-Allow-Headers "accept, content-type"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
One possible issue may be that the browser isn't caching the server response to the browser's OPTIONS request. To fix this, try including an "Access-Control-Max-Age" header in your response and setting it to something like '86400' (1 day). Another issue, according to MDN's documentation on CORS, may be that since you are specifying a specific origin and not just using a wildcard response for the origin, you need to include a "vary" header in your response to specify that responses from the server will depend on the origin of the request. This can be done in the response like so:
Vary: Origin
If you get a CORS error with your main request following a successful OPTIONS request, I believe you also need to include the "Access-Control-Allow-Origin" header and "Vary" header in that response as well.
Hope this helps!
As this answer states, proper handling of the pre-flight OPTIONS request is necessary, but NOT SUFFICIENT for cross-site resource requests to work. All responses to any subsequent requests after prefligh must include Access-Control-Allow-Headers. Hope this helps.
In the server side servlet, add the headers and return 200 status. Example from RESTFul WCF service, where following code was added in Global.asax file
protected void Application_AuthenticateRequest(object sender, EventArgs e){
Response.AddHeader("Access-Control-Allow-Origin", "*");
if (Context.Request.HttpMethod.Equals("OPTIONS")) {
Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
Response.StatusCode = (int)System.Net.HttpStatusCode.OK;
Context.ApplicationInstance.CompleteRequest();
}
}
Related
I'm using a fork of Django Simple SSO as an authentication mechanism on a Server.
It works great while we use the "standard" way to log in on the server. This means, we just access to the /login path, log in, and then navigate across the restricted paths, etc.
The problem comes when we want to connect to a 3rd server that also relays on SSO auth vía javascript/AJAX without direct access to /login path first.
I've tried to use django-cors-headers but didn't get the expected result.
I'm close to give up so any help is welcome.
The problem
Assume we are logged in on server 1 and auth server and we want a resource on server 2
When the browser is redirected to the Auth Server in order to verify that the browser is logged with a valid user, the cookie header is not transferred.
(See the diagram on button for further details on how Django Simple SSO works)
The headers set by the auth-server on the preflight request are the following:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept-encoding, accept, authorization, cookie, content-type, dnt, origin, user-agent, x-csrftoken, x-grafana-org-id, x-dashboard-id, x-panel-id, x-requested-with
Access-Control-Allow-Methods: DELETE, GET, OPTIONS, PATCH, POST, PUT
Access-Control-Allow-Origin: https://server1-domain
Access-Control-Max-Age: 86400
Connection: keep-alive
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Fri, 16 Jul 2021 12:14:54 GMT
Server: nginx
Vary: Origin
The headers on the GET request where the following:
Request/Client:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: es-ES,es;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Host: auth-server-domain
Origin: https://server1-domain
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36
x-grafana-org-id: 1
Response/Auth Server:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://server1-domain
Connection: keep-alive
Content-Language: es
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Fri, 16 Jul 2021 12:14:54 GMT
Location: /error_unauthorized_page
Referrer-Policy: same-origin
Server: nginx
Vary: Accept-Language, Cookie, Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
I think all the headers are correct, but it's clearly there are some error.
On the cookie side, I have tried to play with the SingleSite property, setting it to None and Lax without any change.
The domain set on the cookie browser's memory is "correct" from my point of view as it is .auth-server-domain (note the dot).
I'm using DJango 3.2.5 and Google Chrome as a web browser.
If you have any idea of why cookie is not being send on the auth-server-domain cors requests, I will really appreciate your comments.
If do you think I have missed any piece of relevant information, feel free to ask!
Thank everyone to reach this point and help me!
Appendix:
A simplified schema of how Simple SSO works:
When I am trying to integrate my react js application with the gateway I am facing CORS issue as below
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://IP:port/userme. (Reason: header ‘access-control-allow-credentials’ is not allowed according to header ‘Access-Control-Allow-Headers’ from CORS preflight response).
everything is working from curb & postman request but not from browser.
Curb request (successful request)
HTTP/1.1 200
X-Frame-Options: DENY
Access-Control-Expose-Headers:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: HEAD, DELETE, POST, GET, PATCH, PUT
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID=37C2604B133C7B9D1345A9E13A878A36; Path=/; HttpOnly
Expires: 0
Pragma: no-cache
X-XSS-Protection: 1; mode=block
Access-Control-Allow-Headers: authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction,Authorization
Content-Type: application/json;charset=UTF-8
Date: Tue, 17 Mar 2020 16:26:14 GMT
Transfer-Encoding: chunked
Try
1) enabling access-control-allow-credentials and
2) adding access-control-allow-credentials to the Access-Control-Allow-Headers list in the configuration.
CORS is enabled by default for all APIs but you need to send following values in header earlier i was sending Access-Control-Allow-Headers and other values too which was causing issue....
'Accept': 'application/json',
'content-Type':'application/json',
'Access-Control-Allow-Origin': '*',
'Authorization' : 'Bearer '+token,
I'm trying to configure an HAProxy backend to work with Google-CDN
I see that I always get to the HAProxy backend and the cache is always MISS
This is google-cdn requests regarding headers:
https://cloud.google.com/cdn/docs/caching#cacheability
and this is my HAProxy backend configurations (I've tried multiple sets of headers configuration, but never got an HIT):
http-response set-header Cache-Control public;max-age=31536000
http-response set-header Content-Length 260113322
# http-request add-header Cache-Control public;max-age=31533000
# http-request add-header Content-Length 26012101001
when I'm requesting the object in the browser these are the req\res headers:
Response Headers
alt-svc: clear
cache-control: public;max-age=31536000
content-length: 260113322
content-type: application/javascript; charset=utf-8
date: Thu, 05 Sep 2019 07:56:59 GMT
etag: W/"47e80-NwQR7oXLIZF+J1AAVu9L0mv54I4"
status: 200
vary: Accept-Encoding
via: 1.1 google
Request Headers
:authority: sapix-stg.example.net
:method: GET
:path: /bb/client/SX1234/main.js
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cache-control: no-cache
pragma: no-cache
sec-fetch-mode: navigate
sec-fetch-site: none
sec-fetch-user: ?1
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36
Thanks
Your Cache-Control reaponse header is malformed. The values are separared with a comma (and optional whitespace included by convention) -- not a semicolon.
http-response set-header Cache-Control "public, max-age=31536000"
The quotes are absorbed by the HAProxy parser. Also valid:
(no space)
http-response set-header Cache-Control public,max-age=31536000
(space escaped)
http-response set-header Cache-Control public,\ max-age=31536000
There should normally be no need to add Content-Length in the proxy. If your origin server isn't automatically setting either Content-Length or Transfer-Encoding in the response, then your server should be fixed, upgraded, or replaced.
It might be because your response contains "Vary" header. HAPoxy says that they don't cache that type of responses.
Problem
The Access-Control-Allow-Origin of the response header matches the request Origin header but I'm still getting the error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://myappname.herokuapp.com/api/v1/products. (Reason: CORS request did not succeed).[Learn More]
Headers
Response Header
HTTP/1.1 308 PERMANENT REDIRECT
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
Access-Control-Allow-Origin: http://localhost
Content-Length: 311
Content-Type: text/html; charset=utf-8
Date: Thu, 04 Apr 2019 10:03:39 GMT
Location: http://mpappname.herokuapp.com/api/v1/products/
Server: waitress
Via: 1.1 vegur
Request Header
Host: mpappname.herokuapp.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Referer: http://localhost/admin/main/products/create
Origin: http://localhost
DNT: 1
Connection: keep-alive
Background
The code that generates the headers is below but I'm more concerned with understanding why CORS preflight is rejecting this. This is for a flask api with a products CRUD design and token based authentication.
Cut version
from flask_cors import CORS
def create_app(config_name):
...
CORS(app, origins="http://localhost",
allow_headers=["Content-Type", "Authorization", "Access-Control-Allow-Credentials"],
supports_credentials=True)
...
return app
Full version
from flask import Flask
from config import config
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
CORS(app, origins="http://localhost",
allow_headers=["Content-Type", "Authorization", "Access-Control-Allow-Credentials"],
supports_credentials=True)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .api import api as api_blueprint
app.register_blueprint(api_blueprint, url_prefix='/api/v1')
return app
I was requesting
http://mpappname.herokuapp.com/api/v1/products
instead of
http://mpappname.herokuapp.com/api/v1/products/
Maybe obvious to some but I needed to read this blog post explicitly to understand this:
https://airbrake.io/blog/http-errors/308-permanent-redirect
The appearance of a 308 Permanent Redirect is usually not something that requires much user intervention. All modern browsers will automatically detect the 308 Permanent Redirect response code and process the redirection action to the new URI automatically. The server sending a 308 code will also include a special Location header as part of the response it sends to the client. This Location header indicates the new URI where the requested resource can be found. For example, if an HTTP POST method request is sent by the client as an attempt to login at the https://airbrake.io URL, the web server may be configured to redirect this POST request to a different URI, such as https://airbrake.io/login. In this scenario, the server may respond with a 308 Permanent Redirect code and include the Location: https://airbrake.io/login header in the response. This informs the user agent (browser) that the POST request data (login info) was received by the server, but the resource has been permanently moved to the Location header URI of https://airbrake.io/login.
I am trying to set server side cookies(sessions) in client side. But it is failing.
The process is as follows:
1) Inititate a call to an API which is residing in abc.com from blog.abc.com.
2) The API from abc.com is going to return a response object to blog.abc.com.
I am getting the set_cookie in response object from the API, but in the client side it is not setting!
The following are the request and response headers from abc.com when I called the API from blog.abc.com
Request Headers:
Host: abc.com
Connection: keep-alive
Accept: */*
Origin: http://blog.abc.com
Referer: http://blog.abc.com/
Response Headers:
Connection: keep-alive
Set-Cookie: session_token="2|1:0|10:1474371987|13:session_token|44:NDFjZjNiZjFiYjcwNDk4ZTk4NDllYmRhNmNkYzFjZTA=|f60c277db4f5f38ec31f55bc581ddcf997f38fa493276508156f983500de4b25"; expires=Wed, 21 Sep 2016 11:46:27 GMT; Path=/
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
X-Frame-Options: DENY
But in the client side (blog.abc.com), there is no cookie ("session-token").
Can anyone please help. Thanks in advance.
The cookie should still be getting set correctly on abc.com, but you can't see that cookie from javascript on blog.abc.com. This is part of the same-origin policy: you can't see cookies that are set for another domain (regardless of access-control-allow-*). If you need this information in the client, it needs to be in the body of the response.