User Authentication System using Python​

Introduction

This project implements a basic user authentication system using Python and a CSV file as a database. It allows users to sign up, sign in, reset their passwords using OTP or security questions, and ensures password strength through specific criteria. The system also supports mobile number verification and provides multiple methods to recover passwords, enhancing both security and usability.

Prerequisites

Before proceeding with this project, you should have:

  • Basic knowledge of Python (functions, loops, conditionals, and file handling).
  • Basic understanding of Pandas for data manipulation.
  • Familiarity with Python packages and CSV file handling.

Learning Objectives

By the end of this project, you will learn:

  • How to create a user authentication system in Python.
  • Use of Pandas for managing user data.
  • Implementing password strength validation.
  • OTP generation and Twilio integration for mobile verification.
  • Handling file operations (reading/writing CSV files).
  • Implementing security measures such as password resets via OTP or security questions.

Installation Guide

  1. Python Installation: Make sure Python is installed on your system. You can download it from here.
  2. Pandas Installation: Run the following command in your terminal:

    pip install pandas

  3. Twilio API Setup:
    • Sign up for a Twilio account here.
    • Get your Account SID and Auth Token.
    • Install the Twilio library using:

      pip install twilio

Project Steps

  1. Creating User Authentication System:
    • Sign-up functionality with a unique username, strong password, mobile number, and security question.
    • Password strength validation ensures security.
  2. Sign-in Functionality:
    • User logs in by entering a valid username and password.
    • The system validates the credentials from a CSV file.
  3. Password Reset Mechanism:
    • Users can reset their password either via an OTP sent to their registered mobile number or by answering a security question.
    • OTP is generated using Python’s random module, and Twilio is used to send the OTP.
  4. Data Storage:
    • User data is stored in a CSV file, ensuring persistent storage of information across sessions.

Code

				
					import pandas as pd
import random
d ={'admin':'Pj@123456'}
num = {'+919399374451':'admin'}
SQ = {'what is your hobby ?':'2d animation'}

data = {'UserName':['admin'],
        'pass':['Pj@123456'],
        'SA':['2D animation'],
       'num':['+919399374451']
       }
df = pd.DataFrame(data)

try:
    k = pd.read_csv(r'userData.csv')
except:
    df.to_csv('userData.csv',index = False)
    k = pd.read_csv(r'userData.csv')

t = pd.read_csv(r'userData.csv',index_col = 'UserName')

def checkPasswordStrength():
    while True:
        password = input("Enter a strong password: ")

        # Check if the password meets minimum length requirements (e.g., at least 8 characters)
        if len(password) < 8:
            print("Password should be at least 8 characters long.")
            continue

        # Check if the password contains at least one uppercase letter
        if not any(char.isupper() for char in password):
            print("Password should contain at least one uppercase letter.")
            continue

        # Check if the password contains at least one lowercase letter
        if not any(char.islower() for char in password):
            print("Password should contain at least one lowercase letter.")
            continue

        # Check if the password contains at least one digit
        if not any(char.isdigit() for char in password):
            print("Password should contain at least one digit.")
            continue

        # Check if the password contains at least one special character
        if not any(not char.isalnum() for char in password):
            print("Password should contain at least one special character (e.g., !@#$%^&*(),.?\":{}|<>).")
            continue

        # If all conditions are met, the password is considered strong
        return password
    
def forgotPass(userIn,t):
    flag2 = 3
    while flag2:
        q = input("what is your hobby ?").lower()
        if(q==t.loc[userIn]['SA']):
            while 1:
                s = checkPasswordStrength()
                k.loc[k['UserName'] == userIn, 'pass'] = s
                k.to_csv('userData.csv',index = False)
                print('yes')
                return s
        else:
            flag2 = flag2 - 1 
            print("incorrect , please try again")
    return 'Failed'

def VerifyOTP(abcd,userIn):       #abcd is the return value of numSignIn
    x = int(input("enter the OTP you get on your phone"))
    if(x == abcd):
        while 1:
            k.loc[k['UserName'] == userIn, 'pass'] = s
            k.to_csv('userData.csv',index = False)
            print('yes')
            return True
    return False
    
def ResetPass(userIn,t):
    x = input('''seems like you forgot your password to reset you password
            press 1 for OTP method
            press 2 for Security Question Method''')
    if(x=='2'):
        forgotPass(userIn,t)
        NsignIN()
    if(x=='1'):
        abcd = numSignIn(userIn,t)
        if VerifyOTP(abcd,userIn):
            signIn()
            return 'Successfull'
        else:
            return 'Failed'
        
def OTPgenerator():
    otp = random.randint(1000,9999)
    return otp

def numSignIn(userIn,t):
    flag = True
    while(flag):
        inputMobNo = input('Enter your registered mobile number: ')
        if((inputMobNo in t['num']) and t.loc[userIn]['num']==inputMobNo):       
            OTP = OTPgenerator()
            print(OTP)
            
            
#             This is Twilio API, we are using twilio to send OTP
            import os
            from twilio.rest import Client
            # Set environment variables for your credentials
            # Read more at http://twil.io/secure
            account_sid = "Different_for_different_user"
            auth_token = "Different_for_different_users"
            client = Client(account_sid, auth_token)
            message = client.messages.create(
              body=OTP,
              from_="Differetn_for_every_user",
              to=inputMobNo           #This is the mobile number of user , given at the time of SignUp
            )
            print(message.sid)
            flag=False
            print("this is from return OTP")
            return OTP;

def NsignUp():
    nums = list(k['num'])
    nums
    l = []
    j = 0
    flag = True
    flag2 = True
    while flag:
        x = input('Enter your user Name')
        if(x in k['UserName'].values):
            print('UserName taken , try another one')
            continue
        else:
            l.append(x)
            y = checkPasswordStrength()
            l.append(y)
            z = input('Enter security question')
            l.append(z)
            if(j>0):
                break
            while flag2:
                num = input('Enter the mobile number')
                if(num in nums):
                    print('number already used , use another number')
                    continue
                else:
                    l.append(num)
                    j = j+1
                    k.loc[k.index[-1]+1] = l
                    flag = False
                    k.to_csv('userData.csv',index = False)
                    return k
                    
def NsignIN():
    flag2 = 3
    while flag2:
        t = pd.read_csv(r'userData.csv',index_col = 'UserName')
        x = input('Enter you user name')
        if(x in list(t.index)):
            flag2 = 3
            while flag2:
                y = input('enter you password')
                if(y in list(t.loc[x])):
                    print("logged in successfully")
                    return 'Successful'
                else:
                    print('Incorrect password plz try again')
                    flag2 = flag2-1
            ResetPass(x,t)
        else:
            flag = flag-1
            print('Username not found , enter a valid user name')
    return False

def main():
    while 1:
        mode = input('''choose mode:
        Press 1 to SignUp
        Press 2 to SignIn
        Press 0 to exit
        : ''')
        if(mode=='1'):
            NsignUp()
            return 'Done'
        elif(mode=='2'):
            NsignIN()
            return True
        elif(mode=='0'):
            print("Thankyou for using our service")
            break
        else:
            print("enter valid input")
main()
				
			

Code

				
					import pandas as pd
import random
d ={'admin':'Pj@123456'}
num = {'+919399374451':'admin'}
SQ = {'what is your hobby ?':'2d animation'}

data = {'UserName':['admin'],
        'pass':['Pj@123456'],
        'SA':['2D animation'],
       'num':['+919399374451']
       }
df = pd.DataFrame(data)

try:
    k = pd.read_csv(r'userData.csv')
except:
    df.to_csv('userData.csv',index = False)
    k = pd.read_csv(r'userData.csv')

t = pd.read_csv(r'userData.csv',index_col = 'UserName')

def checkPasswordStrength():
    while True:
        password = input("Enter a strong password: ")

        # Check if the password meets minimum length requirements (e.g., at least 8 characters)
        if len(password) < 8:
            print("Password should be at least 8 characters long.")
            continue

        # Check if the password contains at least one uppercase letter
        if not any(char.isupper() for char in password):
            print("Password should contain at least one uppercase letter.")
            continue

        # Check if the password contains at least one lowercase letter
        if not any(char.islower() for char in password):
            print("Password should contain at least one lowercase letter.")
            continue

        # Check if the password contains at least one digit
        if not any(char.isdigit() for char in password):
            print("Password should contain at least one digit.")
            continue

        # Check if the password contains at least one special character
        if not any(not char.isalnum() for char in password):
            print("Password should contain at least one special character (e.g., !@#$%^&*(),.?\":{}|<>).")
            continue

        # If all conditions are met, the password is considered strong
        return password
    
def forgotPass(userIn,t):
    flag2 = 3
    while flag2:
        q = input("what is your hobby ?").lower()
        if(q==t.loc[userIn]['SA']):
            while 1:
                s = checkPasswordStrength()
                k.loc[k['UserName'] == userIn, 'pass'] = s
                k.to_csv('userData.csv',index = False)
                print('yes')
                return s
        else:
            flag2 = flag2 - 1 
            print("incorrect , please try again")
    return 'Failed'

def VerifyOTP(abcd,userIn):       #abcd is the return value of numSignIn
    x = int(input("enter the OTP you get on your phone"))
    if(x == abcd):
        while 1:
            k.loc[k['UserName'] == userIn, 'pass'] = s
            k.to_csv('userData.csv',index = False)
            print('yes')
            return True
    return False
    
def ResetPass(userIn,t):
    x = input('''seems like you forgot your password to reset you password
            press 1 for OTP method
            press 2 for Security Question Method''')
    if(x=='2'):
        forgotPass(userIn,t)
        NsignIN()
    if(x=='1'):
        abcd = numSignIn(userIn,t)
        if VerifyOTP(abcd,userIn):
            signIn()
            return 'Successfull'
        else:
            return 'Failed'
        
def OTPgenerator():
    otp = random.randint(1000,9999)
    return otp

def numSignIn(userIn,t):
    flag = True
    while(flag):
        inputMobNo = input('Enter your registered mobile number: ')
        if((inputMobNo in t['num']) and t.loc[userIn]['num']==inputMobNo):       
            OTP = OTPgenerator()
            print(OTP)
            
            
#             This is Twilio API, we are using twilio to send OTP
            import os
            from twilio.rest import Client
            # Set environment variables for your credentials
            # Read more at http://twil.io/secure
            account_sid = "Different_for_different_user"
            auth_token = "Different_for_different_users"
            client = Client(account_sid, auth_token)
            message = client.messages.create(
              body=OTP,
              from_="Differetn_for_every_user",
              to=inputMobNo           #This is the mobile number of user , given at the time of SignUp
            )
            print(message.sid)
            flag=False
            print("this is from return OTP")
            return OTP;

def NsignUp():
    nums = list(k['num'])
    nums
    l = []
    j = 0
    flag = True
    flag2 = True
    while flag:
        x = input('Enter your user Name')
        if(x in k['UserName'].values):
            print('UserName taken , try another one')
            continue
        else:
            l.append(x)
            y = checkPasswordStrength()
            l.append(y)
            z = input('Enter security question')
            l.append(z)
            if(j>0):
                break
            while flag2:
                num = input('Enter the mobile number')
                if(num in nums):
                    print('number already used , use another number')
                    continue
                else:
                    l.append(num)
                    j = j+1
                    k.loc[k.index[-1]+1] = l
                    flag = False
                    k.to_csv('userData.csv',index = False)
                    return k
                    
def NsignIN():
    flag2 = 3
    while flag2:
        t = pd.read_csv(r'userData.csv',index_col = 'UserName')
        x = input('Enter you user name')
        if(x in list(t.index)):
            flag2 = 3
            while flag2:
                y = input('enter you password')
                if(y in list(t.loc[x])):
                    print("logged in successfully")
                    return 'Successful'
                else:
                    print('Incorrect password plz try again')
                    flag2 = flag2-1
            ResetPass(x,t)
        else:
            flag = flag-1
            print('Username not found , enter a valid user name')
    return False

def main():
    while 1:
        mode = input('''choose mode:
        Press 1 to SignUp
        Press 2 to SignIn
        Press 0 to exit
        : ''')
        if(mode=='1'):
            NsignUp()
            return 'Done'
        elif(mode=='2'):
            NsignIN()
            return True
        elif(mode=='0'):
            print("Thankyou for using our service")
            break
        else:
            print("enter valid input")
main()
				
			

Pseudo Code explaining this Python Project

				
					1.	Data Initialization:
o	Check if a CSV file exists for storing user data.
o	If not, create a new CSV file with sample data.
2.	Main Authentication Workflow:
o	The main() function serves as the entry point, giving users options to SignUp, SignIn, or Exit.
3.	SignUp Process:
o	A new user provides a unique username, mobile number, password (validated for strength), and answers a security question.
o	These details are saved in the CSV file.
4.	SignIn Process:
o	A user inputs their username and password, which are verified from the CSV file.
5.	Forgot Password:
o	If a user forgets their password, they can reset it either via OTP sent to their mobile number or by answering their security question.
6.	OTP Generation:
o	A 4-digit OTP is generated using Python’s random module and sent via Twilio API.

				
			

Pseudo Code explaining this Python Project

				
					1.	Data Initialization:
o	Check if a CSV file exists for storing user data.
o	If not, create a new CSV file with sample data.
2.	Main Authentication Workflow:
o	The main() function serves as the entry point, giving users options to SignUp, SignIn, or Exit.
3.	SignUp Process:
o	A new user provides a unique username, mobile number, password (validated for strength), and answers a security question.
o	These details are saved in the CSV file.
4.	SignIn Process:
o	A user inputs their username and password, which are verified from the CSV file.
5.	Forgot Password:
o	If a user forgets their password, they can reset it either via OTP sent to their mobile number or by answering their security question.
6.	OTP Generation:
o	A 4-digit OTP is generated using Python’s random module and sent via Twilio API.

				
			

Code Explanation

  • Password Strength Validation (checkPasswordStrength): Ensures the password is at least 8 characters long, contains uppercase and lowercase letters, digits, and special characters.
  • CSV File Handling: The CSV file stores user data, and all operations (sign-up, sign-in, password reset) read from and write to this file.
  • Forgot Password (forgotPass): Allows users to reset their password either via a security question or OTP.
  • OTP Generation (OTPgenerator): Generates a 4-digit OTP and integrates with the Twilio API to send it to the user’s phone.
  • Twilio Integration (numSignIn): Uses Twilio to send OTPs to users’ registered phone numbers for secure authentication.

Challenges and Solutions

  1. Challenge: Ensuring password strength to maintain security.
    • Solution: A comprehensive validation function that checks for minimum length, character types, and special characters.
  2. Challenge: Handling CSV file operations efficiently.
    • Solution: Pandas is used for reading/writing data to the CSV file, ensuring easy manipulation of the data.
  3. Challenge: Sending OTPs securely to mobile numbers.
    • Solution: Twilio API integration for generating and sending OTPs via SMS.

Testing

  1. Sign-Up Testing:
    • Enter valid and invalid usernames, passwords, and phone numbers to verify the sign-up process.
  2. Sign-In Testing:
    • Test with correct and incorrect passwords for an existing user.
  3. Forgot Password Testing:
    • Verify OTP and security question methods for password recovery.
  4. Edge Case Testing:
    • Test for edge cases such as duplicate usernames, weak passwords, and invalid phone numbers.

Additional Resources

  • Python Documentation:
    Python Official Documentation: Comprehensive guide on Python programming, including modules and libraries.
  • Twilio API Guide.
  • General Python Projects and Tutorials:
    Python Project Ideas: List of Python project ideas for practice and inspiration.
  •  

FAQs

  1. What if my username is taken during sign-up?
    • The system will prompt you to enter a different username.
  2. What happens if I forget my password?
    • You can reset your password using either the OTP method or the security question method.
  3. How is user data stored?
    • User data is stored in a CSV file called userData.csv. This file persists across sessions.

Project by Parn Jain, Team edSlash.