Activity 41: Python Flask Hash

Setting up Activity 41 with the required endpoints for hash handling in Python Flask. This will include a POST and GET method for hashing, as well as login and register routes.

Set Up Your Flask Project

  1. Create a New Project Folder:

      mkdir nicolas_python_flask_hash
      cd nicolas_python_flask_hash
    
  2. Set Up a Virtual Environment and Install Flask:

      python -m venv venv
      venv\Scripts\activate     # For Windows
      pip install Flask
    
  3. Install Additional Libraries: For password hashing, install the werkzeug library, which comes with Flask but may require an update:

      pip install -U Werkzeug
    

Create the Main Application File

Create a file named app.py This file will contain all the necessary code for your Flask application.

  • Import the Required Modules: At the beginning of app.py, import the necessary modules. We need Flask for creating the app, request and jsonify to handle HTTP requests and responses, and generate_password_hash and check_password_hash from werkzeug.security to handle password hashing.

        from flask import Flask, request, jsonify
        from werkzeug.security import generate_password_hash, check_password_hash
    
  • Initialize the Flask App: After the imports, set up your Flask app by creating an instance of Flask. Here, __name__ helps Flask identify the root path for resources in your project.

        app = Flask(__name__)
    
  • Simulate a Database: Since this project is a demo, we'll simulate a database using a dictionary. The users_db dictionary will store usernames as keys and hashed passwords as values.

        users_db = {}
    
  • Define the /sethash Route: Now, we’ll create a route to register a user and hash their password. The POST method will accept a JSON payload containing username and password. Here’s a breakdown of the code:

    • request.json.get('username') and request.json.get('password') retrieve the values of username and password from the request body.

    • generate_password_hash(password) creates a hashed version of the password, which we then store in users_db.

    • Finally, the endpoint returns a JSON response indicating successful registration.

    @app.route('/sethash', methods=['POST'])
    def set_hash():
        username = request.json.get('username')
        password = request.json.get('password')
        hashed_password = generate_password_hash(password)
        users_db[username] = hashed_password
        return jsonify({"message": f"User {username} registered successfully with hashed password!"}), 201
  • Define the /gethash Route: Next, we’ll set up a route to retrieve the hashed password for a given username. This GET method will take a username as a query parameter. Here’s the process:

    • request.args.get('username') retrieves the username from the URL’s query string.

    • We check if username exists in users_db. If it does, return the hashed password; if not, send a response saying "User not found."

    @app.route('/gethash', methods=['GET'])
    def get_hash():
        username = request.args.get('username')
        if username in users_db:
            return jsonify({"username": username, "hashed_password": users_db[username]}), 200
        return jsonify({"message": "User not found!"}), 404
  • Define the /register Route: This route provides instructions on how to register a user. The GET method here simply returns a JSON response to guide users.

        @app.route('/register', methods=['GET'])
        def register():
            return jsonify({"message": "Please use POST /sethash with a username and password to register."})
    
  • Define the /login Route: Lastly, we create a route for user login. This GET method takes username and password as query parameters to verify if the entered password matches the stored hashed password.

    • We first check if username exists in users_db.

    • If it does, check_password_hash compares the provided password with the stored hash.

    • If the check passes, we return a welcome message; otherwise, we send an error message.

    @app.route('/login', methods=['GET'])
    def login():
        username = request.args.get('username')
        password = request.args.get('password')
        if username in users_db and check_password_hash(users_db[username], password):
            return jsonify({"message": f"Welcome, {username}!"}), 200
        return jsonify({"message": "Invalid username or password!"}), 401
  • Run the Application: At the end of the file, add code to start the Flask application. Setting debug=True allows us to see detailed error messages during development.

        if __name__ == '__main__':
            app.run(debug=True)
    

Your app.py should look like this:

from flask import Flask, request, jsonify
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)

users_db = {}

@app.route('/sethash', methods=['POST'])
def set_hash():
    username = request.json.get('username')
    password = request.json.get('password')
    hashed_password = generate_password_hash(password)
    users_db[username] = hashed_password
    return jsonify({"message": f"User {username} registered successfully with hashed password!"}), 201

@app.route('/gethash', methods=['GET'])
def get_hash():
    username = request.args.get('username')
    if username in users_db:
        return jsonify({"username": username, "hashed_password": users_db[username]}), 200
    return jsonify({"message": "User not found!"}), 404

@app.route('/register', methods=['GET'])
def register():
    return jsonify({"message": "Please use POST /sethash with a username and password to register."})

@app.route('/login', methods=['GET'])
def login():
    username = request.args.get('username')
    password = request.args.get('password')
    if username in users_db and check_password_hash(users_db[username], password):
        return jsonify({"message": f"Welcome, {username}!"}), 200
    return jsonify({"message": "Invalid username or password!"}), 401

if __name__ == '__main__':
    app.run(debug=True)

Explanation of Routes:

  • POST /sethash: This endpoint accepts a JSON payload containing username and password. It hashes the password and stores it in a simulated database (a dictionary in this example).

  • GET /gethash: This retrieves the hashed password for a given username.

  • GET /register: Provides instructions on using /sethash to register.

  • GET /login: Allows users to verify their credentials by matching the hashed password.

Test Your Application

  1. Run the Flask Application:

      python app.py
    
  2. Use Postman to test the endpoints:

    • Register a new user: (Ser method to POST)

          http://127.0.0.1:5001/sethash -H "Content-Type: application/json" -d "{\"username\": \"testuser\", \"password\": \"testpassword\"}"
      

    • Retrieve the hash for a user: (Set method to GET)

          http://127.0.0.1:5001/gethash?username=testuser
      

    • Log in as a user: (Set method to GET)

          http://127.0.0.1:5001/login?username=testuser&password=testpassword
      

Initialize Git and Push to GitHub

git init
git add .
git commit -m "Initial commit for Python Flask hash implementation"
git remote add origin https://github.com/yourusername/surname_python_flask_hash.git
git branch -M master
git push -u origin master