From 5ca4bd0db0a2942cef742fb6c3946ad6617c70ba Mon Sep 17 00:00:00 2001 From: Jim Ewald Date: Thu, 1 Mar 2018 06:22:11 -0800 Subject: [PATCH 1/6] Refactor code to expect an empty email address. --- app/Email/services.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/Email/services.py b/app/Email/services.py index 8ec3d4b..825f009 100644 --- a/app/Email/services.py +++ b/app/Email/services.py @@ -211,7 +211,8 @@ def _convert_email_uri(email): to create a URI that contains an email address that, when submitted to a server, will not be replaced with a space character. """ - if "+" in email: - return email.replace("+", "%2B") - else: - return email + if email is not None: + if "+" in email: + return email.replace("+", "%2B") + + return email From 22a766845212f6a6a408f36caa75716195cf2bff Mon Sep 17 00:00:00 2001 From: Jim Ewald Date: Thu, 1 Mar 2018 06:25:08 -0800 Subject: [PATCH 2/6] Increment build number for release. --- app/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/__init__.py b/app/__init__.py index 693d67d..3a17c7f 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -24,11 +24,14 @@ app = Flask(__name__) # Application version (major,minor,patch-level) -version = "1.1.4" +version = "1.1.5" """ Change Log +1.1.5 Refactor _convert_email_uri(email) to properly handle a null + email address. + 1.1.4 Add code to convert plus signs located the the username portion of an email address to a '%2B'when the email address is embedded in a URL. From f57768fdea4372cbf4c2e5e7840270011264d10b Mon Sep 17 00:00:00 2001 From: Jim Ewald Date: Wed, 21 Mar 2018 07:38:51 -0700 Subject: [PATCH 3/6] Add logging details for authetication errors. --- Failures.py | 14 +++++++------- app/Authenticate/controllers.py | 8 ++++---- app/__init__.py | 4 +++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Failures.py b/Failures.py index c97b29c..1f2a780 100644 --- a/Failures.py +++ b/Failures.py @@ -12,7 +12,7 @@ def unknown_user_id(id_user): def unknown_user_email(email): - logging.debug('Failures: Unknown user: %s', email) + logging.debug('Failures: Unknown user email: %s', email) return { 'success': False, 'message': 'Unknown user', @@ -41,8 +41,8 @@ def email_already_in_use(email): }, 500 -def email_not_confirmed(): - logging.debug('Failures: Email not confirmed') +def email_not_confirmed(email): + logging.debug('Failures: Email %s not confirmed', email) return { 'success': False, 'message': 'Email not confirmed', @@ -50,8 +50,8 @@ def email_not_confirmed(): }, 401 -def user_blocked(): - logging.debug('Failures: User blocked') +def user_blocked(email): + logging.debug('Failures: User %s blocked', email) return { 'success': False, 'message': 'User is blocked', @@ -113,8 +113,8 @@ def rate_exceeded(time): }, 500 -def wrong_password(): - logging.debug('Failures: Wrong password') +def wrong_password(email): + logging.debug('Failures: Wrong password for %s', email) return { 'success': False, 'message': 'Wrong password', diff --git a/app/Authenticate/controllers.py b/app/Authenticate/controllers.py index efc02a6..5a315ec 100644 --- a/app/Authenticate/controllers.py +++ b/app/Authenticate/controllers.py @@ -41,9 +41,9 @@ def post(self): if user is None: return Failures.unknown_user_email(email) if not user.confirmed: - return Failures.email_not_confirmed() + return Failures.email_not_confirmed(email) if user.blocked: - return Failures.user_blocked() + return Failures.user_blocked(email) if user.auth_source != 'local': return Failures.wrong_auth_source(user.auth_source) @@ -53,11 +53,11 @@ def post(self): if not user_services.check_password(user.id, password): rate_limiting_services.consume_tokens(user.id, 'failed-password', 1) db.session.commit() - return Failures.wrong_password() + return Failures.wrong_password(email) db.session.commit() - logging.info('Authenticate-controller: Authenticate: success: %s', user.id) + logging.info('Authenticate-controller: Authenticate: success: %s', email) return {'success': True, 'user': { 'id': user.id, diff --git a/app/__init__.py b/app/__init__.py index 3a17c7f..5f213b3 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -24,11 +24,13 @@ app = Flask(__name__) # Application version (major,minor,patch-level) -version = "1.1.5" +version = "1.1.6" """ Change Log +1.1.6 Add email address detail for various authentication failures + 1.1.5 Refactor _convert_email_uri(email) to properly handle a null email address. From e84689b22268e04abe17702d3c0681f8000daa51 Mon Sep 17 00:00:00 2001 From: Jim Ewald Date: Wed, 21 Mar 2018 15:07:38 -0700 Subject: [PATCH 4/6] Update application logging to separate application events from those logged by the uwsgi servivce. --- app/__init__.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 5f213b3..24fbf6e 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -24,11 +24,14 @@ app = Flask(__name__) # Application version (major,minor,patch-level) -version = "1.1.6" +version = "1.1.7" """ Change Log +1.1.7 Update application logging to separate application events from + those logged by the uwsgi servivce + 1.1.6 Add email address detail for various authentication failures 1.1.5 Refactor _convert_email_uri(email) to properly handle a null @@ -83,7 +86,15 @@ 'bucket.email-confirm.freq': '1800000' } -logging.basicConfig(level=logging.DEBUG) + +# Set up Cloud Session application log details. The user account that +# this application runs under must have create and write permissions to +# the /var/log/supervisor/ folder. +# ---------------------------------------------------------------------- +logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(levelname)s %(message)s', + filename='/var/log/supervisor/cloud-session-app.log', + filemode='w') logging.info('Log level set to %s', 'DEBUG') logging.info('Starting Cloud Session Service v%s', version) From 081489363ed5899db4f7af5553b245369acbdcca Mon Sep 17 00:00:00 2001 From: Jim Ewald Date: Mon, 24 Sep 2018 13:41:48 -0700 Subject: [PATCH 5/6] Add code to fail a password reset attempt when the account email has not been verified. --- app/LocalUser/controllers.py | 4 ++++ app/__init__.py | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/LocalUser/controllers.py b/app/LocalUser/controllers.py index 4757bbc..d01f1fd 100644 --- a/app/LocalUser/controllers.py +++ b/app/LocalUser/controllers.py @@ -63,6 +63,7 @@ def post(self): if confirm_token is None: # Unknown token return {'success': False, 'code': 510} + if confirm_token.id_user != user.id: # Token is not for this user return {'success': False, 'code': 510} @@ -214,6 +215,9 @@ def get(self, email): if user.auth_source != 'local': return Failures.wrong_auth_source(user.auth_source) + if not user.confirmed: + return Failures.email_not_confirmed(user.email) + success, code, message = user_service.send_password_reset(user.id, server) db.session.commit() diff --git a/app/__init__.py b/app/__init__.py index 24fbf6e..b2e1777 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -24,11 +24,14 @@ app = Flask(__name__) # Application version (major,minor,patch-level) -version = "1.1.7" +version = "1.1.8" """ Change Log +1.1.8 Fail any attempt to reset an account password is the account + email address has not yet been confirmed. + 1.1.7 Update application logging to separate application events from those logged by the uwsgi servivce From 67905fe60e8c0d3bbd411fc22a0d3165e2721f15 Mon Sep 17 00:00:00 2001 From: Jim Ewald Date: Tue, 25 Sep 2018 14:14:55 -0700 Subject: [PATCH 6/6] Add comments and corrected line spacing. --- app/Authenticate/controllers.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/Authenticate/controllers.py b/app/Authenticate/controllers.py index 5a315ec..89586ae 100644 --- a/app/Authenticate/controllers.py +++ b/app/Authenticate/controllers.py @@ -15,7 +15,7 @@ authenticate_app = Blueprint('authenticate', __name__, url_prefix='/authenticate') api = Api(authenticate_app) - +# Authenticate a login attempt using local auth class AuthenticateLocalUser(Resource): def post(self): @@ -23,27 +23,28 @@ def post(self): server = request.headers.get('server') email = request.form.get('email') password = request.form.get('password') - #browser = request.form.get('browser') - #ip_address = request.form.get('ipAddress') # Validate required fields validation = Validation() validation.add_required_field('server', server) validation.add_required_field('email', email) validation.add_required_field('password', password) - #validation.add_required_field('browser', browser) - #validation.add_required_field('ipAddress', ip_address) + if not validation.is_valid(): return validation.get_validation_response() # Validate user exists, is validated and is not blocked user = user_services.get_user_by_email(email) + if user is None: return Failures.unknown_user_email(email) + if not user.confirmed: return Failures.email_not_confirmed(email) + if user.blocked: return Failures.user_blocked(email) + if user.auth_source != 'local': return Failures.wrong_auth_source(user.auth_source)