Login Authentication with Flask

In today’s blog, we will learn how to build a login for different users defined in the database and a Web app with Python using Flask.

$ pip install Flask

Indeed, make a file Hello.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
return "Hello World!"

if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)

Finally, run the app using this command:

$ python Hello.py

Open this URL http://localhost:8080/ in your web browser, and “Hello World!” should appear.

Building a Flask Login Screen

Create this Python file and save it as app.py:

from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os

app = Flask(__name__)

@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello User!"

@app.route('/login', methods=['POST'])
def do_admin_login():
if request.form['password'] == 'password' and request.form['username'] == 'admin':
session['logged_in'] = True
else:
flash('wrong credentials!')
return home()

if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=8080)

Hence, we have created two routes here:

@app.route('/')
@app.route('/login', methods=['POST'])

We make the directory /templates/. Make a file /templates/login.html with this code:

{% block body %};
{% if session['logged_in'] %};

You're logged in already!

{% else %};

<form action="/login" method="POST">
<input type="username" name="username" placeholder="Username">
<input type="password" name="password" placeholder="Password">
<input type="submit" value="Log in">
</form>
{% endif %};
{% endblock %}
{% endraw %};

Run the command:

$ python Hello.py

Open http://localhost:8080/ in your web browser, and show the login screen.

Make It Look Amazing

We make the directory/static with the file style.css for a better look.

* {
box-sizing: border-box;
}

*:focus {
outline: none;
}
body {
font-family: Arial;
background-color: #3498DB;
padding: 50px;
}
.login {
margin: 20px auto;
width: 300px;
}
.login-screen {
background-color: #FFF;
padding: 20px;
border-radius: 5px
}

.app-title {
text-align: center;
color: #777;
}

.login-form {
text-align: center;
}
.control-group {
margin-bottom: 10px;
}

input {
text-align: center;
background-color: #ECF0F1;
border: 2px solid transparent;
border-radius: 3px;
font-size: 16px;
font-weight: 200;
padding: 10px 0;
width: 250px;
transition: border .5s;
}

input:focus {
border: 2px solid #3498DB;
box-shadow: none;
}

.btn {
border: 2px solid transparent;
background: #3498DB;
color: #ffffff;
font-size: 16px;
line-height: 25px;
padding: 10px 0;
text-decoration: none;
text-shadow: none;
border-radius: 3px;
box-shadow: none;
transition: 0.25s;
display: block;
width: 250px;
margin: 0 auto;
}

.btn:hover {
background-color: #2980B9;
}

.login-link {
font-size: 12px;
color: #444;
display: block;
margin-top: 12px;
}

Modify the login.html template as:

<link rel="stylesheet" href="/static/style.css" type="text/css">
{% block body %}

<form action="/login" method="POST">
<div class="login">
<div class="login-screen">
<div class="app-title">
<h1>Login</h1>
</div>
<div class="login-form">
<div class="control-group">
<input type="text" class="login-field" value="" placeholder="username"
 name="username">
<label class="login-field-icon fui-user" for="login-name"></label></div>
<div class="control-group">
<input type="password" class="login-field" value="" placeholder="password"
 name="password">
<label class="login-field-icon fui-lock" for="login-pass"></label></div>
<input type="submit" value="Log in" class="btn btn-primary btn-large btn-block">

</div>
</div>
</div>
</form>
{% endblock %}

Please restart the application.

Logout

As you may have seen, there is no logout button or functionality. Creating that is very easy. The solution proposed below is only one of the many solutions. Subsequently, we create a new route /logout which directs to the function logout(). This function clears the session variable and returns to the login screen.

@app.route("/logout")
def logout():
session['logged_in'] = False
return home()

The full code is shown below:

from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os

app = Flask(__name__)

@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello user! <a href="/logout">Logout</a>"

@app.route('/login', methods=['POST'])
def do_admin_login():
if request.form['password'] == 'password' and request.form['username'] == 'admin':
session['logged_in'] = True
else:
flash('wrong password!')
return home()

@app.route("/logout")
def logout():
session['logged_in'] = False
return home()

if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=8080)

Connecting a Database

If you want a multi-user login system, you should add a database layer to the application. Flask does not have out of the box database support. Moreover, you have to use a third-party library if you want database support. In this tutorial, we will use SqlAlchemy. If you do not have that installed type:

$ pip install Flask-SqlAlchemy

SQLAlchemy is an SQL toolkit and object-relational mapper (ORM) for the Python programming language. Also, it has support for MySQL, Microsoft SQL Server, and many more relational database management systems. If all of these terms are unfamiliar to you, keep reading.

Create the file tabledef.py:

from sqlalchemy import *
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy import Column, Date, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref

engine = create_engine('sqlite:///tutorial.db', echo=True)
Base = declarative_base()


class User(Base):
""""""
__tablename__ = "users"

id = Column(Integer, primary_key=True)
username = Column(String)
password = Column(String)

#----------------------------------------------------------------------
def __init__(self, username, password):
""""""
self.username = username
self.password = password

# create tables
Base.metadata.create_all(engine)

Execute it with:

python tabledef.py

Hence, this file will create the database structure. Inside the directory, you will find a file called tutorial.db. Thereforecreate a file called demo.py which will contain this code:

import datetime
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from tabledef import *

engine = create_engine('sqlite:///tutorial.db', echo=True)

# create a Session
Session = sessionmaker(bind=engine)
session = Session()

user = User("admin","password")
session.add(user)

user = User("python","python")
session.add(user)

user = User("jumpiness","python")
session.add(user)

# commit the record the database
session.commit()

session.commit()
$ python demo.py

This will put dummy data into your database. Finally, we update our app.py

Validating the Login Credentials with SqlAlchemy

The next step is to write the function that validates the user and password that exist in the database. Hence, using SqlAlchemy, we can do this (dummy/pseudo-code):

@app.route('/test')
def test():

POST_USERNAME = "python"
POST_PASSWORD = "python"

Session = sessionmaker(bind=engine)
s = Session()
query = s.query(User).filter(User.username.in_([POST_USERNAME]),
                            User.password.in_([POST_PASSWORD]) )
result = query.first()
if result:
return "Object found"
else:
return "Object not found " + POST_USERNAME + " " + POST_PASSWORD

Also, we use SqlAlchemys Object Relational Mapping (ORM). Undoubtedly, we map the objects to relational database tables and vice versa.

from flask import Flask
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
from sqlalchemy.orm import sessionmaker
from tabledef import *
engine = create_engine('sqlite:///tutorial.db', echo=True)

app = Flask(__name__)

@app.route('/')
def home():
if not session.get('logged_in'):
return render_template('login.html')
else:
return "Hello User! <a href="/logout">Logout</a>"

@app.route('/login', methods=['POST'])
def do_admin_login():

POST_USERNAME = str(request.form['username'])
POST_PASSWORD = str(request.form['password'])

Session = sessionmaker(bind=engine)
s = Session()
query = s.query(User).filter(User.username.in_([POST_USERNAME]), 
                             User.password.in_([POST_PASSWORD]) )
result = query.first()
if result:
session['logged_in'] = True
else:
flash('wrong password!')
return home()

@app.route("/logout")
def logout():
session['logged_in'] = False
return home()

if __name__ == "__main__":
app.secret_key = os.urandom(12)
app.run(debug=True,host='0.0.0.0', port=8080)

Finally, you can now login with different users defined in the database.

Please feel free to share your feedback and comments in the section below. To know more about our services, please visit Loginworks Softwares Inc.

Leave a Comment