Flask WTF error - CSRF session token is missing (but actually not) - python

Currently trying to fix this issue, I have browsed many posts but still cannot solve this problem hence this message to the community :)
I am creating a dev/test environment for a Flask based website and I have to duplicate the current website into a subdomain, such as from mydomain.com to dev.mydomain.com and so on for the additional related services such as elastic search (e.g. from es.mydomain.com to es-dev.mydomain.com).
So here I am, I deployed everything through Nginx, the main website dev.mydomain.com and all services run and are accessible. BUT I cannot log in to Flask which throws me an error 400 missing CSRF session token when there is actually 2 session tokens ... it seems that 1 duplicate is created in the form submission process as the cookie holds 2 session keys.
Before form submission
Original cookie keys: _ga=...; _gid=...; session=...
Dev cookie keys: session=...; Domain=.dev.mydomain.com; Secure; HttpOnly; Path=/
After form submission
Original website cookie keys: _ga=...; _gid=...; session=...
Dev wbesite cookie keys: _ga=...; _gid=...; session=...; session=...
CSRF is enabled for the whole app via csrf.init_app(app) and my Flask config is:
SECRET_KEY = os.getenv("SECRET_KEY")
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
REMEMBER_COOKIE_SECURE = True
REMEMBER_COOKIE_HTTPONLY = True
I'm trying different config flavors but no improvement so far ...
Some help would be appreciated as always, thank you in advance :)

For the record, one just needs to set the SESSION_COOKIE_NAME configuration paramater to solve that problem
Cf. https://flask.palletsprojects.com/en/1.1.x/config/#SESSION_COOKIE_NAME

Related

Django 400 Bad request after pulling update from Github

I had a working page running Django with channels via Nginx, Daphne, Redis, and Gunicorn. After pulling an update from Github my index page now shows "Bad Request (400)" with nothing helpful in the console except for missing favicon. My settings.py has DEBUG = False and ALLOWED_HOSTS = ['AWS_IP']. Can anyone help me figure out what might be causing this?

Flaskdance doesn't generate a HTTPS uri

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.

SESSION_COOKIE_SECURE does not encrypt session

I'm trying to put some security on my Flask web app. As a first step I'm going to make my session cookie secure by setting SESSION_COOKIE_SECURE to true.
But after I get my session cookie from "inspect element" I can decode session cookie easily and there is no difference whether I add SESSION_COOKIE_SECURE or not.
Here is my code:
from flask import Flask, request, app, render_template, session, send_file, redirect
MyApp = Flask(__name__)
MyApp.secret_key = "something"
application = MyApp
if __name__ == "__main__":
MyApp.debug = False
MyApp.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
)
MyApp.config["SESSION_PERMANENT"] = True
MyApp.run()
I also tried to add this attribute using the following syntax but this made no difference:
MyApp.config['SESSION_COOKIE_SECURE'] = True
When I try to print SESSION_COOKIE_SECURE I get this error
Traceback (most recent call last):
File "...", line ..., in <module>
print(MyApp.session_cookie_secure)
AttributeError: 'Flask' object has no attribute 'session_cookie_secure'
My Flask version is 1.0.2, and I'm on HTTPS.
Setting SESSION_COOKIE_SECURE does not encrypt the cookie value, no. When set, this causes Flask to create cookies with the "Secure" flag set. This means that a browser can only return the cookie to the server over an encrypted connection, nothing more. The setting doesn't change anything about the cookie value itself.
Flask produces cookies that are cryptographically signed, by default. That means that the cookie contents can be decoded but not altered, because a third party without access to the server secret can't create a valid signature for the cookie.
You generally don't need to encrypt your session cookie if you a) use HTTPS (which encrypts the data from outsiders) and b) protect your web app from XSS attacks. Without an XSS attack vector, attackers can't get access to your cookie contents at all anyway.
You certainly don't need to do so here, as SESSION_COOKIE_HTTPONLY means that the browser will never expose the cookie to JavaScript, and only someone with full access to the browser can see the cookie value.
Flask doesn't have a 'encrypt cookie' setting, because it is not deemed necessary when you can secure the cookie in other ways. You should not store information in a session cookie so sensitive that it should be protected from the end-user with access to the browser storage; keep such data on the server and only store a unique identifier in the session to retrieve that secret data later on.
If for some reason you can't keep such secrets out of the session cookie and are unwilling to accept that the end-user can read this data, then you'll have to encrypt the cookie yourself or use an alternative session provider for Flask, such as EncryptedSession.
As for the attribute error: only a few configuration settings are accessible as attributes on the Flask object. To print arbitrary configuration settings, use the app.config object:
print(MyApp.config['SESSION_COOKIE_SECURE'])

Cookie not setting with Flask

I am trying to set a cookie with Flask after login and redirect on the front end in Javascript.
#app.route("/login")
#auth.login_required
def get_auth_token():
token = g.user.generate_auth_token()
request = make_response()
token = str(token.decode("ascii"))
request.set_cookie("token", value = token)
return request, 200
No matter if I have the redirect in or not, the cookie never sets. I've tried commenting out my redirect on the front end, I've tried setting my cookie with secure = false but none of that seems to work. What am I missing? If needed, I can provide the generate_suth_token function, but I know that is working properly. I am serving on localhost:5000 and using Flask 0.12.2, and received no cookie warnings in the server log.
If Flask service and client service are being hosted on different domains (e. g Flask uses 127.0.0.1:8080 and a client uses 127.0.0.1:3000) in this case, cookies should be set with domain parameter otherwise they will not be available.
resp.set_cookie('cookie_key', value="cookie_value", domain='127.0.0.1')
Find more info about domain parameter here

How to configure flask session behind iis reverse proxy (wfastcgi)?

I'm configuring my flask app to run under iis with a reverse proxy. Basically my setup is like this:
external.domain.com:8000 ->
Reverse Proxy IIS ->
interal.network.net ->
iis (wfastcgi/flask)
The app's urls and content is loading correctly, but anything that deals with a session is not working:
Message flashing - no messages are flashed
Login cookies - not able to login at all
I've configured the flask app with these relevent config variables:
SERVER_NAME = 'internal.network.net'
SESSION_COOKIE_DOMAIN = 'external.domain.com'
I have an IIS rewrite rule set up on the external server:
Pattern: (.*)
Rewrite URL: http://internal.network.net/{R:1}
Is there anything else I need to configure to get sessions working correctly?
Not sure if this is the correct way of doing things but apparently excluding the properties SERVER_NAME and SESSION_COOKIE_DOMAIN actually fixes the issue.
Hope this helps someone.

Categories

Resources