From 8f5a326920c176049fc12ae9cc013b2e35b3fff9 Mon Sep 17 00:00:00 2001 From: m4tice Date: Sat, 19 Apr 2025 17:11:14 +0700 Subject: [PATCH 01/10] #2 bcrypt installation --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d4d2ea8..e065fdd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ flask -pytest \ No newline at end of file +pytest +bcrypt \ No newline at end of file From abc79aefd6d5c2c2fc9fc1634c707d0751cdb253 Mon Sep 17 00:00:00 2001 From: m4tice Date: Sat, 19 Apr 2025 18:55:08 +0700 Subject: [PATCH 02/10] #2.c: Session Security --- app/__init__.py | 10 ++++++++-- app/settings.py | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 8a622c3..4e492d7 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,18 +1,24 @@ """ author: @GUU8HC """ -#pylint: disable=import-outside-toplevel +#pylint: disable=import-outside-toplevel, line-too-long from flask import Flask -from app.settings import DEBUG_MODE, USER_DB, SECRET_KEY, SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE, SESSION_PERMANENT +from app.settings import DEBUG_MODE, USER_DB, SECRET_KEY, SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE, SESSION_PERMANENT, SESSION_COOKIE_SAMESITE def create_app(): """ function to create application + Issues: + #2.c: Session Security """ app = Flask(__name__) app.config['SECRET_KEY'] = SECRET_KEY + app.config['SESSION_COOKIE_SECURE'] = SESSION_COOKIE_SECURE + app.config['SESSION_COOKIE_HTTPONLY'] = SESSION_COOKIE_HTTPONLY + app.config['SESSION_COOKIE_SAMESITE'] = SESSION_COOKIE_SAMESITE + app.config['SESSION_PERMANENT'] = SESSION_PERMANENT from app.home import home_bp app.register_blueprint(home_bp, url_prefix='/home') diff --git a/app/settings.py b/app/settings.py index 07ecfca..26a89e5 100644 --- a/app/settings.py +++ b/app/settings.py @@ -11,3 +11,4 @@ SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SECURE = True # Use this in production with HTTPS SESSION_PERMANENT = False +SESSION_COOKIE_SAMESITE = 'Strict' # CSRF protection From ef43a8369aa047a8d781790a999484c7f320d9ce Mon Sep 17 00:00:00 2001 From: m4tice Date: Fri, 2 May 2025 16:27:32 +0700 Subject: [PATCH 03/10] update: db --- app/database/dbs/user.db | Bin 12288 -> 12288 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/database/dbs/user.db b/app/database/dbs/user.db index 5fbe3bd93e2f2be0314e8af7f7f4025265078ea4..073a2e314862cd7720ce4b026e502cbf32fa5c1d 100644 GIT binary patch delta 413 zcmX9)txkhM5d0b_1(J_zNty~EAn@$%{c9v4cvScH?t&>l2?!MQ4IuCcSOh_%&?sI2 zkH?X4Et%}7-I>|B9p8@cHah+L&HYaQW&9-8n|{-XXK^fgYrE~|3@;aN?afiII~q;f zbTye=&nX&04i*hqiOSkc=&%%Gn}XAtsOYE-5vO2@92bs3$(&U*#-j;`OWomc+Mb`} zv)On^B%NgT${C4}6h=g^sp@LhH`UEMu$~}mC8Y`krm(S;*kkalo2GdjOxsDu>du@b zuro@<Bq?bj z7X?n+oRji0bI@#^&Ve~b03D=_Qd`3|C!fkgZ~OPZ(RcA9zQvdLnBjG>^DMSj7Dk Date: Fri, 2 May 2025 16:32:46 +0700 Subject: [PATCH 04/10] update:db --- app/database/dbs/user.db | Bin 12288 -> 12288 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/database/dbs/user.db b/app/database/dbs/user.db index 5fbe3bd93e2f2be0314e8af7f7f4025265078ea4..073a2e314862cd7720ce4b026e502cbf32fa5c1d 100644 GIT binary patch delta 413 zcmX9)txkhM5d0b_1(J_zNty~EAn@$%{c9v4cvScH?t&>l2?!MQ4IuCcSOh_%&?sI2 zkH?X4Et%}7-I>|B9p8@cHah+L&HYaQW&9-8n|{-XXK^fgYrE~|3@;aN?afiII~q;f zbTye=&nX&04i*hqiOSkc=&%%Gn}XAtsOYE-5vO2@92bs3$(&U*#-j;`OWomc+Mb`} zv)On^B%NgT${C4}6h=g^sp@LhH`UEMu$~}mC8Y`krm(S;*kkalo2GdjOxsDu>du@b zuro@<Bq?bj z7X?n+oRji0bI@#^&Ve~b03D=_Qd`3|C!fkgZ~OPZ(RcA9zQvdLnBjG>^DMSj7Dk Date: Fri, 2 May 2025 17:31:42 +0700 Subject: [PATCH 05/10] update: hashing and verification method --- app/authenticator/authenticator.py | 40 ++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/app/authenticator/authenticator.py b/app/authenticator/authenticator.py index 3b08ff5..9f268cf 100644 --- a/app/authenticator/authenticator.py +++ b/app/authenticator/authenticator.py @@ -5,6 +5,7 @@ #pylint: disable=line-too-long import hashlib +from bcrypt import checkpw, gensalt, hashpw from app.database.user import User @@ -20,6 +21,30 @@ def __init__(self, db: User): """ self.db = db + def hash_password(self, password): + """ + Return the SHA-256 hash of a password. + + Args: + password (String): The provided password. + + Returns: + String: The SHA-256 hash of the password. + """ + # return hashlib.sha256(password.encode()).hexdigest() + return hashpw(password.encode(), gensalt()).decode('utf-8') + + def verify_password(self, password, hashed_password): + """ + Verifies if the provided password matches the hashed password. + Args: + password (str): The plain text password to verify. + hashed_password (str): The hashed password to compare against. + Returns: + bool: True if the password matches the hashed password, False otherwise. + """ + return checkpw(password.encode(), hashed_password.encode()) + def authenticate(self, username, password): """ Authenticate user. @@ -34,19 +59,8 @@ def authenticate(self, username, password): user = self.db.get_user_by_username(username) # Perform password validation if user exists - return user[-1] == self.hash_password(password) if user else False - - def hash_password(self, password): - """ - Return the SHA-256 hash of a password. - - Args: - password (String): The provided password. - - Returns: - String: The SHA-256 hash of the password. - """ - return hashlib.sha256(password.encode()).hexdigest() + # return user[-1] == self.hash_password(password) if user else False + return self.verify_password(password, user[-1]) if user else False def register(self, username, password): """ From 9d9aea6bed762534b3bc0c759db9266f63827214 Mon Sep 17 00:00:00 2001 From: m4tice Date: Fri, 2 May 2025 17:43:14 +0700 Subject: [PATCH 06/10] update: commenting out unused import --- app/authenticator/authenticator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/authenticator/authenticator.py b/app/authenticator/authenticator.py index 9f268cf..781c831 100644 --- a/app/authenticator/authenticator.py +++ b/app/authenticator/authenticator.py @@ -4,7 +4,7 @@ #pylint: disable=wrong-import-position #pylint: disable=line-too-long -import hashlib +# import hashlib from bcrypt import checkpw, gensalt, hashpw from app.database.user import User From 1fd66e154551b6e8b1fea54e2a9ae9cee64a006a Mon Sep 17 00:00:00 2001 From: m4tice Date: Fri, 2 May 2025 17:48:43 +0700 Subject: [PATCH 07/10] update: gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 59bf362..594a3b6 100644 --- a/.gitignore +++ b/.gitignore @@ -174,6 +174,6 @@ poetry.toml pyrightconfig.json # Database file -.db +*.db # End of https://www.toptal.com/developers/gitignore/api/python From 6d47d5919d47486e9f15d647d6a40305da728b0c Mon Sep 17 00:00:00 2001 From: m4tice Date: Fri, 2 May 2025 17:49:04 +0700 Subject: [PATCH 08/10] update: new user registered --- app/database/dbs/user.db | Bin 12288 -> 12288 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/database/dbs/user.db b/app/database/dbs/user.db index 073a2e314862cd7720ce4b026e502cbf32fa5c1d..e02e8ac866486414b421f4f61c2e29d972a7eb92 100644 GIT binary patch delta 124 zcmZojXh@hK%_ulg#+gxYW5N=CHb(x94E!56a|tZxkMw0^m6U8`O)o9A$Vi5eDn>~v zhDIs@{w^tAp{C~E*)A3#&Z((-=0$lSslFZsMXpBvE_nt?VIHmqIYI6&<=LU;PR=?0 YK?aejTnr2hjQrmi_`hxDQuxLX0LBv}VgLXD delta 124 zcmZojXh@hK%_uNY#+gxIW5N=CHU)m%=xG0CwCVMgRZ+ From eca15f36fa9d0045a80841e188275cced2d51892 Mon Sep 17 00:00:00 2001 From: m4tice Date: Sat, 24 May 2025 21:52:50 +0700 Subject: [PATCH 09/10] add: debug --- app/authentication/authentication.py | 8 +++++++- app/authentication/static/signin.js | 13 ++++++++----- app/authenticator/authenticator.py | 3 +++ app/home/static/home-private.js | 4 +++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/app/authentication/authentication.py b/app/authentication/authentication.py index a3c9059..ad57c57 100644 --- a/app/authentication/authentication.py +++ b/app/authentication/authentication.py @@ -7,6 +7,7 @@ from app.authenticator import authenticator from app.util import login_user, logout_user from app.util import get_git_branch +from app.settings import DEBUG_MODE from . import authentication_bp @@ -30,7 +31,12 @@ def authenticate(username, password): route: /auth/signin// """ login_user(username) - return jsonify({'result': authenticator.authenticate(username, password)}) + result = authenticator.authenticate(username, password) + + if DEBUG_MODE: + print(f"[DEBUG] authentication.py: Authentication result: {result}") + + return jsonify({'result': result}) @authentication_bp.route('/registration') def registration(): diff --git a/app/authentication/static/signin.js b/app/authentication/static/signin.js index 28acc16..3529bb7 100644 --- a/app/authentication/static/signin.js +++ b/app/authentication/static/signin.js @@ -1,11 +1,14 @@ -document.getElementById('button-signin').addEventListener('click', function(event) { - event.preventDefault(); // Prevent form submission - const username = document.querySelector('input[type="text"]').value; - const password = document.querySelector('input[type="password"]').value; - authenticate(username, password) +document.addEventListener("DOMContentLoaded", function() { + document.getElementById('button-signin').addEventListener('click', function(event) { + event.preventDefault(); // Prevent form submission + const username = document.querySelector('input[type="text"]').value; + const password = document.querySelector('input[type="password"]').value; + authenticate(username, password) + }); }); function authenticate(username, password) { + console.log("[DEBUG] signin.js: authenticate() called"); fetch(`/auth/signin/${username}/${password}`, { method: 'GET', headers: { diff --git a/app/authenticator/authenticator.py b/app/authenticator/authenticator.py index 781c831..2d8b099 100644 --- a/app/authenticator/authenticator.py +++ b/app/authenticator/authenticator.py @@ -8,6 +8,7 @@ from bcrypt import checkpw, gensalt, hashpw from app.database.user import User +from app.settings import DEBUG_MODE class Authenticator: """ @@ -43,6 +44,8 @@ def verify_password(self, password, hashed_password): Returns: bool: True if the password matches the hashed password, False otherwise. """ + if DEBUG_MODE: + print(f"[DEBUG] authenticator.py: Verifying password: {checkpw(password.encode(), hashed_password.encode())}") return checkpw(password.encode(), hashed_password.encode()) def authenticate(self, username, password): diff --git a/app/home/static/home-private.js b/app/home/static/home-private.js index a676dc4..f2f2f52 100644 --- a/app/home/static/home-private.js +++ b/app/home/static/home-private.js @@ -1,6 +1,8 @@ -document.getElementById('button-signout').addEventListener('click', function(event) { +document.addEventListener("DOMContentLoaded", function() { + document.getElementById('button-signout').addEventListener('click', function(event) { event.preventDefault(); redirect_signout(); + }); }); function redirect_signout(){ From 496c5a4e21a6918b1564713e7c78b03d29bfa7bd Mon Sep 17 00:00:00 2001 From: m4tice Date: Sun, 25 May 2025 20:15:33 +0700 Subject: [PATCH 10/10] update: comments --- app/authenticator/authenticator.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/app/authenticator/authenticator.py b/app/authenticator/authenticator.py index 2d8b099..0362a80 100644 --- a/app/authenticator/authenticator.py +++ b/app/authenticator/authenticator.py @@ -4,7 +4,6 @@ #pylint: disable=wrong-import-position #pylint: disable=line-too-long -# import hashlib from bcrypt import checkpw, gensalt, hashpw from app.database.user import User @@ -24,15 +23,12 @@ def __init__(self, db: User): def hash_password(self, password): """ - Return the SHA-256 hash of a password. - + Hashes a given password using bcrypt. Args: - password (String): The provided password. - + password (str): The plaintext password to be hashed. Returns: - String: The SHA-256 hash of the password. + str: The hashed password as a UTF-8 encoded string. """ - # return hashlib.sha256(password.encode()).hexdigest() return hashpw(password.encode(), gensalt()).decode('utf-8') def verify_password(self, password, hashed_password): @@ -62,7 +58,6 @@ def authenticate(self, username, password): user = self.db.get_user_by_username(username) # Perform password validation if user exists - # return user[-1] == self.hash_password(password) if user else False return self.verify_password(password, user[-1]) if user else False def register(self, username, password):