Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple authentication with encryption using Flask and Python
"""
This file defines a User model and a Flask application, and implements authentication using encryption.
For more information, visit http://tecladocode.com/blog/learn-python-password-encryption-with-flask
"""
from flask import Flask, request, jsonify
from werkzeug.security import generate_password_hash, check_password_hash
import sqlite3
app = Flask(__name__)
class UserNotFoundError(Exception):
def __init__(self, message):
self.message = message
class User:
def __init__(self, username, password):
self.username = username
self.password = password
def save_to_db(self):
connection = sqlite3.connect('data.db')
cursor = connection.cursor()
try:
cursor.execute('INSERT INTO users (username, password) VALUES (?, ?)', (self.username, self.password))
except:
cursor.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, password TEXT)')
raise UserNotFoundError('The table `users` did not exist, but it was created. Run the registration again.')
finally:
connection.commit()
connection.close()
@classmethod
def find_by_username(cls, username):
connection = sqlite3.connect('data.db')
cursor = connection.cursor()
try:
data = cursor.execute('SELECT * FROM users WHERE username=?', (username,)).fetchone()
if data:
return cls(data[1], data[2])
finally:
connection.close()
@app.route('/register', methods=['POST'])
def register_user():
username = request.form['username']
password = request.form['password']
try:
User(username, generate_password_hash(password)).save_to_db()
except Exception as e:
return jsonify({'error': e.message}), 500
return jsonify({'message': 'User registered successfully'}), 201
@app.route('/login', methods=['POST'])
def login_user():
username = request.form['username']
password = request.form['password']
user = User.find_by_username(username)
if user and check_password_hash(user.password, password):
return jsonify({'message': 'Password is correct'}) # You'll want to return a token that verifies the user in the future
return jsonify({'error': 'User or password are incorrect'}), 401
if __name__ == '__main__':
app.run(debug=True)
@kirbyevanj

This comment has been minimized.

Show comment
Hide comment
@kirbyevanj

kirbyevanj Feb 27, 2018

Line 43 has an SQL injection vulnerability. Might want to use an ORM type interface to the database in the future

kirbyevanj commented Feb 27, 2018

Line 43 has an SQL injection vulnerability. Might want to use an ORM type interface to the database in the future

@makmoud98

This comment has been minimized.

Show comment
Hide comment
@makmoud98

makmoud98 Feb 27, 2018

wouldn't this be hashing instead of encrypting?

makmoud98 commented Feb 27, 2018

wouldn't this be hashing instead of encrypting?

@victordomingos

This comment has been minimized.

Show comment
Hide comment
@victordomingos

victordomingos Mar 12, 2018

@kirbyevanj, are you sure that line has a SQL injection vulnerability? According to the Python sqlite docs:

# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())

In the code above, at line 43, @jslvtr is passing a one-item tuple containing the username. Isn't it the same as suggested by the documentation? He simply skips the creation of a variable for that tuple. I believe the important bit here is to use the ? notation instead of just building a string with the variables appended.

victordomingos commented Mar 12, 2018

@kirbyevanj, are you sure that line has a SQL injection vulnerability? According to the Python sqlite docs:

# Never do this -- insecure!
symbol = 'RHAT'
c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# Do this instead
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())

In the code above, at line 43, @jslvtr is passing a one-item tuple containing the username. Isn't it the same as suggested by the documentation? He simply skips the creation of a variable for that tuple. I believe the important bit here is to use the ? notation instead of just building a string with the variables appended.

@victordomingos

This comment has been minimized.

Show comment
Hide comment
@victordomingos

victordomingos Mar 12, 2018

@makmoud98, yes. it is very common to use these term interchangeably, but actually this seems not to be encryption but hashing, as the password stored this way cannot be decrypted.

victordomingos commented Mar 12, 2018

@makmoud98, yes. it is very common to use these term interchangeably, but actually this seems not to be encryption but hashing, as the password stored this way cannot be decrypted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment