Categories
General python

User Login: User Authentication in Python

Simple username/password login is pretty much extinct today. Most services today have moved on to rely on more refined and secure forms of user authentication systems. These include encryption, hashing, the use of salt and pepper, and even 2FA with messages or emails. So given that, it is fundamental to know about authentication systems to understand more complex security subjects. So, what does user login authentication in Python mean exactly, and why is it so important to know? Before I get into that, I want to explain the basics of user login, its methods, why authentication is so important, and how it is shaping differently today.

user login and user authetnication 2023

User Security & User Authentication

Security plays an essential role in all business models today. An upsurge in cybercrime has led to vast growth in currently used security measures.

You landed the Cloud Storage of the future internet. Cloud Storage Services Sesame Disk by NiHao Cloud

Use 10GB for free NOW and forever!

Support the growth of a Team File sharing system that works in China, USA, Europe, APAC and everywhere else.

Authentication is the cornerstone of security. As such, it’s important to know its history of use and how it has evolved over time and is moving more towards a truly random key, making it impossible for communication to be hacked.

It is important to look at the basics of authentication to see why the need endured to develop state of the art security systems.

User Authentication & User Login with Python

Python makes things simpler. Python has robust encryption systems that are also easier to code. The ease of that makes it more favorable for someone to perform user authentication or user login in Python. Besides, even someone starting out can quickly claw their way in with Python. Moreover, it is also a great language for cybersecurity experts or analysts.

User authentication involves two modules: register and login. A new user can register with their info, or an existing one can log in using their authenticated details.

User authentication has heavily evolved from a basic password stored in a data structure in Python to advanced cryptographic algorithms, including hashing. It’s vital to learn from past systems. This will help us understand why there was a need for improved security systems and how these systems have evolved to work for user authentication.

Simple User Authenication in Python

Before diving into more intricate stuff, I want to explain the need for an authentication system with a simple program. This code serves user verification.

It focuses on basic user authentication in python. First, you need to import a library: getpass.

import getpass

After importing, you need to create a dictionary in python and pass key-value pairs of usernames and passwords. This acts like your database on a low level… for the sake of this example. This is by no means a practical, or effective, user authentication system.

After creating a dictionary, prompt the user for an input. Then, if the user enters a valid username from the key values above and a valid password, the program prints “User Verified”.

The getpass() method prompts the user for password input without echoing. In other words, the characters are not shown on the screen. get() fetches the value for a key in the dict.

The program works in this way:

  • the user enters a username
  • then, the user enters a password
  • if the password matches the value in the dictionary, print “User Verified”
  • otherwise, re-prompt the user for a correct password

A flaw of this program, among other issues, is that if the user enters a username out of this dict, the program still works as = long as a valid password is entered. In simple terms, it accepts a username that it shouldn’t if matched with the right password. Hence, it is a crucial security flaw.

database = {"umar_1": "sesamedisk", "abel_2": "nihaocloud"}
username = input("Enter Your Username : ").lower()
password = getpass.getpass("Enter Your Password : ").lower()
for key in database.keys():
    if username == key:
        while password != database.get(key):
            password = getpass.getpass("Re-enter Your Password : ")
        break
print("User Verified")

User Login Output:

The last output points out the glaring flaw in this basic system. So, a wrong username will still work on such a system.

How do you go about fixing that?

Well, a simple solution could be adding a condition to print a statement if the username entered does not match the key in the dictionary.

python auth system user login

… What Next? What Do I Need To Know?

Well…

Encryption and Encryption Standards for Modern User Authentication

So, what is encryption? Why should you know about it?

Encryption is a mechanism whereby plain text is converted to cipher text to ensure safe data flow from one person to another. It links to user login because the login information has to be safely sent to the APIs or database servers for user authentication. Anyone can intercept and determine the entered private info if the data is not encrypted. This, of course, refers to your emails, usernames, passwords, and all your personal info. Moreover, decrypt the data at the destination to read the original text. That said, these– are the key elements of user login security.

The following are key elements of user login security that encryption helps enhance.

  • Confidentiality – Do not reveal private messages to unauthorized people.
  • Encryption – It transforms data so that only specific individuals can transform the message.
  • Access control – Users have limited actions and views.
  • Authentication – Tracing the origin of a message, for example, user login info.
  • Data Integrity – An unauthorized person cannot read or alter information in a message. It can only be changed in a specified and authorized way.

An encryption algorithm defines the steps taken by a system to achieve the desired output in a defined time. It aims to fulfill these elements. Also, it tries to uplift security.

Base64: Encoding Scheme for User Login

Base64 is an encoding scheme that converts binary data to text data in ASCII String format. It encodes binary data that must be stored and transferred over media designed to deal with ASCII. This is to ensure that the data remain intact without modification. Today, it is common in various use cases, including email via MIME, and in URLs.

Its working is simple. Let’s see how it works:

When you have some binary data you want to transmit, you don’t do it by just streaming the bits and bytes over the wire in a raw format. Why? So, because many types of media can stream text, some protocols may interpret your binary data as control characters or that you entered a special character combination.

Base64 is the solution to this. Why 64, though? The answer is easy.

You can generally rely on the same 64 characters in most character sets, and your data will end up uncorrupted on the other side.

In this example, first, you need to import base64.

Moreover, b64encode and b64decode provide the functionality. Each of them uses UTF-8, the most common character encoding type. Maskpass hides the password input you fetch from the user for privacy.

import base64
import maskpass

# Accept user password input
pwd = maskpass.askpass()
 
# Encoding the string
encode = base64.b64encode(pwd.encode("utf-8"))
print("str-byte : ", encode)
 
# Decoding the string
decode = base64.b64decode(encode).decode("utf-8")
print("byte-str : ", decode)

It’s important to mention that while it is lossless, it significantly increases the data’s size. Also, it is just an encoding scheme, not encryption, that secures the data.

Types of Encryption for User Login & User Authentication

Experts believe there are three types of primary encryption systems. You can group them into two classical types.

Let’s look at them here:

  • Two-Way Encryption: The data is encrypted and then decrypted using a key. It further includes two types:
    1. Symmetric cipher model: the most popular type; has a single key. This means that both encryption and decryption use the same private key. It makes the process more kinetic while keeping its simplicity. Hence, it is a fast process. It is widespread in its use today and is probably the most common type of encryption.
    2. Asymmetric cipher model:: lesser known and used. It is also known as public-key cryptography. This type of encryption uses different keys for both encryption and decryption. The process is more dynamic, but it is slower. Why? Its lack of speed is using different keys; thus, it’s much more secure than symmetric encryption. Moreover, a popular trending use case is digital signing today.
  • One-Way Encryption:
    • Hashing: generates a value of fixed length using data with a mathematical function called the hash function. It cannot be realistically decrypted since it is a one way encryption. Hence, having is irreversible. Only if you know the input data can you reverse the encryption. Moreover, hashing validates the integrity of data. Here are some key elements to consider for hashing:
      • each input produces a unique output
      • modifying input changes the output hash value as well
      • a fixed length, a unique string of numbers, or “message digest” or hash value
      • irreversible once encryption done

For our discussion, the next section will explore hashing algorithms. Why? It’s safer as it’s only one way encryption; symmetric and asymmetric ciphers are two-way. This means you can decrypt them.

Hashing Algorithms

A hashing algorithm is simply a mechanism that makes data unreadable. So, if I were to send an input text that says: “Hi, I’m Umar”– it would encrypt it so that it becomes a unique type of gibberish. Anyone trying to interpret the message would not be able to know its contents. It offers a way to receive unique outputs for each input.

These are the most popular hashing algorithms:

  • MD5
  • SHA: (secure hashing algorithm)
    • SHA-1
    • SHA-2
    • SHA-3
  • Bcrypt

MD5: Insecure Today

It stands for Message Digest algorithm 5. MD5 produces a 128-bit hash value that is prone to brute attacks. It is used to verify the integrity of files, but it has been cryptographically broken and considered weak. As such, it is one of the most insecure hashing algorithms, but it is still widely used. A salted version of MD5 is harder to break but not quite secure. Hence, people don’t prefer or rely on MD5 today.

A common attack type is sign MD5 collision to forge valid digital certificates.

Here is a code example of using MD5:

import hashlib

md5_enc = hashlib.md5(b'SesameDisk')

print(f"The hash value for the entered byte is: ")
print(md5_enc.digest())

This is the output:

byte code hashing in python using md5

SHA (secure hashing algorithm)

There are three types of SHA.

  • SHA-1: SHA-1 is a legacy cryptographic hashing algorithm that is no longer deemed secure. Using the SHA-1 hashing algorithm in digital certificates could allow attackers to spoof content, perform phishing attacks, or perform man-in-the-middle attacks. It takes an input and produces an output of 160 bits, rendered as 40 hexadecimal digits. While it is more secure than MD5, it is now cryptographically broken and not so secure.
  • SHA-2: most common hash function type. It refers to a family of six hash functions, most commonly including the SHA-256 and SHA-512 functions. It is widely used and still secure. Its use cases include user authentication and user login, but it’s not a great option for user login– bcrypt is better. Still, SHA-2 is almost everywhere.
  • SHA-3: latest hash function in the SHA family. The SHA-3 (Keccak) family of hash routines generates almost-unique 224-bit, 256-bit, 384-bit, or 512-bit (28-/32-/48-/64-byte) signatures for a text. It provides much more cryptographic strength than SHA-2 for the same number of bits (256-bits). It works differently than SHA-1 and SHA-2, which have MD5-like structures.

Bcrypt

Bcrypt is great for user login. It encrypts byte code by adding salt. Salt is a randomly generated number of characters to your password to improve its security. The process involves encoding a password string into machine-level byte code for encryption. Bcrypt only reads byte code, not raw strings. Usually, the ‘utf-8’ encoding is used for byte code. It is purposefully slow, a security measure that helps make it one of the best hashing algorithms.

What you need to start is installing the bcrypt library.

pip install bcrypt

After that, get a password input, encrypt it, and then use the hashpw (password, bcrypt. gensalt()) function for hashing. Password is a keyword; you can replace it with your variable name. Oh, you can also specify the number of salt characters in the gensalt function.

import bcrypt

password = str(input("input password: ")).encode('utf-8')

hashed = bcrypt.hashpw(password, bcrypt.gensalt(10)) 

check_pass = str(input("check password: ")).encode('utf-8')

if bcrypt.checkpw(check, hashed):
    print("Login is successful")
else:
    print("Incorrect password entered")

Salt

Salt? We’re not cooking, are we…? No, no. Salt in user authentication refers to a random string of unique values that append a password. Adding salt to a string of passwords makes it less prone to brute force attacks. Intruders can’t easily find the real password and separate it from the salt. On average, a brute force attack tries at least half of the possible keys before finding the right one. Salt makes that process even longer and harder. So, it makes brute force unsuitable and a waste of time. Also, this encryption is still liable to rainbow table attacks.

def get_hashed_pass(plain_text_password):
  
    return bcrypt.hashpw(plain_text_password.encode('utf-8'), bcrypt.gensalt())

def check_pass(plain_text_password, hashed_password):

    return bcrypt.checkpw(plain_text_password.encode('utf-8', hashed_password)

Pepper in User Login Authentication

Many people tend to use common passwords like “password”, “12345”, “qwerty”, etc. Since the hash of the same input never changes, attackers precompute the hashes of common passwords and then check the leaked database data against those precomputed hashes.

For example, the SHA256 hash of "12345" is "5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5". If this hash is spotted, it can easily be known that the password is “12345”. So what is the solution? Pepper.

Add pepper to the hashed value that consists of the password and the salt, but with a vital difference from salt. Store salt with the password hash in the database while keeping the pepper a secret.

$passwordHash = bcrypt(hash_hmac('sha256', $password, $pepper), $salt);

2FA for User Login Authentication

2FA refers to 2-Factor Authentication. It is widely considered a robust authentication system. Why? Because of its two factor method of verification of identity. It offers a second layer of login security that helps prevent unauthorized access and cyber attacks. However, a downside is a potentially longer time to login and the risk of losing access due to losing your system, such as a phone, OTP token, etc.

Let’s explore how to execute a 2FA system in Python.

from onetimepass import valid_totp
from secrets import choice


def generate_secret():
    secret = ''
    while len(secret) < 16:
        secret += choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
    return secret


secret = generate_secret()
print('Enter the following secret in your authenticator app: ', secret)
print("""
Instructions for saving this secret on Google Authenticator:
1. Open Google Authenticator.
2. Click plus icon at the right bottom.
3. Click Enter a setup key.
4. Enter an Account name of your choice and enter the secret provided above.
5. Click Add.
""")
while True:
    otp = int(input('Please enter the otp generated by your authenticator app: '))
    authenticated = valid_totp(otp, secret)
    if authenticated:
        print('Correct otp, Authenticated!')
    elif not authenticated:
        print('Wrong otp, please try again.')

Conclusion:

In conclusion, user login authentication in Python is a crucial skill to learn as a developer today, in 2022. But before you can fully master user login, you must also know the basics to be able to manipulate the knowledge to your use.

I hope you liked this post and that it was easy to follow. But if you face any issues or problems, let me know below. Even if you don’t, I would love to hear your feedback and experiences. Don’t forget to like the article if you learned anything. Also, share with your friends if you think it might help them.

You might want to read similar tutorial posts if you liked this post. Face Recognition in Python or Biometric authentication and Deploying Smart Contracts in Python.

Have a great day! Take care!

Hits: 7

By Syed Umar Bukhari

Syed Umar Bukhari lives south of the ocean. He is a published author, writer, and poet who has worked as an editor and proofreader on countless promising and burgeoning projects. He loves to explore
mental health—depression, anxiety and OCD—and hopeless romance through his alliterative writings on his blog--- Panacea of Rhapsody. He is inspired by timeless writers and poets like John Keats and Pablo
Neruda with their affinity for love and semantics. He is also currently pursuing a career in computer science, leaning towards AI/ML and data science with a flair for SQL and Python.
He plans to publish his third book in the fall of 2021. His first two books were previously published on
Amazon: Six Times Forever and Avaricious Alphabets.

Leave a Reply

Your email address will not be published.

Start Sharing and Storing Files for Free

You can also get your own Unlimited Cloud Storage on our pay as you go product.
Other cool features include: up to 100GB size for each file.
Speed all over the world. Reliability with 3 copies of every file you upload. Snapshot for point in time recovery.
Collaborate with web office and send files to colleagues everywhere; in China & APAC, USA, Europe...
Tear prices for costs saving and more much more...
Create a Free Account Products Pricing Page
LinkedIn
LinkedIn
Share
WeChat
WhatsApp