├── 1-hardcoded └── login.py ├── 2-hardcoded-multiple ├── hint.md └── login.py ├── 3-hardcoded-hashes └── login.py ├── 4-config-file ├── credentials.yaml └── login.py └── 5-database ├── add_user.py ├── login.py ├── ppab6.db └── setup_db.py /1-hardcoded/login.py: -------------------------------------------------------------------------------- 1 | VALID_USERNAME = "robert" 2 | VALID_PASSWORD = "test123" 3 | 4 | def is_valid_credentials(username, password): 5 | return username == VALID_USERNAME and password == VALID_PASSWORD 6 | 7 | if __name__ == "__main__": 8 | username = input("What is your username?\n") 9 | password = input("What is your password?\n") 10 | 11 | if is_valid_credentials(username, password): 12 | print("ACCESS GRANTED") 13 | print("REVEALING DEEP DARK SECRET...") 14 | print("I didn't like Stranger Things all that much") 15 | 16 | else: 17 | print("ACCESS DENIED") 18 | -------------------------------------------------------------------------------- /2-hardcoded-multiple/hint.md: -------------------------------------------------------------------------------- 1 | To represent user credentials, try one of: 2 | 3 | * A dictionary where the keys are usernames and the values are passwords 4 | 5 | ``` 6 | { 7 | 'robert': 'password123', 8 | 'anoosh': 'snuffles456', 9 | 'juan': 'happyland' 10 | } 11 | ``` 12 | 13 | * A list where each element is a dictionary with 2 keys: username and password 14 | 15 | ``` 16 | [ 17 | { 18 | 'username': 'robert', 19 | 'password': 'password123` 20 | }, 21 | { 22 | 'username': 'anoosh', 23 | 'password': 'snuffles456` 24 | }, 25 | { 26 | 'username': 'juan', 27 | 'password': 'happyland` 28 | } 29 | ] 30 | ``` 31 | 32 | In each case, think about how, given a username, you can verify an associated password. 33 | -------------------------------------------------------------------------------- /2-hardcoded-multiple/login.py: -------------------------------------------------------------------------------- 1 | VALID_CREDENTIALS = [ 2 | { 3 | 'username': 'robert', 4 | 'password': 'test123' 5 | }, 6 | { 7 | 'username': 'anoosh', 8 | 'password': 'snuffles456' 9 | }, 10 | { 11 | 'username': 'juan', 12 | 'password': 'happyland' 13 | } 14 | ] 15 | 16 | def is_valid_credentials(username, password): 17 | user_stored_creds = None 18 | for cred in VALID_CREDENTIALS: 19 | if cred['username'] == username: 20 | user_stored_creds = cred 21 | break 22 | 23 | if user_stored_creds is None: 24 | return False 25 | 26 | return user_stored_creds['password'] == password 27 | 28 | 29 | if __name__ == "__main__": 30 | username = input("What is your username?\n") 31 | password = input("What is your password?\n") 32 | 33 | if is_valid_credentials(username, password): 34 | print("ACCESS GRANTED") 35 | print("REVEALING DEEP DARK SECRET...") 36 | print("I didn't like Stranger Things all that much") 37 | 38 | else: 39 | print("ACCESS DENIED") 40 | -------------------------------------------------------------------------------- /3-hardcoded-hashes/login.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | VALID_CREDENTIALS = [ 4 | { 5 | 'username': 'robert', 6 | 'password_hash': 'ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae' 7 | }, 8 | { 9 | 'username': 'anoosh', 10 | 'password_hash': '3c32608fd9ffd87ae17dbb3a65a509cc8ba5aa395147c99ed20bdba9c434d8c2' 11 | }, 12 | { 13 | 'username': 'juan', 14 | 'password_hash': '5dc7286295def318e3e643b21ec8963fe1a0d4c43c0e62a7477ad43c4a04406e' 15 | } 16 | ] 17 | 18 | def is_valid_credentials(username, password): 19 | user_stored_creds = None 20 | for cred in VALID_CREDENTIALS: 21 | if cred['username'] == username: 22 | user_stored_creds = cred 23 | break 24 | 25 | if user_stored_creds is None: 26 | return False 27 | 28 | password_hash = hashlib.sha256(password.encode('utf-8')).hexdigest() 29 | 30 | return user_stored_creds['password_hash'] == password_hash 31 | 32 | 33 | if __name__ == "__main__": 34 | username = input("What is your username?\n") 35 | password = input("What is your password?\n") 36 | 37 | if is_valid_credentials(username, password): 38 | print("ACCESS GRANTED") 39 | print("REVEALING DEEP DARK SECRET...") 40 | print("I didn't like Stranger Things all that much") 41 | 42 | else: 43 | print("ACCESS DENIED") 44 | -------------------------------------------------------------------------------- /4-config-file/credentials.yaml: -------------------------------------------------------------------------------- 1 | - username: robert 2 | password_hash: ecd71870d1963316a97e3ac3408c9835ad8cf0f3c1bc703527c30265534f75ae 3 | - username: anoosh 4 | password_hash: 3c32608fd9ffd87ae17dbb3a65a509cc8ba5aa395147c99ed20bdba9c434d8c2 5 | - username: juan 6 | password_hash: 5dc7286295def318e3e643b21ec8963fe1a0d4c43c0e62a7477ad43c4a04406e 7 | -------------------------------------------------------------------------------- /4-config-file/login.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import yaml 3 | 4 | with open('./credentials.yaml', 'r') as f: 5 | VALID_CREDENTIALS = yaml.safe_load(f) 6 | 7 | def is_valid_credentials(username, password): 8 | user_stored_creds = None 9 | for cred in VALID_CREDENTIALS: 10 | if cred['username'] == username: 11 | user_stored_creds = cred 12 | break 13 | 14 | if user_stored_creds is None: 15 | return False 16 | 17 | password_hash = hashlib.sha256(password.encode('utf-8')).hexdigest() 18 | 19 | return user_stored_creds['password_hash'] == password_hash 20 | 21 | 22 | if __name__ == "__main__": 23 | username = input("What is your username?\n") 24 | password = input("What is your password?\n") 25 | 26 | if is_valid_credentials(username, password): 27 | print("ACCESS GRANTED") 28 | print("REVEALING DEEP DARK SECRET...") 29 | print("I didn't like Stranger Things all that much") 30 | 31 | else: 32 | print("ACCESS DENIED") 33 | -------------------------------------------------------------------------------- /5-database/add_user.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import sqlite3 3 | 4 | DB_NAME = "ppab6.db" 5 | 6 | def is_username_available(username): 7 | conn = sqlite3.connect(DB_NAME) 8 | c = conn.cursor() 9 | 10 | res = c.execute(""" 11 | SELECT * 12 | FROM users 13 | WHERE 14 | username = ? 15 | """, (username,)).fetchone() 16 | 17 | return res is None 18 | 19 | 20 | def add_user(username, password): 21 | conn = sqlite3.connect(DB_NAME) 22 | c = conn.cursor() 23 | 24 | password_hash = hashlib.sha256(password.encode('utf-8')).hexdigest() 25 | 26 | c.execute(""" 27 | INSERT INTO 28 | users (username, password_hash) 29 | VALUES 30 | (?, ?) 31 | """, (username, password_hash)) 32 | conn.commit() 33 | 34 | 35 | if __name__ == "__main__": 36 | print("Let's create your user account!") 37 | 38 | while True: 39 | username = input("What is your username?\n") 40 | if is_username_available(username): 41 | print("Username is available!") 42 | break 43 | else: 44 | print("Username is taken. Choose another one.") 45 | 46 | password = input("What is your password?\n") 47 | 48 | add_user(username, password) 49 | print("Added %s to the database!" % username) 50 | -------------------------------------------------------------------------------- /5-database/login.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import sqlite3 3 | 4 | DB_NAME = "ppab6.db" 5 | 6 | def is_valid_credentials(username, password): 7 | conn = sqlite3.connect(DB_NAME) 8 | c = conn.cursor() 9 | 10 | password_hash = hashlib.sha256(password.encode('utf-8')).hexdigest() 11 | 12 | res = c.execute(""" 13 | SELECT * 14 | FROM users 15 | WHERE 16 | username = ? AND 17 | password_hash = ? 18 | """, (username, password_hash)).fetchone() 19 | 20 | return res is not None 21 | 22 | 23 | if __name__ == "__main__": 24 | username = input("What is your username?\n") 25 | password = input("What is your password?\n") 26 | 27 | if is_valid_credentials(username, password): 28 | print("ACCESS GRANTED") 29 | print("REVEALING DEEP DARK SECRET...") 30 | print("I didn't like Stranger Things all that much") 31 | 32 | else: 33 | print("ACCESS DENIED") 34 | -------------------------------------------------------------------------------- /5-database/ppab6.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robert/user-authentication/b3f5f3b23f736e29baa5f955904026507b06af95/5-database/ppab6.db -------------------------------------------------------------------------------- /5-database/setup_db.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sqlite3 3 | 4 | DB_NAME = "ppab6.db" 5 | 6 | if __name__ == "__main__": 7 | if os.path.isfile(DB_NAME): 8 | while True: 9 | ans = input("Database file %s already exists. Shall I overwrite it? [y/n]" % DB_NAME) 10 | 11 | if ans == "y": 12 | print("OK. Deleting database and recreating it.") 13 | os.remove(DB_NAME) 14 | break 15 | elif ans == "n": 16 | print("OK. Exiting.") 17 | exit(0) 18 | else: 19 | print("I didn't understand you") 20 | 21 | conn = sqlite3.connect(DB_NAME) 22 | c = conn.cursor() 23 | 24 | c.execute(""" 25 | CREATE TABLE users ( 26 | username VARCHAR, 27 | password_hash VARCHAR 28 | ) 29 | """) 30 | conn.commit() 31 | 32 | print("Database created!") 33 | --------------------------------------------------------------------------------