From a4011028b22799704c3ca586a763a0d36a714619 Mon Sep 17 00:00:00 2001 From: Lars Holm Nielsen Date: Wed, 27 Aug 2014 15:11:01 +0200 Subject: [PATCH 1/2] Notify client of OAuth2Errors * Properly report non-fatal client errors to the client (like e.g. invalid_scope) according to http://tools.ietf.org/html/rfc6749#section-4.1.2.1 --- flask_oauthlib/provider/oauth2.py | 12 ++++++++++-- tests/oauth2/test_oauth2.py | 11 +++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/flask_oauthlib/provider/oauth2.py b/flask_oauthlib/provider/oauth2.py index bb663c3c..ebb3763d 100644 --- a/flask_oauthlib/provider/oauth2.py +++ b/flask_oauthlib/provider/oauth2.py @@ -384,6 +384,9 @@ def decorated(*args, **kwargs): except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e) return redirect(e.in_uri(self.error_uri)) + except oauth2.OAuth2Error as e: + log.debug('OAuth2Error: %r', e) + return redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return redirect(add_params_to_uri( @@ -398,6 +401,9 @@ def decorated(*args, **kwargs): except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e) return redirect(e.in_uri(self.error_uri)) + except oauth2.OAuth2Error as e: + log.debug('OAuth2Error: %r', e) + return redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return redirect(add_params_to_uri( @@ -416,7 +422,7 @@ def decorated(*args, **kwargs): return decorated def confirm_authorization_request(self): - """When consumer confirm the authrozation.""" + """When consumer confirm the authorization.""" server = self.server scope = request.values.get('scope') or '' scopes = scope.split() @@ -437,9 +443,11 @@ def confirm_authorization_request(self): log.debug('Authorization successful.') return create_response(*ret) except oauth2.FatalClientError as e: + log.debug('Fatal client error %r', e) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: - return redirect(e.in_uri(redirect_uri)) + log.debug('OAuth2Error: %r', e) + return redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return redirect(add_params_to_uri( diff --git a/tests/oauth2/test_oauth2.py b/tests/oauth2/test_oauth2.py index 9b9c74b6..ec14cd7b 100644 --- a/tests/oauth2/test_oauth2.py +++ b/tests/oauth2/test_oauth2.py @@ -162,6 +162,17 @@ def test_invalid_response_type(self): rv = self.client.get(clean_url(rv.location)) assert b'error' in rv.data + def test_invalid_scope(self): + authorize_url = ( + '/oauth/authorize?response_type=code&client_id=dev' + '&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fauthorized' + '&scope=invalid' + ) + rv = self.client.get(authorize_url) + rv = self.client.get(clean_url(rv.location)) + assert b'error' in rv.data + assert b'invalid_scope' in rv.data + class TestWebAuthCached(TestWebAuth): From 5721e09e19eec3c58c677e4f081b8f0885013b24 Mon Sep 17 00:00:00 2001 From: Lars Holm Nielsen Date: Wed, 27 Aug 2014 15:22:33 +0200 Subject: [PATCH 2/2] Fix all lint and PEP8 errors --- tests/oauth1/server.py | 2 +- tests/oauth2/server.py | 6 ++++-- tests/oauth2/test_oauth2.py | 16 ++++++++++------ tests/test_utils.py | 1 - 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/oauth1/server.py b/tests/oauth1/server.py index 51c5d084..917ed1e9 100644 --- a/tests/oauth1/server.py +++ b/tests/oauth1/server.py @@ -24,7 +24,7 @@ class User(db.Model): class Client(db.Model): - #id = db.Column(db.Integer, primary_key=True) + # id = db.Column(db.Integer, primary_key=True) # human readable name client_key = db.Column(db.String(40), primary_key=True) client_secret = db.Column(db.String(55), unique=True, index=True, diff --git a/tests/oauth2/server.py b/tests/oauth2/server.py index 2fbc30db..f1e689e6 100644 --- a/tests/oauth2/server.py +++ b/tests/oauth2/server.py @@ -21,7 +21,7 @@ def check_password(self, password): class Client(db.Model): - #id = db.Column(db.Integer, primary_key=True) + # id = db.Column(db.Integer, primary_key=True) # human readable name name = db.Column(db.String(40)) client_id = db.Column(db.String(40), primary_key=True) @@ -121,6 +121,7 @@ def delete(self): db.session.commit() return self + def current_user(): return g.user @@ -276,7 +277,8 @@ def access_token(): @app.route('/oauth/revoke', methods=['POST']) @oauth.revoke_handler - def revoke_token(): pass + def revoke_token(): + pass @app.route('/api/email') @oauth.require_oauth('email') diff --git a/tests/oauth2/test_oauth2.py b/tests/oauth2/test_oauth2.py index ec14cd7b..862cdef7 100644 --- a/tests/oauth2/test_oauth2.py +++ b/tests/oauth2/test_oauth2.py @@ -272,6 +272,7 @@ class TestRefreshTokenSQLAlchemy(TestRefreshToken): def create_oauth_provider(self, app): return sqlalchemy_provider(app) + class TestRevokeToken(OAuthSuite): def create_oauth_provider(self, app): @@ -288,47 +289,50 @@ def get_token(self): def test_revoke_token(self): data = self.get_token() - tok = Token.query.filter_by( + tok = Token.query.filter_by( refresh_token=data['refresh_token']).first() assert tok.refresh_token == data['refresh_token'] revoke_url = '/oauth/revoke' args = {'token': data['refresh_token']} - rv = self.client.post(revoke_url, data=args, headers={ + self.client.post(revoke_url, data=args, headers={ 'Authorization': 'Basic %s' % auth_code, }) tok = Token.query.filter_by( refresh_token=data['refresh_token']).first() - assert tok == None + assert tok is None def test_revoke_token_with_hint(self): data = self.get_token() - tok = Token.query.filter_by( + tok = Token.query.filter_by( access_token=data['access_token']).first() assert tok.access_token == data['access_token'] revoke_url = '/oauth/revoke' args = {'token': data['access_token'], 'token_type_hint': 'access_token'} - rv = self.client.post(revoke_url, data=args, headers={ + self.client.post(revoke_url, data=args, headers={ 'Authorization': 'Basic %s' % auth_code, }) tok = Token.query.filter_by( access_token=data['access_token']).first() - assert tok == None + assert tok is None + class TestRevokeTokenCached(TestRefreshToken): def create_oauth_provider(self, app): return cache_provider(app) + class TestRevokeTokenSQLAlchemy(TestRefreshToken): def create_oauth_provider(self, app): return sqlalchemy_provider(app) + class TestCredentialAuth(OAuthSuite): def create_oauth_provider(self, app): diff --git a/tests/test_utils.py b/tests/test_utils.py index 68299ebd..c3cb8f5a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,7 +5,6 @@ import werkzeug.wrappers from flask_oauthlib.utils import extract_params from oauthlib.common import Request -from flask import request @contextmanager