Authlib client error: State not equal in request and response - flask

I'm trying to implement authlib client and server. I took example OAuth2.0 example and making my own client authorization on Flask site following tutorial. This is my code:
from flask import Flask, redirect, url_for, session, request
from authlib.flask.client import OAuth
from authlib.client.errors import OAuthException
APP_ID = 'KBtRDO3r2HETjw4TcLznthoj'
APP_SECRET = '3g4C6nbJcTIYX3jyCIEmf6KE8h8pzxUhjy6ArlY3AEgj1snv'
app = Flask('testa_client')
app.debug = True
app.secret_key = 'development'
oauth = OAuth()
oauth.init_app(app)
remote = oauth.register(
'testa',
client_id=APP_ID,
client_secret=APP_SECRET,
# request_token_params={'scope': 'base'},
base_url='http://127.0.0.1:5000',
access_token_url='http://127.0.0.1:5000/auth/token',
authorize_url='http://127.0.0.1:5000/auth/connect'
)
#app.route('/')
def index():
return redirect(url_for('login'))
#app.route('/login')
def login():
callback = url_for(
'websa_authorized',
next=request.args.get('next') or request.referrer or None,
_external=True
)
return remote.authorize_redirect(callback=callback)
#app.route('/login/authorized')
def websa_authorized():
resp = remote.authorize_access_token()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error_reason'],
request.args['error_description']
)
if isinstance(resp, OAuthException):
return 'Access denied: %s' % resp.message
session['oauth_token'] = (resp['access_token'], '')
me = remote.get('/user/me')
return 'Logged in as id=%s name=%s redirect=%s' % \
(me.data['id'], me.data['name'], request.args.get('next'))
app.run(port=9001)
Server code as I said almost the same as in https://github.com/authlib/example-oauth2-server repository.
When I'm trying to make an authorization I'm getting to the authorization server (on port 5000) and confirm that I allow access. But when I got redirect back to the client site on page http://127.0.0.1:9001/login/authorized?code=...&state=... (on 9001) I'm getting the error:
127.0.0.1 - - [20/Jun/2018 09:33:12] "GET /login/authorized?code=1jw8niqDdzSLpnYHGvT1NIulTwRdVoy22UNm3G4xEaTOWE9Y&state=JUuJtmnseITz8WZYaDeHcAsiIL6KfS HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise
raise value
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/xen/Dev/auth/client_example/client_testa.py", line 52, in testa_authorized
resp = remote.authorize_access_token()
File "/Users/xen/envs/auth-s4eELiZl/lib/python3.6/site-packages/authlib/flask/client/oauth.py", line 257, in authorize_access_token
raise MismatchingStateError()
authlib.client.errors.MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response.
What can be wrong? Both parts use Authlib 0.8.

I've spent a lot of time to find an error in my code. The problem was not in the code, but in the way I use it. I accessed both applications by local IP address 127.0.0.1 and different ports. Browser mix sessions and cookies for such related URIs. I give another local domain name (http://test:9001 in my case) for the service and that fixed my problem.
When you work with OAuth don't use the local address and same domains.

Related

2021-02-16 10:43:57,123 ERROR in app: Exception on / GET?

I want to embed/put a tkinter gui in a flask app, but the code i made seems not to be rendering/show and gives this error when i run my code:
[2021-02-16 10:43:57,123] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\site-packages\flask\app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "C:\ProgramData\Anaconda3\lib\site-packages\flask\app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\ProgramData\Anaconda3\lib\site-packages\flask\app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\ProgramData\Anaconda3\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\ProgramData\Anaconda3\lib\site-packages\flask\app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "C:\ProgramData\Anaconda3\lib\site-packages\flask\app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\User\untitled0.py", line 14, in my_app
File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 2369, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 2299, in __init__
(widgetName, self._w) + extra + self._options(cnf))
File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 1326, in _options
v = self._register(v)
File "C:\ProgramData\Anaconda3\lib\tkinter\__init__.py", line 1372, in _register
self.tk.createcommand(name, f)
RuntimeError: main thread is not in main loop
127.0.0.1 - - [16/Feb/2021 10:43:57] "GET / HTTP/1.1" 500 -
also when i want to run the flask web server it shows Internal Server Error The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
from flask import Flask
from webbrowser import open
app = Flask(__name__)
root = Tk()
root.title("Tkinter")
#app.route('/')
def my_app():
def click():
l = Label(root, text = "You Clicked!").pack()
b = Button(root, text = "Click Me!", command = click).pack()
return(root)
if __name__ == '__main__':
open('http://127.0.0.1:5000/')
app.run()
#root.mainloop()

Flask-Security Login Functional testing

I'm trying to do some functional testing on Flask view functions.
Currently I'm using login, logout from Flask Security module and when I try to follow the login and logout guide from flask's documentation(http://flask.pocoo.org/docs/0.12/testing/#logging-in-and-out), the 'post' of login seems to not working. I've been getting this same error when I try to post using requests module too.
My Flask-Security's login endpoint is /login_test/
Below are piece of my unit test code.
class TestUser(unittest.TestCase):
#run before each test
def setUp(self):
self.client = app.test_client()
db.create_all()
def tearDown(self):
#db.session.remove()
#DropEverything().drop_db()
pass
def login(self, email, password):
return self.client.post('/login_test/', data=dict(
email=email,
password=password
), follow_redirects=False)
def logout(self):
return self.client.get('/logout', follow_redirects=True)
def test_login_logout(self):
response = self.client.post('/login_test', data=dict(
email='admin',
password='admin'
), follow_redirects=False)
self.assertIn(b'You logged in', response.data)
The error message that I got after hitting test_login_logout is like below. The below is when I hit the url with '/login_test'
Ran 1 test in 0.187s
FAILED (failures=1)
Failure
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/case.py", line 58, in testPartExecutor
yield
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/case.py", line 600, in run
testMethod()
File "/Users/genom003dm/PycharmProjects/sample_accessioning_dev/app/tests/user_management_testing.py", line 38, in test_login_logout
), follow_redirects=False)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/werkzeug/test.py", line 801, in post
return self.open(*args, **kw)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/testing.py", line 127, in open
follow_redirects=follow_redirects)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/werkzeug/test.py", line 764, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/werkzeug/test.py", line 677, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/werkzeug/test.py", line 884, in run_wsgi_app
app_rv = app(environ, start_response)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1590, in dispatch_request
self.raise_routing_exception(req)
File "/Users/genom003dm/sample_accessioning_dev_virtual_env/lib/python3.5/site-packages/flask/app.py", line 1576, in raise_routing_exception
raise FormDataRoutingRedirect(request)
flask.debughelpers.FormDataRoutingRedirect: b'A request was sent to this URL (http://localhost/login_test) but a redirect was issued automatically by the routing system to "http://localhost/login_test/". The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one. Make sure to directly send your POST-request to this URL since we can\'t make browsers or HTTP clients redirect with form data reliably or without user interaction.\n\nNote: this exception is only raised in debug mode'
If I change the URL to /login_test/ then I get HTTP 400 errors. I'm assuming that this is happening due to the fact that I'm missing form object for login? (but in this case I don't have form object because I'm trying just trying to login with post api).
I want to know is there a way to login using flask-security's /login_test/ url.
Thanks
Ok, I found an answer. The reason why I was only seeing HTTP 400 errors instead of the specifics of HTTP 400 errors are because I put the error handling on Flask app and it just showed me 400 rather than what the actual error was. Once I removed the HTTP 400 error handling, it was saying that the CSRF token was missing. So what I did was to WTF_CSRF_ENABLED = False in app config file.

Using MySQLdb --> conn.select_db() with Flask [duplicate]

I am trying to debug a view in my Flask app that is return a 500 status with the error TypeError: 'bool' object is not callable in the traceback. The view calls login_user from Flask-Login then returns True to indicate that the login was successful.
I have debugged until app_iter = app(environ, start_response) and the app is now a boolean with the value True rather than the Flask app object.
Traceback (most recent call last):
File "D:\Python27\lib\site-packages\flask\app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "D:\Python27\lib\site-packages\flask\app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "D:\Python27\lib\site-packages\flask\app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "D:\Python27\lib\site-packages\flask\app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "D:\Python27\lib\site-packages\flask\app.py", line 1478, in full_dispatch_request
response = self.make_response(rv)
File "D:\Python27\lib\site-packages\flask\app.py", line 1577, in make_response
rv = self.response_class.force_type(rv, request.environ)
File "D:\Python27\lib\site-packages\werkzeug\wrappers.py", line 824, in force_type
response = BaseResponse(*_run_wsgi_app(response, environ))
File "D:\Python27\lib\site-packages\werkzeug\wrappers.py", line 57, in _run_wsgi_app
return _run_wsgi_app(*args)
File "D:\Python27\lib\site-packages\werkzeug\test.py", line 854, in run_wsgi_app
app_iter = app(environ, start_response)
TypeError: 'bool' object is not callable
#app.route('/login', methods=['POST'])
def login():
username = request.form['username']
user = User.query.filter_by(username=username).first()
if user:
login_user(user)
return True
return False
In Flask, a view must return one of the following:
a string
a Response object (or subclass)
a tuple of (string, status, headers) or (string, status)
a valid WSGI application
Flask tests for the first 3 options, and if they don't fit, assumes it is the fourth. You returned True somewhere, and it is being treated as a WSGI application instead.
See About Responses in the documentation.

Permission denied for access to folder on Python3.6 with Flask

EDIT: Ignore this question entirely. It was a filesystem problem.
Whenever I try to open the posts folder, I get an error:
Traceback (most recent call last):
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\vikas\Projects\blg\main.py", line 19, in index
return render_template("index.html", newest_post=find_recent_post())
File "C:\Users\vikas\Projects\blg\main.py", line 12, in find_recent_post
with open(str(find_recent_post_name())) as post:
PermissionError: [Errno 13] Permission denied: 'posts/'
My main.py file:
from flask import Flask
from flask import render_template
app = Flask(__name__)
def find_recent_post_name():
import glob
posts = glob.glob("posts/")
return posts[len(posts) - 1]
def find_recent_post():
with open(str(find_recent_post_name())) as post:
newest_post = post.readlines()
return newest_post
#app.route("/")
def index():
return render_template("index.html", newest_post=find_recent_post())
if __name__ == '__main__':
app.run(debug=True)
My Python version is v3.6.1 and Flask v1.12.0
EDIT: Debugging code and using PowerShell seems to work.
It is not a problem with flask. you can either change the permissions on the folder /posts/ or you can run flask as a user who has read access.
$ chmod 755 <folder names>
to give access to the user who run's flask app, or you could use:
$ sudo python main.py
to run as admin or run flask as a user who already has access. and note that you should add the same settings while on deployment. so workers for uwsgi or gunicron or however you run your app on deployment should run with same credentials.
note that your user should have both read or 4 access to read the file content's, and have execute or 1 access to be able to cd into it.

python flask microframework not able to use session variable

from flask import Flask,redirect
from flask import session
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
#app.route('/signup', methods = ['POST'])
def signup():
email = 'xxxx'
session['email'] = email
print session['email']
print("The email address is '" + email + "'")
return redirect('/')
#app.route('/unregister', methods = ['POST'])
def unregister():
print "session check"
print session['email']
return 'We have removed from the list!'
if __name__ == '__main__':
app.secret_key = '#d\xe9X\x00\xbe~Uq\xebX\xae\x81\x1fs\t\xb4\x99\xa3\x87\xe6.\xd1_'
app.debug = True
app.run()
When I run this I am able to run a server on http://127.0.0.1:5000/. The problem I am facing is that I am able to use session in signup but not able to use it in unregister. I am using it through curl:
curl -X POST http://127.0.0.1:5000/unregister
I see this error:
127.0.0.1 - - [07/Apr/2016 16:06:08] "POST /unregister HTTP/1.1" 500 -
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ,
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1820, in
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1403, in
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/pvelumul/ACI/workspace/acitoolkit/applications/snapback/helloworld.py", line 20, in unregister
print session['email']
File "/usr/local/lib/python2.7/site-packages/Werkzeug-0.11.4-py2.7.egg/werkzeug/local.py", line 373, in <lambda>
__getitem__ = lambda x, i: x._get_current_object()[i]
KeyError: 'email'
You're missing a salient part:
When you assign a session variable, like this: session['email'] = email, Flask saves that info in the browser's cookie. Hence, it can only be read through the browser.
You are trying to read the session using a cURL POST request. But, the command line is different from the browser, which means cURL cannot has no access to the browser.
That way, reading session['email'] will return a KeyError which means, email is not present.
The proper way to read a session variable is when running the app in the browser, not through a command line request.
Also, you should use session.get('email') which returns None if the key is not present, rather than throw an error.
The problem I am facing is that I am able to use session in signup but not able to use it in unregister
When you visit /signup from the command line, you are only assigning to the session object in memory, which is no longer available after the code has finished running.