Introduction

In this post we are going to see how to give users opportunity to remember their login credentials through cookie so that next time they try to login to the application do not require username and password for login.

In our previous tutorials we have seen how to login and logout from an application using the following examples:

Here we will store username and password into cookie.

As long as cookie contains such user’s valid username and password, user doesn’t need to enter any username and password. The user will be logged in to the application automatically.

What is cookie?

An http cookie is a small piece of data sent from a website and stored on the user’s computer by the user’s web browser while the user is browsing.

Cookies were designed to be a reliable mechanism for websites to remember stateful information or to record the user’s browsing activity.

Prerequisites

Python 3.7.4, Flask 1.1.1, MySQL 8.0.17, Windows 10 64 Bit

Creating MySQL table

Create a table called user in the MySQL database using the following structure.

The following table has user_id , user_name , user_email , user_password columns.

CREATE TABLE `user` ( `user_id` bigint NOT NULL AUTO_INCREMENT, `user_name` varchar(45) DEFAULT NULL, `user_email` varchar(45) DEFAULT NULL, `user_password` varchar(255) DEFAULT NULL, PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Dumping User Details

We don’t want to create any new user through our application, so we will dump a user details using SQL statement.

The password field’s value is in the encrypted format, so the actual value is roy .

insert into `user`(`user_id`,`user_name`, `user_email`, `user_password`) values (1, 'Soumitra', '[email protected]', 'pbkdf2:sha256:150000$k1Ud5dzh$d0347f416e89ea486b33c988c9be65730329b2dd6d712f73c9920103a006a82e');

Creating Project Directory

Create a project root directory called python-flask-rest-api-login-logout-remember as per your chosen location.

We may not mention the project’s root directory name in the subsequent sections but we will assume that we are creating files with respect to the project’s root directory.

Configuring Application

We will configure application through flask framework.

Create a file called app.py with the below code.

Here we need to assign secret key otherwise session will not work in Python. The secret key, ideally, should be in encrypted format.

We have also configured the session timeout – 10 minutes because flask expires session once you close the browser unless you have a permanent session.

We have also configured maximum time 5 minutes for cookie for testing purpose. Ideally cookie is kept live for days to months. We have defined the cookie timeout in a global variable so that this variable can be used anywhere throughout the application.

from flask import Flask from datetime import timedelta app = Flask(__name__) app.secret_key = "secret key" app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=10) global COOKIE_TIME_OUT #COOKIE_TIME_OUT = 60*60*24*7 #7 days COOKIE_TIME_OUT = 60*5 #5 minutes

Database Configuration

We create the below db.py Python script to setup the MySQL database configurations for connecting to database.

We need to configure database connection with flask module and that’s why we have imported app module and setup the MySQL configuration with flask module.

Make sure to change the database configuration values according to your database setup.

from app import app from flaskext.mysql import MySQL mysql = MySQL() # MySQL configurations app.config['MYSQL_DATABASE_USER'] = 'root' app.config['MYSQL_DATABASE_PASSWORD'] = 'root' app.config['MYSQL_DATABASE_DB'] = 'roytuts' app.config['MYSQL_DATABASE_HOST'] = 'localhost' mysql.init_app(app)

Handling Session, Cookie, Login, Logout

Now we will see how to handle user’s login logout with session and cookie.

We will create main.py script. This script handles Python login and logout example with remember me option using Flask and MySQL.

It defines all required URIs for performing login and logout operations.

It will also connect to MySQL database server and query the database to read.

Related Posts:

We have used login.html page as a template view for logging in to the system but for home or index page we have only displaying html text instead of using template page. If you want you can use html template page for home or index page also.

The important part is /submit URI which is used to validate user credentials.

If login credentials are found in the cookie then you may validate or not against database. Here we have validated against database values.

If user logs in first time with remember me option then only we put into the cookie. Finally user redirected to the restricted area upon successful login.

import pymysql from app import app, COOKIE_TIME_OUT from db import mysql from flask import flash, session, render_template, request, redirect, make_response from werkzeug import generate_password_hash, check_password_hash @app.route('/') def index(): if 'email' in session: username = session['email'] return 'Logged in as ' + username + '<br>' + "<b><a href = '/logout'>Click here to logout</a></b>" return "You are not logged in <br><a href = '/login'></b>" + "click here to login</b></a>" @app.route('/login') def login(): return render_template('login.html') @app.route('/submit', methods=['POST']) def login_submit(): conn = None cursor = None _email = request.form['inputEmail'] _password = request.form['inputPassword'] _remember = request.form.getlist('inputRemember') if 'email' in request.cookies: username = request.cookies.get('email') password = request.cookies.get('pwd') conn = mysql.connect() cursor = conn.cursor() sql = "SELECT * FROM user WHERE user_email=%s" sql_where = (username,) cursor.execute(sql, sql_where) row = cursor.fetchone() if row and check_password_hash(row[3], password): print(username + ' ' + password) session['email'] = row[2] cursor.close() conn.close() return redirect('/') else: return redirect('/login') # validate the received values elif _email and _password: #check user exists conn = mysql.connect() cursor = conn.cursor() sql = "SELECT * FROM user WHERE user_email=%s" sql_where = (_email,) cursor.execute(sql, sql_where) row = cursor.fetchone() if row: if check_password_hash(row[3], _password): session['email'] = row[2] cursor.close() conn.close() if _remember: resp = make_response(redirect('/')) resp.set_cookie('email', row[2], max_age=COOKIE_TIME_OUT) resp.set_cookie('pwd', _password, max_age=COOKIE_TIME_OUT) resp.set_cookie('rem', 'checked', max_age=COOKIE_TIME_OUT) return resp return redirect('/') else: flash('Invalid password!') return redirect('/login') else: flash('Invalid email/password!') return redirect('/login') else: flash('Invalid email/password!') return redirect('/login') @app.route('/logout') def logout(): if 'email' in session: session.pop('email', None) return redirect('/') if __name__ == "__main__": app.run()

Template View File

Below login.html page is created inside templates folder from where flask API by default picks up the view file.

We show any message, if found, in flash scope on the top of the page.

We populate the input fields if the value found in cookie.

<doctype html> <title>User Login with remember me - Python Flask</title> <h2>Login</h2> <p> {% with messages = get_flashed_messages() %} {% if messages %} <ul class=flashes> {% for message in messages %} <li>{{ message }}</li> {% endfor %} </ul> {% endif %} {% endwith %} </p> <form method="post" action="/submit"> <dl> <p> <input name="inputEmail" value="{% if 'email' in request.cookies %} {{ request.cookies.get('email') }} {% endif %}" type="text" placeholder="Email" required> </p> <p> <input name="inputPassword" value="{% if 'pwd' in request.cookies %} {{ request.cookies.get('pwd') }} {% endif %}" type="password" placeholder="Password" autocomplete="off" required> </p> <p> <input name="inputRemember" checked="{% if 'rem' in request.cookies %} {{ request.cookies.get('rem') }} {% endif %}" type="checkbox" autocomplete="off">Remember Me</input> </p> </dl> <p> <input type="submit" value="Submit"> </p> </form>

Enough coding… let’s move on to testing…

Testing the Application

Now navigate to the project directory and execute the command python main.py , your server will start on default port 5000.

If you want to change the port then you can change the line app.run() to app.run(port=5001) , where 5001 is the new port.

Invalid Credentials

When you input incorrect email and password without remember me checkbox checked then you will see below error:

Valid Credentials

When you input valid username and password (roy/roy) then you will get below output:

Remember Me

When you give valid credentials and check the checkbox (Remember Me) and click on Submit button.

Next time you come back to login to application on same browser and if cookie has not been expired then you will see the input fields are automatically populated with credentials and you just need to click on Submit button to login.

That’s all. Hope you got an idea on Python Flask login logout example with remember me option.

Source Code

Download Source Code

Thanks for reading.