Flask-sentinel /oauth/token endpoint CORS issue - python

I'm having issues trying to get a token from my flask-sentinel app with my front-end.
To make the AJAX requests from my front-end to my Python Eve API server I use the superagent module.
While using a Basic Authentication I don't have any issue getting data from my endpoints. See code below:
superagent
.get( 'http://192.168.1.x:5000/endpoint' )
.auth( this.params.username, this.params.password )
.on( 'error', this.onError )
.then( this.onSuccess );
If I try to request a token to the /oauth/token endpoint with this code:
superagent
.post( 'http://192.168.1.x:5000/oauth/token' )
.set( 'Content-Type', 'application/x-www-form-urlencoded' )
.send( 'grant_type=password&client_id='+this.params.client_id+'&username='+this.params.username+'&password='+this.params.password )
.on( 'error', this.onError )
.then( this.onTokenReceived );
I get a CORS error:
Access to XMLHttpRequest at 'http://192.168.1.x:5000/oauth/token' from origin 'http://192.168.1.y:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here are the settings of my application (omitting the database and domain settings):
SENTINEL_X_DOMAINS = ['http://192.168.1.y:3000']
SENTINEL_X_HEADERS = ['Authorization','Content-type','If-Match','Access-Control-Allow-Origin']
SENTINEL_X_EXPOSE_HEADERS = SENTINEL_X_HEADERS
SENTINEL_RESOURCE_METHODS = ['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS']
SENTINEL_PUBLIC_METHODS = SENTINEL_RESOURCE_METHODS
SENTINEL_X_ALLOW_CREDENTIALS = True
X_DOMAINS = ['http://192.168.1.y:3000']
X_ALLOW_CREDENTIALS = True
X_HEADERS = ['Authorization','Content-type','If-Match','Access-Control-Allow-Origin']
RESOURCE_METHODS = ['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS']
Can you please guide me in getting what I'm doing wrong?
Thank you in advance!

It's possible that because the content-type is not text/plain, the browser is issuing an OPTIONS request. and as stated in the console error the response does not set the 'Access-Control-Allow-Origin' header.
From looking at Eve's docs, it seems you need to set the X_EXPOSE_HEADERS variable with ['Access-Control-Allow-Origin'] that:
"Allows API maintainers to specify which headers are exposed within a
CORS response. Allowed values are: None or a list of headers names.
Defaults to None."
The browser expects to receive the 'Access-Control-Allow-Origin', thus the failure.
Try to allow this header in the response from the API

In your Flask app, try setting the 'Access-Control-Allow-Origin' header in your response, i.e.,
response.headers.add('Access-Control-Allow-Origin', '*')
That should most likely solve the issue.

I have sorted out how to fix this though I am not completely satisfied.
Here the steps I've followed:
I have forked the Flask Sentinel repository
I have installed Flas-CORS with Pip
I have edited the flask_sentinel/flask_sentinel.py file by importing flask_cors
Before this line I've inserted this piece of code:
CORS(app, origins=['http://192.168.1.y:3000','https://192.168.1.y:3000'])
I went back to my Eve project and installed Flask-Sentinel through my forked repository with Pip instead of the original one

Related

API giving CORS Error to the frontent even though it should allow it

I'm making an API with FastAPI, and the frontend is made with next.js, so when the nextjs application makes a post request to the API, it should return the data normally with no problem, but it keeps giving a CORS error, the cors in the API are:
origins = ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
and the cors error is
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://jc-api-test.herokuapp.com/users/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 500.
Since the error code is 500 - this is an internal server error, meaning something is wrong with your code. When a 500 error happens, the CORSMiddleware doesn't get to add any headers to the response, since an exception is thrown and regular request processing no longer happens.
Fix the error first (the log will show you what actually happens), then start debugging any CORS issues after that (see the other answers).
The client should be making an OPTIONS request before the POST. It's the server's response to that initial call that needs to have the Acces-Control-Allow-Origin header. Then also that header's value must match the client (that heroku domain in your error message). Make sure your server is handling that OPTIONS correctly and it should work.
Your allow_credentials setting breaks the setting.
As stated in FastAPI documentation, if allow_credentials is True, you must define some origins instead of ['*']:
allow_credentials - Indicate that cookies should be supported for cross-origin requests. Defaults to False. Also, allow_origins cannot be set to ['*'] for credentials to be allowed, origins must be specified.

Ajax POST blocked by CORS Policy

Hi I've been scrambling the web for hours now trying to find a solution.
I'm trying to make a post request to my own web server hosted by Namecheap.
Here's my Ajax code to call the Post request. Note: I can't show the url sorry.
$.ajax({
url: "https://api.someurl.com/something" + avariable + "/" + anotherthing,
type: "POST",
crossDomain: true,
dataType: "json",
success: function (response) {
var resp = JSON.parse(response)
console.log(resp)
},
error: function (xhr, status) {
console.log("error")
}
});
This was a code i got from another stackoverflow post's answer which had the most upvotes. It didn't seem to work. actually all of them didn't work.
I'm calling this ajax from a index.html I have running on my localhost.
And i got this error:
Access to XMLHttpRequest at 'the url i cant show' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Any help would be much appericiated! I've never encountered this issue before and I don't know how to handle it.
Update 1
I have access to the backend server. Its running Flask on Python.
Any ideas how I can enable the CORS thing there?
Also I'm not sure what the origin of this index.html will be. Because I'll be packaging it into an electron js desktop application.
Install flask-cors in your flask app:
pip install -U flask-cors
Then in your code:
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
#app.route("/something+avariable/anotherthing")
#cross_origin()
def yourfunction():
Alternatively, add it manually:
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
return response
If you need it for development only then you can use a CORS browser extension such as this for Chrome and this for FireFox.
CORS stands for Cross Origin Resource Sharing.
Its just a mechanism to block unauthorized request to a server.
On your backend you will have yo authorize the address you are using to access your backend.
For php:

“No 'Access-Control-Allow-Origin' header is present” error for some requests but not others

I have a VueJS app running on S3 that is served by a Flask-powered API running on AWS Elastic Beastalk.
The problem
When making some requests, I get the following:
Access to XMLHttpRequest at 'https://api.myflaskapi.net/blueprint/get_info?date=2019-01-01' from origin 'https://app.myvuejsapp.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What I've done so far
In my __init__.py file, initialized by the app factory in Flask I have set CORS(app, support_credentials=True) as the example on this link. With that, I would hope that basically any request would have the CORS heading, so I wouldn't have any policy blocking my frontend requests.
The ideal scenario would be to only allow requests from https://app.myvuejsapp.net, so I tried using CORS(app, support_credentials=True, origins=['https://app.myvuejsapp.net']) but also without success.
I've also tried making one CORS instance for each of my blueprints with CORS(myblueprint) for each .py route file (I have one for each blueprint), also without success.
The strange thing is, I do have one function on Vue that runs when the app is mounted that works just fine. I can't see any difference between this and other functions that won't work.
Example of working function (returns true or false from the backend):
checkDB() {
const path = this.base_url + 'blueprint/check_db'
axios.get(path, this.token)
.then(checkupd => {
this.isupdated = Boolean(checkupd.data);
if (this.isupdated == true) {
this.update_msg = "Database up to date."
this.loading = false
this.finished = true
} else {
this.update_msg = "WARNING: Check DB status."
}
})
.catch(error => {
console.log(error)
})
},
Example of non-working function (returns a XLS from the backend):
getSalesFrom(file) {
const fs = require('fs')
const FileDownload = require('js-file-download');
const path = this.base_url + `blueprint/get_sales?date=${this.date}`
axios.get(path, {
headers:
{
"X-Access-Token": "mytoken",
"Content-Type": "application/json"
},
responseType: 'blob'
})
.then(response => {
const content = response.headers['content-type'];
download(response.data, 'text.xlsx', content)
})
.catch(error => {
console.log(error)
})
this.export_dialog = false
}
S3 CORS Configuration XML
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
<AllowedHeader>Content-Length</AllowedHeader>
<AllowedHeader>Access-Control-Allow-Origin</AllowedHeader>
<AllowedHeader>X-Access-Token</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Any ideas on what I might be doing wrong?
I've been reading for a while, but can't seem to find a solution for what it seems a pretty simple problem... Maybe I should mess with the S3 bucket permission configuration?
Thanks.
Any time you run into a case where you’re seeing a “No 'Access-Control-Allow-Origin' header is present” message for some requests but not others, use the Network pane in browser devtools to check the HTTP status code of the response.
Almost always what you’re going to find is that the HTTP status code in those cases is a 4xx or 5xx error instead of the expected 200 OK success response.
The only reason you see the “No 'Access-Control-Allow-Origin' header is present” message is those cases is, the Access-Control-Allow-Origin header typically isn’t going to get added to 4xx and 5xx errors. Part of the reason is, in the 5xx case especially, the cause can be a server failure that occurs before the server ever gets around to running your application code. Along with that, most servers by default won’t add application-set response headers to 4xx and 5xx errors; instead by default they only add them to 2xx success responses.
So anyway, what you want to do is, look at the server logs on the server side (for the server you’re sending the request to) and see what messages the server is logging about the cause of whatever problem it is that makes the server end up sending that 4xx or 5xx error response.
As I understand correctly you host your Vue.js application from S3.
You need to include CORS headers in your S3 buckets. Without them the browser will block all requests to your Flask application. You are making requests to api.myflaskapi.net from app.myvuejsapp.net so you need configure CORS in app.myvuejsapp.net.
You can read documentation how to set CORS in S3 here and here.
To configure your bucket to allow cross-origin requests, you create a CORS configuration, which is an XML document with rules that identify the origins that you will allow to access your bucket, the operations (HTTP methods) that will support for each origin, and other operation-specific information.
You can add up to 100 rules to the configuration. You add the XML document as the cors subresource to the bucket either programmatically or by using the Amazon S3 console. For more information, see Enabling Cross-Origin Resource Sharing (CORS).

Python Flask CORS - API always allows any origin

I've looked through many SO answers, and can't seem to find this issue. I have a feeling that I'm just missing something obvious.
I have a basic Flask api, and I've implemented both the flask_cors extension and the custom Flask decorator [#crossdomain from Armin Ronacher].1 (http://flask.pocoo.org/snippets/56/) Both show the same issue.
This is my example app:
application = Flask(__name__,
static_url_path='',
static_folder='static')
CORS(application)
application.config['CORS_HEADERS'] = 'Content-Type'
#application.route('/api/v1.0/example')
#cross_origin(origins=['http://example.com'])
# #crossdomain(origin='http://example.com')
def api_example():
print(request.headers)
response = jsonify({'key': 'value'})
print(response.headers)
return response
(EDIT 3 inserted):
When I make a GET request to that endpoint from JS in a browser (from 127.0.0.1), it always returns 200, when I would expect to see:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:5000' is therefore not allowed access. The response had HTTP status code 403.
CURL:
ACCT:ENVIRON user$ curl -i http://127.0.0.1:5000/api/v1.0/example
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 20
Access-Control-Allow-Origin: http://example.com
Server: Werkzeug/0.11.4 Python/2.7.11
Date: [datetime]
{
"key": "value"
}
LOG:
Content-Length:
User-Agent: curl/7.54.0
Host: 127.0.0.1:5000
Accept: */*
Content-Type:
Content-Type: application/json
Content-Length: 20
127.0.0.1 - - [datetime] "GET /api/v1.0/example HTTP/1.1" 200 -
I'm not even seeing all of the proper headers in the response, and it doesn't seem to care what the origin is in the request.
Any ideas what I'm missing? Thanks!
EDIT:
As a side note, looking at the documentation example here (https://flask-cors.readthedocs.io/en/v1.7.4/#a-more-complicated-example), it shows:
#app.route("/")
def helloWorld():
'''
Since the path '/' does not match the regular expression r'/api/*',
this route does not have CORS headers set.
'''
return '''This view is not exposed over CORS.'''
...which is rather interesting since I already have the root path (and others) exposed without any CORS decoration, and they are working fine from any origin. So it seems that there is something fundamentally wrong with this setup.
Along those lines, the tutorial here (https://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask) seems to indicate that Flask apis should naturally be exposed without protection (I would assume that's just since the CORS extension hasn't been applied), but my application is basically just operating like the CORS extension doesn't even exist (other than a few notes in the log that you can see).
EDIT 2:
My comments were unclear, so I created three example endpoints on AWS API Gateway with different CORS settings. They are GET method endpoints that simply return "success":
1) CORS not enabled (default):
Endpoint: https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default
Response:
XMLHttpRequest cannot load
https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-default.
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://127.0.0.1:5000' is therefore not allowed
access. The response had HTTP status code 403.
2) CORS enabled - Origin Restricted:
Access-Control-Allow-Headers: 'Content-Type'
Access-Control-Allow-Origin: 'http://example.com'
Endpoint: https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example
Response:
XMLHttpRequest cannot load
https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-example.
Response to preflight request doesn't pass access control check: The
'Access-Control-Allow-Origin' header has a value 'http://example.com'
that is not equal to the supplied origin. Origin
'http://127.0.0.1:5000' is therefore not allowed access.
3) CORS enabled - Origin Wildcard:
Access-Control-Allow-Headers: 'Content-Type'
Access-Control-Allow-Origin: '*'
Endpoint: https://t9is0yupn4.execute-api.us-east-1.amazonaws.com/prod/cors-enabled-wildcard
Response:
"success"
I'm not that experienced with infrastructure, but my expectation was that enabling the Flask CORS extension would cause my api endpoints to mimic this behavior depending on what I set at the origins= setting. What am I missing in this Flask setup?
SOLUTION EDIT:
Alright, so given that something on my end was obviously not normal, I stripped down my app and re-implemented some very basic APIs for each variation of CORS origin restriction. I've been using AWS's elastic beanstalk to host the test environment, so I re-uploaded those examples and ran a JS ajax request to each. It's now working.
I'm getting the Access-Control-Allow-Origin error on naked endpoints. It appears that when I configured the app for deployment I was uncommenting CORS(application, resources=r'/api/*'), which was obviously allowing all origins for the naked endpoints!
I'm not sure why my route with a specific restriction (origins=[]) was also allowing everything, but that must have been some type of typo or something small, because it's working now.
A special thanks to sideshowbarker for all the help!
From your question as-is, it’s not completely clear what behavior you’re expecting. But as far as how the CORS protocol works, it seems like your server is already behaving as expected.
Specifically, the curl response cited in the question shows this response header:
Access-Control-Allow-Origin: http://example.com
That indicates a server already configured to tell browsers, Only allow cross-origin requests from frontend JavaScript code running in browsers if code’s running at the origin http://example.com.
If the behavior you’re expecting is that the server will now refuse requests from non-browser clients such as curl, then CORS configuration on its own isn’t going to cause a server to do that.
The only thing a server does differently when you configure it with CORS support is just to send the Access-Control-Allow-Origin response header and other CORS response headers. That’s it.
Actual enforcement of CORS restrictions is done only by browsers, not by servers.
So no matter what server-side CORS configuration you make, the server still goes on accepting requests from all clients and origins it would otherwise; in other words, all clients from all origins still keep on getting responses from the server just as they would otherwise.
But browsers will only expose responses from cross-origin requests to frontend JavsScript code running at a particular origin if the server the request was sent to opts-in to permitting the request by responding with an Access-Control-Allow-Origin header that allows that origin.
That’s the only thing you can do using CORS configuration. You can’t make a server only accept and respond to requests from particular origins just by doing any server-side CORS configuration. To do that, you need to use something other than just CORS configuration.

Django cors error even after installing cors-headers

My python view is using requests, like so:
r = requests.post(url, params=data, headers=header)
print r.url
return HttpResponse(r)
The object is POSTED to a redirect URL. When the URL is called, all activity stops in the browser and this error is thrown:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://<website>.com. This can be fixed by moving the resource to the same domain or enabling CORS.
I have already installed django-cors-headers with the following line added in the settings.py:
CORS_ORIGIN_ALLOW_ALL = True
Why am I still getting the error?
Make sure you have added the correct CORS middleware and more importantly its sequence and its allowed methods too.
Also, make sure it's listed in your installed_apps setting.

Categories

Resources