I've built an App engine API in Python that's fetched by a Node application. The API works as expected for (1) get and post requests in production and (2) get requests in development. It fails on post requests in development and I could use some help figuring out why.
Error messages
In my node environment I see the error:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4444' is therefore not allowed
access. The response had HTTP status code 500. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
But I am already using the flask_cors package inside my app so I wonder if this is really a CORS issue.
My activated virtual python environment logs:
File
"/myproject/googleAdsApi/env/lib/python2.7/site-packages/urllib3/contrib/appengine.py",
line 103, in init
"URLFetch is not available in this environment.")
So perhaps I should use an alternative to URLFetch within my virtual environment?
My current implementation
Fetching:
fetch('http://localhost:8080/api/get_accounts', {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json; charset=utf-8",
},
redirect: "follow",
referrer: "no-referrer",
body: JSON.stringify(credentials)
})
.then(response => response.json())
.then(result => console.log(result));
flask_cors:
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
Always use dev_appserver.py for running your local development environment on GAE apps. GAE has a lot of peculiarities that are hard to reproduce manually on a local virtualenv. Plus you get a lot of useful tools to monitor various services (Taskqueues, Memcache, Storage, etc). dev_appserver.py also automatically loads a lot of GAE native apis for you to be able to use and very often they have their own versions of popular libs that are adapted for a serverless environment (URLFetch is one of them)
Official Docs
https://cloud.google.com/appengine/docs/standard/python/tools/using-local-server
Related
I have a public cloud VM which has public IP say 160.159.158.157 (this has a domain registered against it).
I have a Django application (backend) which is CORS-enabled and serves data through port 8080.
I have a React app running on the same VIM on a different port (3000), which is accessing the Django app and is supposed to produce a report.
The problem is that, when I use http://<domain-name>:8080/api/ or http://<public-ip>:8080/api/, my application is working fine,
but when I try to fetch data from localhost like http://localhost:8080/api/ or http://127.0.0.1:8080/api/, the React app fails to fetch data with the following error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8080/api/. (Reason: CORS request did not succeed). Status code: (null).
Here's what I've tried:
axios.get(baseURL, { headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
}
but it didn't work. What should I do?
Looks like you've gotten confused where those headers need to be. You're setting them on the request to the backend, but they need to be set on the response from the backend. After all, it wouldn't be very good security if someone making a request could simply say "yeah, I'm ok, you should trust me".
The problem is going to be somewhere in your backend Django app, so double check the CORS config over there.
The Problem:
The library flask-oidc includes the scope parameter into the authorization-code/access-token exchange request, which unsurprisingly throws the following error:
oauth2client.client.FlowExchangeError: invalid_request Scope parameter is not supported on an authorization code access_token exchange request. Scope parameter should be supplied to the authorized request.
The Question:
Is this a configuration problem or a library problem?
My Configurations:
Flask Application:
app.config.update({
'DEBUG': True,
'TESTING': True,
'SECRET_KEY': 'secret',
'SERVER_NAME' : 'flask.example.com:8000',
'OIDC_COOKIE_SECURE': False,
'OIDC_REQUIRE_VERIFIED_EMAIL': False,
'OIDC_CALLBACK_ROUTE': '/oidc/callback',
'OIDC_CLIENT_SECRETS': 'client_secrets.json'
})
oidc = OpenIDConnect(app)
client_secrets.json
{
"web": {
"auth_uri": "http://openam.example.com:8080/openam/oauth2/realms/root/authorize",
"issuer": "http://openam.example.com:8080/openam/oauth2/realms/root/",
"userinfo_uri": "http://openam.example.com:8080/openam/oauth2/realms/root/userinfo",
"client_id": "MyClientID",
"client_secret": "password",
"redirect_uris": [
"http://flask.example.com:8000/oidc/callback"
],
"token_uri": "http://openam.example.com:8080/openam/oauth2/realms/root/token",
"token_introspection_uri": "http://openam.example.com:8080/openam/oauth2/realms/root/introspect"
}
}
Access Manager
For the access manager I use OpenAM. I configured an OpenAM client agent as follows:
Client ID = MyClientID
Client Secret = password
Response Type = code
Token Endpoint Authentication Method = client_secret_post
Redirect URI = http://flask.example.com:8000/oidc/callback
Context:
I use flask-oidc for the logic on the application side and OpenAM for the identity and access management - both applications run in docker containers. When using simple curl commands I can retrieve an authorization grant as well as an authentication token (grant type: Authorization Code Grant). However, using the mentioned library, after logging in to OpenAM and granting authorization to the application (endpoint 'oauth2/authorize'), flask-oidc sends the following GET request:
GET /oidc/callback?code=<some code> \
&scope=openid%20email \
&iss=http%3A%2F%2Fopenam.example.com%3A8080%2Fopenam%2Foauth2 \
&state=<some state> \
&client_id=MyClientID
Which leads to the error mentioned above.
While this does not directly answer the question, the best answer I could find was to use pyJWT or oauthlib instead of using flask-oidc. I found pyjwt was very straightforward in most respects, and there is an excellent tutorial here:
SSO Using Flask Request Oauthlib and pyjwt
I am not sure of this, but because the error is generated by oauth2client, not flask-oidc, it is possible the error is actually just related to the deprecated oathlib2clientlib.
There was a detailed request to mark the entire flask-oidc project as deprecated, but that request was made several years after the flask-oidc project was stopped being maintained. I hope one day flask will roove this link from their site because it is misleading to think that it is a main part of flask.
I can get my signalr code to connect + work no problem in my local environment by setting host with web url
"Host": {
"LocalHttpPort": 7070,
"CORS": "http://localhost:4200",
"CORSCredentials": true
}
Then I deploy it to the portal and go to CORS and add the web url that my storage blob static website is hosted on inside CORS for the signalr function app. When I login to my app with the web url matching cors value I get this for some reason
Also according to the docs (bottom part of page) I have to enable Access-Control-Allow-Crendentials
but it seems that a function app running on python doesn't have that option
How can I enable Access-Control-Allow-Crendentials in a python function app?
Yes, there is no way to set it on azure portal. Not only 'Access-Control-Allow-Crendentials', but also many other config settings cannot set by using azure portal when you are based on linux web app.
To achieve that you want, you can use below cmd in powershell:(It works when you are based on azure web app. azure function is based on web app sandbox, so below cmd also works on function.)
az resource update --name web --resource-group yourresoursegroupname --namespace Microsoft.Web --resource-type config --parent sites/yourfunctionname --set properties.cors.supportCredentials=true
This is the offcial doc:
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-rest-api#enable-cors
If your app requires credentials such as cookies or authentication
tokens to be sent, the browser may require the
ACCESS-CONTROL-ALLOW-CREDENTIALS header on the response. To enable
this in App Service, set properties.cors.supportCredentials to true in
your CORS config. This cannot be enabled when allowedOrigins includes
'*'.
On my side, I can change the config setting. Let me know whether you can change the config.:)
I'm trying to set up Google sign-in using Flask dance for a flask based website:
from flask_dance.contrib.google import make_google_blueprint, google
blueprint = make_google_blueprint(
client_id= "CLIENT_ID",
client_secret="CLIENT_SECRET",
scope=[
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/userinfo.email",
]
)
app.register_blueprint(blueprint, url_prefix="/google_login")
And as the documentation suggests, I have the view set up like this:
#app.route('/google_login')
def google_login():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.get("/oauth2/v2/userinfo")
assert resp.ok, resp.text
return "You are {email} on Google".format(email=resp.json()["email"])
When I was testing I set the environment variable, OAUTHLIB_INSECURE_TRANSPORT to 1 by using
export OAUTHLIB_INSECURE_TRANSPORT=1
And now even after I've removed the environment variable, for some reason the Flaskdance seems to always resolve the URI to a http instead of HTTPS.
This is evident from the redirect uri mismatch error I'm getting (here website refers to the domain name):
The redirect URI in the request,
http://"website"/google_login/google/authorized, does not match
the ones authorized for the OAuth client.
And here are the authorized redirect URIs I've set up in my Google cloud console:
https://"website"/google_login/google/authorized
https://www."website"/google_login/google/authorized
I tried unsetting the environment variable using this command:
unset OAUTHLIB_INSECURE_TRANSPORT
What am I missing here? Any help would be appreciated.
If Flask-Dance is generating http URLs instead of https, that indicates that Flask (not Flask-Dance, but Flask itself) is confused about whether the incoming request is an https request or not. Flask-Dance has some documentation about how to resolve this problem, and the most likely cause is a proxy server that handles the HTTPS separately from your application server.
The fix is to use a middleware like werkzeug's ProxyFix to teach Flask that it's behind a proxy server. Here's how you can use it:
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
I had the same problem and in my case adding this to my Apache VirtualHost config solved it:
RequestHeader set X-Forwarded-Proto "https"
My Flask is running behind an Apache proxy but Nginx would also have similar issues, potentially.
I have an app in Heroku running with Django.
Now I'm starting to develop a Phonegap app that I want to make work with my Heroku app.
I can't make it work because of CORS (Cross-origin resource sharing) protection. So I need to exclude some urls (not all app) to make my Phonegap app work.
I've tried installing django-cors-headers, but it doesn't seem to work.
To test it, I'm making a call to obtain a csrf_token.
I added this to my setting.py (and of course followed the guide, setting all to default):
CORS_URLS_REGEX = r'^register/.*$'
CORS_URLS_REGEX = r'^login/.*$'
CORS_URLS_REGEX = r'^getcsrf/.*$'
And this is the Ajax call I try to make:
get: function() {
$.getJSON("http://domain.herokuapp.com/getcsrf/",
{
tags: "jquery,javascript",
tagmode: "any",
format: "json"
},
function(data) {
$.each(data.items, function(item){
console.log(item);
});
});
}
But I get this marked in red as an error and an empty response field:
GET http://domain.herokuapp.com/getcsrf/?tags=jquery%2Cjavascript&tagmode=any&format=json 200 OK 206ms
There's no cross origin restrictions with phonegap, it's using a webview, not a web browser.
The only thing you have to do with phonegap/cordova is to be sure your server is whitelisted in config.xml.
In cordova 3.3/3.4, the default setting is <access origin="*" /> which should allow access to any url.