Falcon cors with Angular 2 - python

I do not understand the setup below used to work but it suddenly broke.
I configured CORS on Falcon as follow (I run it via gunicorn):
cors = CORS(
allow_all_origins=True,
allow_all_headers=True,
allow_all_methods=True
)
api = application = falcon.API(
middleware=[
cors.middleware,
auth_middleware,
sqlalchemy_middleware
]
)
On AngularJS
return this.authHttp.get(CONFIG.apiUrl + '/user').map(
(res: Response) => res.json());
Using http.get with manually setting the token does not work.
I have access to my token in localStorage.getItem('token').
I have got the following errors:
zone.js:2019 OPTIONS http://0.0.0.0:8000/user 401 (Unauthorized)
XMLHttpRequest cannot load http://0.0.0.0:8000/user. Response for preflight has invalid HTTP status code 401
I searched everywhere on the internet and I understand it is a server issue... However the server used to work with that configuration.
Let me know if you have any idea.
Cheers,

The solution was simple, I needed to disable the authentication from the FalconAuthMiddleware on 'OPTIONS' requests in my controller.
auth = {
'exempt_methods': ['OPTIONS']
}

Related

REACT + DJANGO - CORS Errors After Login - CORS header ‘Access-Control-Allow-Origin’ missing

We have a React + Django application on GCP App Engine instances and we are facing a CORS error when fetching data through our REST API.
We have already installed and configured the CORS package for the Django Rest Framework in our django application:
`
ALLOWED_HOSTS = [
'xxxxxxxxxxxx.appspot.com',
'yyyyyyyyyyyy.appspot.com',
]
CORS_ALLOWED_ORIGINS=[
'http://localhost:3000',
'https://xxxxxxxxxxxx.appspot.com',
'https://yyyyyyyyyyyy.appspot.com',
]
CORS_ALLOW_CREDENTIALS=True
`
The preflight request is successful as well as the application login, which performs an async request to our backend:
access-control-allow-origin: https://xxxxxxxxxxxxxxxxxxxxx.appspot.com
access-control-allow-headers: accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with
access-control-allow-methods: DELETE, GET, OPTIONS, PATCH, POST, PUT
access-control-max-age: 86400
The correct URL is passed through the allow-origins header. The actual GET request is then blocked with a 400 response code from the browser and the following error message:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxxxxx.appspot.com/api/entities?page_size=10. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 400.
The strangest thing is that we are able to login into the application and that uses an async request to the same domain, only after we login does this error appear.
We have gone through several stackoverflow pages and different configurations (Eg. Using Regex in he allow ORIGINS configuration) but nothing seems to work, the application always returns the CORS error.
Does anyone have any idea of what might be going on here?
After some debugging, we realized that the CORS error was actually masking another issue, related with the size of the cookies, that exceeded the allowed limit of the server.
The only way to view this error was to go to the network tab and preview the response data in Firefox, in Edge the response was empty, and we were not able to understand the real problem.

Flask App deployed on Heroku returns error on post requests

I deployed my Flask App on Heroku, I noticed that once deployed post request in the API don't work anymore and the app just responds with status code 400 and "message": "The browser (or proxy) sent a request that this server could not understand.". Get requests work normally but post don't. Also I am quite confused because if I run the app on localhost everything works as expected but not once deployed. Anyone knows how to solve?
To parse request argument I use args = ParseArgs.parse_args() from flask_restful and I retrive the value with:
args = ParseArgs.parse_args()
mode = args['Mode']
value = args['Value']
I tried to look up on google and I saw that it might be the Content-Type header with value application/json, I removed it but the problem still persists.

API ok from localhost but failed with Ajax - ERR_CONNECTION_REFUSED

I have a very minimal API (let's call it api.py) using Flask :
from flask import Flask, request
from flask_restx import Resource, Api
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app)
api = Api(app)
#api.route('/hello')
class HelloWorld(Resource):
def get(self):
return {"hello" : "world"}
if __name__ == '__main__':
app.run(port=5000)
}`
I then run : python3 api.py, no error
On another command line, I then query the API
curl http://localhost:5000/hello
which give me the right answer : {"hello": "world"}
On its side, the Flask App says : 127.0.0.1 - - [21/May/2020 22:55:38] "GET /hello HTTP/1.1" 200 -
Which seems ok to me
I then build a JS / Ajax Query to query the API from a WebPage :
$.ajax({
url: "http://localhost:5000/hello"
, type: "GET"
, contentType: "application/json"
, dataType: "json"
, success: function(data) {
console.log(data)
}
})
When I access the Web Page that fires the Ajax call, I get the following error message :
GET http://localhost:5000/hello net::ERR_CONNECTION_REFUSED
I understand that is a CORS issue. The problem is that I did test ALL the tricks from SO and other help forums with no success...
I did try :
from flask_cors import CORS
app.run(host="0.0.0.0", debug=True)
app.run(host="0.0.0.0", debug=False)
#cross-origin
...
Nothing works, I still have this ERR_CONNECTION_REFUSED
Thanks for any help on that subject, as I am loosing my head with that problem...
Your ajax call shouldn't be pointing to localhost. Replace it with the URL of the EC2 instance.
No need to configure Nginx to listen on your app's port for this task. Or exposing this port outside on the remote host.
But yes, for remote server setup ajax call shouldn't be pointing to the localhost. You need to update it to the url you see in the browser. So either machine IP or a DNS.
While for local machine debugging you could try 127.0.0.1 instead of localhost.
The second part of making this work is to deal with CORS:
for remote server CORS should be enabled both in the app (as middleware) and in the preflight request (see how to allow CORS for OPTIONS requests);
for local machine I would recommend disabling CORS by running the browser in disabled security mode (like disable-web-security flag for Chrome etc.).

Falcon CORS middleware does not work properly

I'm using Falcon CORS to allow access to my web service only from several domains. But it does not work properly.
Let me explain, if we take a look at my implementation:
ALLOWED_ORIGINS = ['*']
crossdomain_origin = CORS(allow_origins_list=[ALLOWED_ORIGINS], log_level='DEBUG')
app = falcon.API(middleware=[RequireJSON(), JSONTranslator(), cors.middleware])
When I make any post request to my API service, I get this warning:
Aborting response due to origin not allowed
But, then I get the correct response from my API.
Here is an official docs about this module: https://github.com/lwcolton/falcon-cors
Your code does not match the falcon-cors documentation's example:
import falcon
from falcon_cors import CORS
cors = CORS(allow_origins_list=['http://test.com:8080'])
api = falcon.API(middleware=[cors.middleware])
# ^^^^^^^^^^^^^^^
Note the cors.middleware variable is being passed into the api call. In your code you are creating crossdomain_origin but not passing it into the API setup.
If this does not solve it, please provide a working code example, including the Falcon resource classes, that is easy to test and reproduce, and I'm happy to try to assist.
edit:
From comments below, it sounds like falcon-cors is working properly, rather the problem may be origin header was being omitted from the request.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
The Origin header indicates the origin of the cross-site access request or preflight request.
I tried as guided by lwcolton on github here
And also set allow_all_headers=True, allow_all_methods=True
i.e. same as #Ryan comment
from falcon_cors import CORS
cors = CORS(
allow_all_origins=True,
allow_all_headers=True,
allow_all_methods=True,
)
api = falcon.API(middleware=[cors.middleware])
Side note:
ORIGIN '*' does not work on some browsers.. notably IE. In the past I've had to dynamically set the ORIGIN header to the 'host' name requested in the HTTP headers in order to support a wildcard domain host for a site I setup.
There's is another way to implement this without using falcon-cors
You might want to look at this on the official documentation - how-do-i-implement-cors-with-falcon
class CORSComponent:
def process_response(self, req, resp, resource, req_succeeded):
resp.set_header('Access-Control-Allow-Origin', '*')
if (req_succeeded
and req.method == 'OPTIONS'
and req.get_header('Access-Control-Request-Method')
):
# NOTE: This is a CORS preflight request. Patch the
# response accordingly.
allow = resp.get_header('Allow')
resp.delete_header('Allow')
allow_headers = req.get_header(
'Access-Control-Request-Headers',
default='*'
)
resp.set_headers((
('Access-Control-Allow-Methods', allow),
('Access-Control-Allow-Headers', allow_headers),
('Access-Control-Max-Age', '86400'), # 24 hours
))
When using the above approach, OPTIONS requests must also be special-cased in any other middleware or hooks you use for auth, content-negotiation, etc. For example, you will typically skip auth for preflight requests because it is simply unnecessary; note that such request do not include the Authorization header in any case.
You can now put this in middleware
api = falcon.API(middleware=[
CORSComponent()
])

Flask CORS - no Access-control-allow-origin header present on a redirect()

I am implementing OAuth Twitter User-sign in (Flask API and Angular)
I keep getting the following error when I click the sign in with twitter button and a pop up window opens:
XMLHttpRequest cannot load https://api.twitter.com/oauth/authenticate?oauth_token=r-euFwAAAAAAgJsmAAABTp8VCiE. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I am using the python-Cors packages to handle CORS, and I already have instagram sign in working correctly.
I believe it has something to do with the response being a redirect but have not been able to correct the problem.
My flask code looks like this:
app = Flask(__name__, static_url_path='', static_folder=client_path)
cors = CORS(app, allow_headers='Content-Type', CORS_SEND_WILDCARD=True)
app.config.from_object('config')
#app.route('/auth/twitter', methods=['POST','OPTIONS'])
#cross_origin(origins='*', send_wildcard=True)
##crossdomain(origin='')
def twitter():
request_token_url = 'https://api.twitter.com/oauth/request_token'
access_token_url = 'https://api.twitter.com/oauth/access_token'
authenticate_url = 'https://api.twitter.com/oauth/authenticate'
# print request.headers
if request.args.get('oauth_token') and request.args.get('oauth_verifier'):
-- omitted for brevity --
else:
oauth = OAuth1(app.config['TWITTER_CONSUMER_KEY'],
client_secret=app.config['TWITTER_CONSUMER_SECRET'],
callback_uri=app.config['TWITTER_CALLBACK_URL'])
r = requests.post(request_token_url, auth=oauth)
oauth_token = dict(parse_qsl(r.text))
qs = urlencode(dict(oauth_token=oauth_token['oauth_token']))
return redirect(authenticate_url + '?' + qs)
The problem is not yours. Your client-side application is sending requests to Twitter, so it isn't you that need to support CORS, it is Twitter. But the Twitter API does not currently support CORS, which effectively means that you cannot talk to it directly from the browser.
A common practice to avoid this problem is to have your client-side app send the authentication requests to a server of your own (such as this same Flask application that you have), and in turn the server connects to the Twitter API. Since the server side isn't bound to the CORS requirements there is no problem.
In case you want some ideas, I have written a blog article on doing this type of authentication flow for Facebook and Twitter: http://blog.miguelgrinberg.com/post/oauth-authentication-with-flask

Categories