diff --git a/README.md b/README.md index 54ba978..06f2f9a 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ # Secure Coding with Python. ## Chapter 5: Broken De-Authentication -### Fix -In order to avoid sessions to be used even after the user has logged out, we should use a random unique value in the -session that we could revoke on logout, invalidating the session. +### Requirement +Continuing with the user account, we should allow the user to change their password. -Since we are adding a new column to our user model we need to update our Database with: -```bash -> $ flask db migrate -> $ flask db upgrade -``` +### Development +We add a simple form that allows a user to enter their current password and a new password. -**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/5.2-broken-deauthentication/code)** +*Note*: For simplicity we aren't going to add a repeat your password field, but on a real world scenario you probably should. + +### Vulnerability +Most of the times a user changes their password is because of suspicion of account compromise. If an attacker has already +gotten their hands on the user credentials, changing the password is expected to prevent further access from +the attacker. By changing the password, but not invalidating the `session_key` and attacker can keep their +access to the compromised account, contrary to the user expectations. + +**Proceed to [next section](https://github.com/nxvl/secure-coding-with-python/tree/5.2-broken-deauthentication/test)** ## Index ### 1. Vulnerable Components diff --git a/marketplace/__init__.py b/marketplace/__init__.py index d4a8872..7c1c428 100644 --- a/marketplace/__init__.py +++ b/marketplace/__init__.py @@ -8,6 +8,7 @@ db = SQLAlchemy() migrate = Migrate() + def create_app(test_config=None): app = Flask(__name__, instance_relative_config=True) app.config.from_mapping( @@ -29,4 +30,4 @@ def create_app(test_config=None): app.register_blueprint(listings.bp) app.register_blueprint(users.bp) - return app \ No newline at end of file + return app diff --git a/marketplace/templates/users/change_password.html b/marketplace/templates/users/change_password.html new file mode 100644 index 0000000..ccebe58 --- /dev/null +++ b/marketplace/templates/users/change_password.html @@ -0,0 +1,23 @@ +{% extends 'base.html' %} + +{% block header %} +

{% block title %}Change your password{% endblock %}

+{% endblock %} + +{% block content %} +Hello {{user.full_name}}, please enter your current password and the new one you want to use: + +{% if msg %} +

{{msg}}

+{% endif %} + +
+ + +
+ + +
+ +
+{% endblock %} diff --git a/marketplace/templates/users/welcome.html b/marketplace/templates/users/welcome.html index 061d57b..6ba7c6b 100644 --- a/marketplace/templates/users/welcome.html +++ b/marketplace/templates/users/welcome.html @@ -5,6 +5,6 @@

{% block title %}Welcome{% endblock %}

{% endblock %} {% block content %} -Logout
-Welcome to the marketplace! +Logout  Change Password
+Welcome {{user.full_name}} to the marketplace! {% endblock %} diff --git a/marketplace/users.py b/marketplace/users.py index b8abe48..c362efd 100644 --- a/marketplace/users.py +++ b/marketplace/users.py @@ -51,4 +51,18 @@ def logout(user): @bp.route('/welcome', methods=('GET',)) @auth def welcome(user): - return render_template('users/welcome.html') + return render_template('users/welcome.html', user=user) + + +@bp.route('/change_password', methods=('GET', 'POST')) +@auth +def change_password(user): + msg = None + if request.method == 'POST': + if bcrypt.checkpw(request.form['current_password'].encode(), user.password.encode()): + user.password = request.form['new_password'] + db.session.commit() + msg = "Password change successful" + else: + msg = "Incorrect current password" + return render_template('users/change_password.html', user=user, msg=msg)