Introduction technology or framework. So it is decoupled from the UI or front end technology.
We know when we need to restrict users from accessing protected area of the application. In addition to authentication you can also implement authorization based on user’s role.
Prerequisites
Python 3.7.4, MySQL 8.0.17, Flask 1.1.1
Creating MySQL table
Create a table called user in the MySQL database using the following structure.
The following table has
id,
username,
password columns.
CREATE TABLE `user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(45) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Storing Sample User
To make the example Python Flask REST API login logout example workable, we have added one row with user information into table.
It is always better to store password in encrypted format instead of clear text due to security reasons.
The password is
roy for the password field’s encrypted value in the table.
insert into `user`(`username`, `password`) values ('roy', 'pbkdf2:sha256:150000$k1Ud5dzh$d0347f416e89ea486b33c988c9be65730329b2dd6d712f73c9920103a006a82e');
Creating Project Directory
Create a project root directory called python-flask-rest-api-login-logout 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.
Related Posts:
- Python flask login logout example
- Python Flask Login Logout with Remember Me Option
- jQuery AJAX based Login Logout using Python Flask MySQL
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
CORS to allow cross origin requests, otherwise you may get cross origin error.
from flask import Flask from flask_cors import CORS app = Flask(__name__) app.secret_key = "secret key" app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=10) CORS(app)
Database Configuration
We create the below db_config.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)
Configuring REST Endpoint
Now we will create REST endpoint that will be used to authenticate user into the server.
We show a successful message once a user is successfully authenticated with correct credentials.
Only with successful operation we send response status 200 otherwise we send 400 or 401 as bad request or unauthorized with error messages.
We have defined endpoints for root, login and logout to access protected area, authenticate using credentials and logout from the application, respectively.
WARNING: session violates RESTful.
You may want to know why check_password_hash() is required?
Create a file rest.py with the below source code.
import pymysql from app import app from db import mysql from flask import jsonify, request, session from werkzeug import check_password_hash @app.route('/') def home(): if 'username' in session: username = session['username'] return jsonify({'message' : 'You are already logged in', 'username' : username}) else: resp = jsonify({'message' : 'Unauthorized'}) resp.status_code = 401 return resp @app.route('/login', methods=['POST']) def login(): conn = None; cursor = None; try: _json = request.json _username = _json['username'] _password = _json['password'] # validate the received values if _username and _password: #check user exists conn = mysql.connect() cursor = conn.cursor() sql = "SELECT * FROM user WHERE username=%s" sql_where = (_username,) cursor.execute(sql, sql_where) row = cursor.fetchone() if row: if check_password_hash(row[2], _password): session['username'] = row[1] #cursor.close() #conn.close() return jsonify({'message' : 'You are logged in successfully'}) else: resp = jsonify({'message' : 'Bad Request - invalid password'}) resp.status_code = 400 return resp else: resp = jsonify({'message' : 'Bad Request - invalid credendtials'}) resp.status_code = 400 return resp except Exception as e: print(e) finally: if cursor and conn: cursor.close() conn.close() @app.route('/logout') def logout(): if 'username' in session: session.pop('username', None) return jsonify({'message' : 'You successfully logged out'}) REST client tool – Chrome extension REST client. You can also use Postman or any other REST client tool for testing.
You may also do client side programming using Angular, React or any front end technology to call the above REST endpoint.
Root URI
When you access the root URI without authenticating.
URL:
Method:
GET
Response:
{ "message": "Unauthorized" }
Authentication
Authenticate using credentials
roy/roy.
URL:
Method:
Request Body:
{ "username" : "roy", "password" : "roy" }
Response:
{ "message": "You are logged in successfully" }
Accessing Root URI
Now when you access again the root URI or URL, you will be able to access it.
URL:
Method:
GET
Response:
{ "message": "You are already logged in", "username": "roy" }
Logout using the following URL.
URL:
Method:
GET
Response:
{ "message": "You successfully logged out" }
You can also test by providing wrong credentials or not sending any credentials.
Source Code
Thanks for reading.