Python Tornado XSRF cookie issue with Chrome - python

I am new to Tornado and I am trying to build a very simple login form with xsrf cookie.
Code as below:
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("index.html")
def post(self):
self.write("You ahve submitted the form.!")
class App(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", MainHandler),
]
settings = dict(xsrf_cookies=True)
tornado.web.Application.__init__(self, handlers, **settings)
if __name__ == "__main__":
app = App()
server = tornado.httpserver.HTTPServer(app)
server.listen(7001)
tornado.ioloop.IOLoop.current().start()
The form is also very simple:
<html>
<head><title>Text XSRF</title></head>
<body>
<form method="post">
{% module xsrf_form_html() %}
{% raw xsrf_form_html() %}
Username:<input type="text" name="username">
Password:<input type="password" name="pwd">
<input type="submit" value="submit">
</form>
</body>
</body>
</html>
I am adding to the host file a domain:
127.0.0.1 xsrf.test.com
And when I open Chrome and type in hxxp://xsrf.test.com:7001, I can see the login form, but when sending the POST request I get a
403 (XSRF cookie does not match POST argument)
However, if I hit hxxp://localhost:7001, I can submit the form as expected. IE and Safari works fine for both domains. So I am wondering is there anything I did wrong to make this work using "xsrf.test.com" in Chrome?
I did check Chrome->Settings->Content Settings->Cookies->Allow local data to be set is properly selected.

Related

flask sessions and forms : trouble displaying user's username when chat page buttons are clicked

I am a beginner programmer working on a simple chatting application in flask using socketio. When a user submits the form on the login page, they are redirected to the chat page where the message "hello [username]" greets them.
However, when they click any other buttons on the chat page, the page refreshes and displays "hello [none]". I think that this problem originates from the flask sessions I have implemented: when a user starts a session and then refreshes the chat page, accessible only by a POST request, it is like they were passing no information in the login in form, which is why the chat page refreshes to "hello {None}".
However, I have no idea on how to fix this issue. I would like the user's username to be saved and be displayed even if they refresh the chat page.
Would I need to save the user's name in a database to achieve this or can this be fixed in another manner? here is the backend:
from flask import Flask, render_template, request, flash, session, redirect
from flask_socketio import SocketIO, send, emit
app = Flask(__name__)
app.static_folder = "static"
app.secret_key = "My_secret_key"
app.config["SECRET KEY"] = "another_secret!"
socketio = SocketIO(app)
#app.route('/')
def login_form():
return render_template('index.html')
#app.route('/chat-page', methods=["POST"])
def chat_page():
username = request.form.get("user_name")
session["user"] = username
return render_template('chat-page.html', Uname=username)
#app.route("/logout")
def logout():
session.pop("user", None)
flash("You have been logged out!")
return redirect("/")
# function to send messages to the entire group
#socketio.on("message")
def handle_message(msg):
print("message: " + msg)
send(msg, broadcast=True)
if __name__ == "__main__":
socketio.run(app)
here is the relevant front-end for the login page:
<form action="/chat-page" class="custom-centered" method="POST">
<!-- styling the form -->
<div class="d-inline-flex p-2">
<div class="input-group flex-nowrap">
<span class="input-group-text" id="addon-wrapping">#</span>
<input type="text" class="form-control" placeholder=" Enter a Username" name="user_name" aria-label="Username" aria-describedby="addon-wrapping" required>
</div>
</div>
<!-- end of styling the form -->
<button type="submit" class="btn btn-primary">Login!</button>
</form>
and here is the relevant front-end of the chat page
<h1> Hello {{Uname}}! </h1>
</div>
the solution that worked for me was
adding the following lines of code to the python file:
from flask_session import Session
and
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

POST method not working on Flask application

I'm trying to run a simple Flask application based on multiple simple tutorials. My goal is to finish a full tutorial and manipulate the code to build a search web app that connects to a SQL server database.
However, when I try running the code and provide an integer input, the POST method is not working, so it will not return a {{value}} as specified.
I've tried adding and removing several components: adding in the action='/' on the HTML, and trying to run the code as well without it. That didn't make a difference.
I have methods=['GET', 'POST'] already.
I even tried {{ url_for('/') }} and that just gave me an Internal Server Error.
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#app.route('/hello')
def hello():
return "My flask app"
#app.route('/', methods=["GET", "POST"])
def home():
if request.method == "POST":
value = int(request.form["number"])
add_one = value + 1
return render_template('index.html', string="WORLD!", value=add_one)
return render_template('index.html', string="WORLD!")
if __name__ == "__main__":
app.run()
HTML:
<body>
<div class="container">
<h1>Hello, {{string}}</h1>
<br>
<form action='/' role="form" method="post" onsubmit="return false;">
<div class="form-group">
<input type="number" class="form-control" name="number" placeholder="Enter a number" required>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<p>The calculated number is {{value}}</p>
<br>
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</body>
While running the code my app renders successfully, but when submitting a number the server does not register the input.
I don't even receive an error. All I see in the terminal is "GET / HTTP/1.1" 200.
By removing onsubmit="return false;" attribute of the form in the HTML.
And by restarting your app and reload the HTML.
It should be working.

flask + ngrok - redirect doesn't work

I've got the following app:
server.py
#app.route('/')
def main():
return render_template('index.html')
#app.route('/login')
def login():
return 'hey'
index.html
<body>
<form action="http://localhost:5000/login" , method="post">
<input type="submit" value="submit">
</body>
Now I run ngrok:
ngrok http 5000
After typing address (generated by ngrok) into web browser I can see index.html page with button, but when I press the button it redirects me to http://localhost:5000/login where I can see: "connection refused".
My question is how to set ngrok and flask server the way they can communicate?
P.S. I've put only a part of my code just for better reading
Btw, I've figured out how to make it other way. After running command:
ngrok http 5000
I get ngrok address thanks to this python script:
import json
import os
def get_ngrok_address():
os.system("curl http://localhost:4040/api/tunnels > tunnels.json")
with open('tunnels.json') as data_file:
datajson = json.load(data_file)
return dict(zip(['http', 'https'], [i['public_url'] for i in datajson['tunnels']]))
It just gets json object and converts it to python dict:
'http' -> ngrok_http_address
'https' -> ngrok_https_address
Before server start I pass generated address to all html templates e.x.:
<body>
<form action="{{ ngrok_address }}/login", method="post">
<input type="submit" value="submit">
</body>
What happens if you add the POST method to the login route
#app.route('/login', methods=['POST'])
def login():
return 'hey'
and change the form action to
<body>
<form action="/login", method="post">
<input type="submit" value="submit">
</body>
hm?
Try to change your host of application.
app.run(host='0.0.0.0')
and then run the command ngrok http 5000
also add POST method for the your route.
#app.route('/login', methods=['POST'])
def login():
return 'hey'
Try Flask-PyNgrok to use ngrok as flask application extension.

How to use recaptcha without Flask-WTF

I have been making a file sharing website for quite a while and I want to implement recaptcha when people register to the website. The problem is that I can't use Flask-WTF because I will have to change a lot of my code (I have been programming without it).
I have found this Flask recaptcha that doesn't include the use of Flask-WTF but I can't seem to make it work (it doesn't show the recaptcha itself):
https://github.com/mardix/flask-recaptcha
I have followed step by step and still, it doesn't work. The only thing that I didn't do is the config.
EDIT:
The captcha is not working. Everytime that I enter the right info for the registration and mark the captcha, it says that the username/password is incorrect. If I don't mark it, it does the same.
Here is the captcha code (the others worked before):
recaptcha = ReCaptcha(app=app)
if recaptcha.verify() is False:
flash('Captcha is incorrect')
return redirect(url_for('register'))
<div id="captcha"">
{{ recaptcha }} - HTML PART
</div>
EDIT: After getting help from Nurzhan, I have changed the code and the captcha always returns false, no matter what.
You didn't try the config, but you need to indicate the keys in order to make your recaptcha work. These 2 options are NOT optional in the config:
RECAPTCHA_SITE_KEY : Public key
RECAPTCHA_SECRET_KEY: Private key
Set them with proper values and it see if it works.
EDIT:
It's working now. This is app.py:
import requests
import json
from flask import Flask, render_template, request
from flask_recaptcha import ReCaptcha
app = Flask(__name__)
app.config.update({'RECAPTCHA_ENABLED': True,
'RECAPTCHA_SITE_KEY':
'site_key',
'RECAPTCHA_SECRET_KEY':
'secret_key'})
recaptcha = ReCaptcha(app=app)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/submit', methods=['GET', 'POST'])
def submit():
print('SUBMIT CALLED')
username = ''
password = ''
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
print(request.form)
if username == 'username' and password == 'password':
print('CREDENTIALS ARE OK')
r = requests.post('https://www.google.com/recaptcha/api/siteverify',
data = {'secret' :
'secret_key',
'response' :
request.form['g-recaptcha-response']})
google_response = json.loads(r.text)
print('JSON: ', google_response)
if google_response['success']:
print('SUCCESS')
return render_template('profile.html')
else:
# FAILED
print('FAILED')
return render_template('index.html')
# if recaptcha.verify():
# # SUCCESS
app.run(debug=True)
This is the index.html page:
<!DOCTYPE html>
<html>
<head>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
<body>
<h1>Flask Recaptcha</h1>
<p>Flask Recaptcha Test</p>
<form method="post" action="/submit">
Username:<br>
<input type="text" name="username"><br>
Password:<br>
<input type="password" name="password">
{{ recaptcha }}
<input type="submit" value="Submit">
<div class="g-recaptcha" data-sitekey="site_key"></div>
</form>
</body>
</html>
This is the profile.html page if you pass the validation:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Profile page</h1>
<p>Registration is ok</p>
</body>
</html>
I couldn't make recaptcha.verify() work. In the official docs of Google Recaptcha it is stated that you need to send a post request to google recaptcha api separately after the client submits your form with your secret_key and g-recaptcha-response which you receive when user puts a tick in recaptcha.
Note that this is just an example code. You need to add your own site_key and secret_key to the app.py and index.html and also add a proper checking of user credentials for the registation like double entering password etc.

Request handler not working in GoogleAppEngine WSGI application

I am new to web development. I have written the following python code to get input in a form and send it to '/testform'
import webapp2
form="""
<form action="/testform">
<input name="q">
<input type="submit">
</form>
"""
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.out.write(form)
class TestHandler(webapp2.RequestHandler):
def get(self):
q=self.request.get("q")
self.response.out.write(q)
app = webapp2.WSGIApplication([
('/', MainHandler),('/testform',TestHandler)
], debug=True)
But when I am opening the file in my browser, nothing is being displayed. Why is it so?

Categories