Python Validate Hashed Password for Postgres

Introduction

In this tutorial we will learn how to use Python to validate a hashed password with a Postgres database by using SQL and the hashlib function built into Python. This is a feature used when you want to build a login screen. This is what you can expect to learn:

  • What? What is hashing and validation and what is the “hashlib” function?
  • How? We will use the latest version of Python to utilize the “Render_template” and “Request” functions to show the user an HTML form and retrieve data. Then we will hash the password and insert it into a table in our PostgreSQL database.

Prerequisites

  • Some knowledge of the basics of query writing for Postgres, using PG’s free PGadmin tool or other database admin tool and writing applications with languages like PHP, Python, Javascript, Java, C#, ASP.Net, VB.Net, Note.js, Ruby, etc. In this case, we are using Python.
  • Using SQL statements like “SELECT” and “WHERE”.
  • Some experience with HTML scripting. If not, that’s ok, you will learn some here.
  • Helpful: Article on naming conventions showing why we prefix our variables, column names, table names, etc. as you see done in this tutorial. For example, naming “t_variablename” with the “t” prefix to define it as a “text” (string) object and “tbl_” before table names in order to clearly delineate those objects as tables.

Before we learn to use hashlib(), which is the most important function for hashing a password in Python, let’s look at how the request() and render_template() functions behave, because they are quite necessary for password hashing. For example, what we’ll do in this tutorial:

  1. Build an HTML login form for the user to enter an email and password.
  2. Hash the password the user submitted.
  3. Compare that hashed password to the one in the Postgres database.
  4. Redirect the user accordingly.

First, we’ll learn how to build that HTML login form we mentioned above. This involves (a) writing some HTML, which we will write for you; and (b) using Python’s “render_template” function to display the HTML page.

Step 1: Build an HTML form that will be the “template” we call later

Below is some barebones HTML, really the minimum you will need. Later, you may want to make it more modular by referencing a header, css file, and footer, but for now, this will work on all web browsers. Call this page “register.html” and save it in a folder called “templates”:

<html>
    <head>
        <link rel="shortcut icon" href="favicon.ico">
        <title>Template: Python Validate Hashed Password for Postgres</title>
    </head>
<body>
<!-- The message below encapsulated in an "h1" tag is why we call this page a template -->
<!-- It is what makes this page "dynamic" because the server fills -->
<!-- in at the spot where you see {{t_message}} with data you sent when you used -->
<!-- the "render_template()" function. -->
<h1>{{t_message}}</h1>
<!-- div to contain form -->
<div>
    <!-- Set up form and the file to process user input -->
    <form name='frmLogin' action='' method='post' onsubmit='return true;'>

    <!-- input box for the user to enter their user name -->
    <!-- Notice our input has a 'name' (parameter of the HTML input type) of 't_name_user'. -->
    <!-- This is how our request function chooses which data to retrieve. -->
    <div class="form-row">
      User Name: <input type="text"  name="t_name_user">
    </div>

    <div class="form-row">
      Password: <input type="text"  name="t_password">
    </div>

    <!-- button for user to submit the form -->
    <div>
      <input type="submit" name="btn_submit_add_user" value='LOGIN'>
    </div>

    <!-- Close the form -->
    </form>
<!-- Close the container div -->
</div>
<!-- Close the body of the HTML document -->
</body>
</html>

Step 2: The Render_Template Python function

Next step is to increase our understanding of how Python’s Render_Template() function can be used. PostgreSQL’s Render_Template function displays an HTML page for the user, which can be filled with dynamic content we control with parameters in the function. Note: Please don’t confuse it with the redirect function, which sends the user away without waiting for a return.

Syntax: RENDER_TEMPLATE() function

return render_template(t_name_page, t_message)

We offer the RENDER_TEMPLATE function two parameters:

  • t_name_page: This is the name of the HTML page we created to be our template.
  • t_message: The contents of “t_message” will be sent, along with the user, to page_name.html, an html template you create, that is set up to receive and use t_message. Note: instead of “message”, you can call your variable anything you want. You can even send more variables. Look for our article that goes into detail on this function.

Step 3: The Request Python function

The next function we will need to know how to use is the request() function. It is used to pull data that was submitted either by form “post” or by “get” (querystring).

Syntax of the REQUEST() function

variable = request.args.get(field name, default value) # querystring, which is form method = GET in HTML.
variable = request.form.get(field name, default value) # post, which is form method = POST in HTML forms.

Analysis

  • field name: This parameter determines the name of the field (how it was named in your querystring or form). For example, “t_email” or “t_name_user”.
  • default value: In case no data was sent for that field, this is the value your variable will receive. This is an easy way to prevent 404 errors. We often put an empty string here, like ” “.

Here are some examples of how the syntax above might look when used in a project. We’ll leave out “get” as it has no relevance to our current learning:

t_name_user = request.form.get("t_name_user", "")
t_password = request.form.get("t_password", "")

Analysis

  • t_stage: This line of Python code is like saying to the server, “Look at the URL, find the ‘?’, and after that symbol, look for ‘t_stage=’ and put the value that comes after that ‘=’ into a local variable we are naming t_stage.”
  • t_name_user: This line of code grabs the value the user put into the HTML field named “t_name_user” and places that value in the local Python text variable we called “t_name_user”.

Now back to the topic at hand…

What is a hash, what does the HASHLIB function do, and what is the syntax?

A Hash Value – or checksum – is a string (text) value that is the result of a “Hashing Algorithm”. The algorithm we use here is SHA3-512. One use of Hashing is to determine the integrity of values, like passwords.

Syntax of the HASHLIB() function

    t_hashed = hashlib.sha3_512(t_user_input.encode())
    t_password = t_hashed.hexdigest()

Now that you have a basic understanding of how to use the primary Python functions required for building a login screen, we’ll show you how to build these functions into a Python application so we can validate and hash the password the user entered against the hashed password stored in the “tbl_users table in our PostgreSQL database.

Step 4: Build the login application with Python for Postgres

We start by using Python’s render_template() function to send the user to the HTML page we built above and use the request() function to receive the data given by the user.

@app.route("/login", methods=["POST","GET"])
def login():
    return RENDER_TEMPLATE("login.html", t_message = "Login here")
    t_name_user = REQUEST.form.get("t_name_user", "")
    t_password = REQUEST.form.get("t_password", "")

Next we’ll hash of that value stored in “t_password”.

    t_password_hashed = hashlib.sha3_512(t_password.encode())
    t_password = t_password_hashed.hexdigest()

Analysis

  • Starting with the value our user entered into the password field on our HTML form, we are hashing it using Python’s hashlib() function, specifying the “sha3_512” algorithm, and then temporarily saving the resulting value (now hashed) in a variable we called “t_password_hashed”. NOTE: The value now in “t_password_hashed” will be in byte format, so there is one more step to do…
  • Finally, we use the “hexdigest” function to convert the sequence of bytes into more readable hexadecimal format.

Now that we have explained the most complex parts required to build our login screen and validation, it’s time to look at a full listing of our source code:

Step 5: The Full Python Source Code

from flask import Flask
from flask import render_template # to render our html page
from flask import request # to get user input from form
import hashlib # included with Python; no install needed, but need to import
import psycopg2 # for database connection

app = Flask(__name__)
@app.route("/")

# database credentials
t_host = "PostgreSQL database host address" # either "localhost", a domain name, or an IP address.
t_port = "5432" # default postgres port
t_dbname = "database name"
t_user = "database user name"
t_pw = "password"
db_conn = psycopg2.connect(host=t_host, port=t_port, dbname=t_dbname, user=t_user, password=t_pw)
db_cursor = db_conn.cursor()

@app.route("/login", methods=["POST","GET"])
def sign_in():
    return render_template("login.html", t_message = "Login here")
    t_name_user = request.form.get("t_name_user", "")
    t_password = request.form.get("t_password", "")

    # VALIDATION TO CHECK FOR EMPTY FIELDS
    # Check for user name field is empty
    if t_name_user == "":
        t_message = "Login - empty field: Please fill in your user name."
        # Send user back to the dynamic html page (template), with a message
        return render_template("login.html", t_message = t_message)

    if t_password == "":
        t_message = "Login - empty field: Please fill in your password"
        return render_template("login.html", t_message = t_message)

    # Hash the password they entered into a encrypted hex string
    t_hashed = hashlib.sha256(t_password.encode())
    t_password = t_hashed.hexdigest()

    # Taking the time to build our SQL query string so that
    #   (a) we can easily and quickly read it; and
    #   (b) we can easily and quickly edit or add/remote lines.
    #   The more complex the query, the greater the benefits of this approach.
    s = ""
    s += "SELECT"
    s += " ID"
    s += " FROM tbl_users"
    s += " WHERE"
    s += "("
    s += " t_name_user = '" + t_name_user + "'"
    S += " AND"
    s += " t_password = '" + t_password + "'"
    s += ")"
    # NOTE: the format above allows for a user to try to insert
    #   potentially damaging code, commonly known as "SQL injection".
    #   In another article (link below) we will show how to
    #   prevent that by using stored procedures.
    #   Here we left it as you see, so as to keep it as simple as possible.

    # Catch and display any possible errors
    #   while TRYing to commit the SQL script.
    db_cursor.execute(s)
    try:
        array_row = db_cursor.fetchone()
    except psycopg2.Error as e:
        t_message = "Postgres Database error: " + e + "/n SQL: " + s
        return render_template("login.html", t_message = t_message)
    db_cursor.close()

    # Clean up
    db_cursor.close()

IMPORTANT SECURITY MEASURE: Use Stored Procedures

Protect the integrity of your users’ data by understanding…

Conclusion

In this lesson we explored using Python to validate a hashed password for a Postgres login screen. Part of that process was to learn how to use the Render_template() and Request() functions to retrieve data posted by the user to login using an HTML form and the “Post” parameter. The next thing we did is hash their password and check it and the username against data in the PostgreSQL users table. In order to best understand this kind of validation, we created a login / sign-in application using HTML, Python, SQL, and Postgres. Finally, we shared all the Python source code you need.

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.