Let’s have a look at how we are able to safe a REST API with JSON internet tokens to stop customers and third-party purposes from misusing them.
We’ll construct a database service utilizing SQLite and permit customers to entry this service via a REST API utilizing HTTP strategies corresponding to POST and PUT.
As well as, we are going to study why JSON internet tokens are an acceptable option to shield relaxation API as an alternative of digest and primary authentication. Earlier than transferring on, let’s perceive the time period JSON internet tokens, REST API and Flask framework.
JSON internet tokens
JSON internet token, also called JWT, is the safe option to switch arbitrary tokens between two events or entities. JSON normally consists of three elements as follows.
- Load capability
- Header
- Signature
JSON makes use of two forms of construction varieties when transferring information or data between two events.
- serialized
- Deserialized
The serialized type is utilized in transferring information to the community via every request and response whereas the deserialized type is utilized in studying and writing information to the online token.
Within the serialized type, there are three elements.
- Header
- Load capability
- Signature
The header part defines the cryptographic details about the tokens. For instance:
- Is it signed or unsigned JWT?
- Outline algorithm strategies
Not like the serialized type, the deserialized type incorporates two elements.
- Load capability
- Header
REST API
API (Software Programming Interface) permits communication between two purposes to retrieve or submit the info. There are two common forms of APIs: internet and system API.
On this article, we solely have a look at the online API. There are two forms of internet APIs.
- Request–Response API: Relaxation, GraphQL, Distant Process Name (RPC)
- Occasion Pushed API: WebHooks, Net Sockets, HTTP Streaming
REST API falls below the request-response class. It makes use of HTTP strategies corresponding to GET, POST, and PUT to carry out API operations.
A traditional instance is when a consumer sends a GET methodology to the online service to request or fetch a particular useful resource or assortment of sources. The server then returns the particular useful resource or assortment of sources to the consumer who requested it.
Flask body
Flask is a framework primarily based on Python. It’s a micro framework utilized by python builders to construct the REST API. It’s referred to as a micro-framework as a result of it permits builders so as to add, for instance, customized authentication and another backend system primarily based on preferences.
Let’s begin with the implementation. My system setup is as follows.
- Ubuntu as working system
- Python 2.7+
- Postman
Arrange a digital surroundings with virtualenv
We have to arrange a digital surroundings to make sure that some packages do not battle with system packages. Let’s use the virtualenv
to arrange a brand new digital surroundings.
Suppose you could have the pip
command is obtainable in your system, run the next command through pip
to put in.
pip set up virtualenv
If you do not have pip in your laptop, observe this documentation to put in pip in your system.
Subsequent, let’s create a folder to retailer or maintain our digital surroundings. Use the mkdir
beneath command to create a folder
mkdir flaskproject
Change to the flaskproject
listing utilizing the next command
cd flaskproject
Contained in the flaskproject
folder, use the virtualenv
software to create a digital surroundings as proven beneath:
virtualenv flaskapi
After you put in the virtualenv
software to create the digital surroundings, run it cd
command to alter to the flaskapi
listing because the digital surroundings and activate it with the command beneath.
supply bin/activate
Carry out all duties associated to this venture throughout the digital surroundings.
Set up packages utilizing pip
Now it is time to set up packages, such because the flask framework and PyJWT, which we are going to use to construct the REST API and different crucial packages for our API venture.
make a necessities.txt
file containing the next packages.
Flask
datetime
uuid
Flask-SQLAlchemy
PyJWT
Set up them with pip.
pip set up -r necessities.txt
Arrange a database
Let’s set up SQLite.
apt-get set up sqlite3
Create a database referred to as the library. Inside this database we are going to create two tables, specifically the Customers
And Authors
desk.
Person desk will comprise registered customers. Solely registered customers can entry the Authors desk.
The creator desk shops the creator data or particulars corresponding to creator title, nation of delivery and so forth submitted by the registered customers.
Create the database with the next command:
sqlite3 library.db
You may verify when you’ve got efficiently created the database through the use of the command beneath:
.databases
Open a brand new terminal and run the next within the digital surroundings we created earlier.
contact app.py
Paste the next code into the file named app.py
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import SQLAlchemy
from werkzeug.safety import generate_password_hash, check_password_hash
import uuid
import jwt
import datetime
from functools import wraps
The primary line within the code above imports packages like request
And jsonify
. We’ll make use of it request
to maintain observe of the request degree information throughout a request and use jsonify
to output responses in a JSON format.
On the following line, we imported SQLAlchemy from flask_sqlalchemy
to combine SQLAlchemy capabilities into the flask.
By werkzeug.safety
we imported generate_password_hash
to generate password hash for customers and check_password_hash
to verify the consumer’s password when evaluating the password submitted by customers with the passwords of customers saved within the database.
Lastly, we imported uuid
also called common distinctive identifiers to generate random ID numbers for customers.
But throughout the app.py
implement the library API configuration settings utilizing the code beneath within the app.py file.
Place the next code beneath the import assertion.
app = Flask(__name__)
app.config['SECRET_KEY']='Th1s1ss3cr3t'
app.config['SQLALCHEMY_DATABASE_URI']='sqlite://///house/michael/geekdemos/geekapp/library.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
Now create two fashions for the Customers and Authors desk as proven beneath. Copy and paste the code into the app.py file.
Place the code beneath proper beneath this database setting db = SQLAlchemy(app)
class Customers(db.Mannequin):
id = db.Column(db.Integer, primary_key=True)
public_id = db.Column(db.Integer)
title = db.Column(db.String(50))
password = db.Column(db.String(50))
admin = db.Column(db.Boolean)
class Authors(db.Mannequin):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), distinctive=True, nullable=False))
e-book = db.Column(db.String(20), distinctive=True, nullable=False))
nation = db.Column(db.String(50), nullable=False))
booker_prize = db.Column(db.Boolean)
Generate consumer and creator tables
On the terminal, kind the next code into the digital surroundings to generate or create tables for each the consumer and creator tables as proven beneath
from app import db
db.create_all()
Then open the app.py
file within the digital surroundings and create one other perform.
This perform generates tokens to permit solely registered customers to entry and carry out a set of API operations on the creator desk.
Place this code below the database mannequin for the Authors desk
def token_required(f):
@wraps(f)
def decorator(*args, **kwargs):
token = None
if 'x-access-tokens' in request.headers:
token = request.headers['x-access-tokens']
if not token:
return jsonify({'message': 'a legitimate token is lacking'})
attempt:
information = jwt.decode(token, app.config[SECRET_KEY])
current_user = Customers.question.filter_by(public_id=information['public_id']).first()
besides:
return jsonify({'message': 'token is invalid'})
return f(current_user, *args, **kwargs)
return decorator
Create routes for the consumer desk
Now let’s create a route that enables customers to register for the Authors API through a username and password, as proven beneath.
Open the app.py
file within the digital surroundings and paste the next code beneath the perform token_required(f)
@app.route('/register', strategies=['GET', 'POST'])
def signup_user():
information = request.get_json()
hashed_password = generate_password_hash(information['password'], methodology='sha256')
new_user = Customers(public_id=str(uuid.uuid4()), title=information['name'], password=hashed_password, admin=False)
db.session.add(new_user)
db.session.commit()
return jsonify({'message': 'registered efficiently'})
Inside the digital surroundings, create a distinct route within the app.py
file to permit registered customers to login.
When a consumer logs in, a random token is generated for the consumer to entry the library API.
Paste the code beneath beneath the earlier route we created.
@app.route('/login', strategies=['GET', 'POST'])
def login_user():
auth = request.authorization
if not auth or not auth.username or not auth.password:
return make_response('couldn't confirm', 401, {'WWW.Authentication': 'Fundamental realm: "login required"'})
consumer = Customers.question.filter_by(title=auth.username).first()
if check_password_hash(consumer.password, auth.password):
token = jwt.encode({'public_id': consumer.public_id, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)}, app.config['SECRET_KEY'])
return jsonify({'token' : token.decode('UTF-8')})
return make_response('couldn't confirm', 401, {'WWW.Authentication': 'Fundamental realm: "login required"'})
Nonetheless throughout the digital surroundings, create one other route within the app.py
file to retrieve or retrieve all registered customers.
This code checks for all registered customers within the Customers desk and returns the ultimate lead to JSON format.
Paste the code beneath beneath the login route
@app.route('/customers', strategies=['GET'])
def get_all_users():
customers = Customers.question.all()
end result = []
for consumer in customers:
user_data = {}
user_data['public_id'] = consumer.public_id
user_data['name'] = consumer.title
user_data['password'] = consumer.password
user_data['admin'] = consumer.admin
end result.append(user_data)
return jsonify({'customers': end result})
Create routes for the creator desk
Let’s create routes for the Authors desk in order that customers can retrieve all authors within the database and delete authors.
Solely customers with legitimate tokens can carry out these API operations.
Within the app.py file, create a route for registered customers to create new authors.
Paste this code beneath the route that enables a consumer to retrieve all registered customers.
@app.route('/creator', strategies=['POST', 'GET'])
@token_required
def create_author(current_user):
information = request.get_json()
new_authors = Authors(title=information['name'], nation=information['country'], e-book=information['book'], booker_prize=True, user_id=current_user.id)
db.session.add(new_authors)
db.session.commit()
return jsonify({'message' : 'new creator created'})
Then create one other route so {that a} registered consumer with a legitimate token can retrieve all authors within the creator desk as proven beneath.
Paste this code beneath the route that enables a consumer to create a brand new creator.
@app.route('/authors', strategies=['POST', 'GET']) @token_required def get_authors(current_user): authors = Authors.question.filter_by(user_id=current_user.id).all() output = [] for creator in authors: author_data = {} author_data['name'] = creator.title author_data['book'] = creator.e-book author_data['country'] = creator.nation author_data['booker_prize'] = creator.booker_prize output.append(author_data) return jsonify({'list_of_authors' : output})
Lastly, nonetheless throughout the app.py
file, create a path to take away a specified creator as proven beneath.
Paste this code beneath the route that enables a consumer to retrieve an inventory of authors.
@app.route('/authors/<author_id>', strategies=['DELETE'])
@token_required
def delete_author(current_user, author_id):
creator = Writer.question.filter_by(id=author_id, user_id=current_user.id).first()
if not creator:
return jsonify({'message': 'creator doesn't exist'})
db.session.delete(creator)
db.session.commit()
return jsonify({'message': 'Writer deleted'})
if __name__ == '__main__':
app.run(debug=True)
After that, save the app.py file and shut it within the digital surroundings.
Check the library API with Postman
On this part we are going to make use of a postman software to ship a request to the database providers. If you do not have Mailman in your laptop, discover ways to obtain and set up it right here.
Along with the postman, we are able to use different instruments corresponding to Curl to ship requests to the server.
Open a brand new terminal and sort the next:
postman
The order postman
causes your internet browser to show the web page beneath:
Chances are you’ll determine to enroll and create a free account, however we’ll skip this and entry the app instantly to check the library API, as proven beneath:
On this part, we could have a consumer register for the library API by offering a username and a novel password in JSON format utilizing the POST methodology utilizing the steps beneath:
- Click on the Physique tab
- Then choose the uncooked button and select the JSON format
- enter a username and password to register as proven within the screenshot
- Subsequent to the submit button, enter the next URL http://127.0.0.1/register
- Lastly, change the strategy to POST and hit the submit button.
It is going to show the next output as proven beneath:
Now we’ve got efficiently registered a consumer. Let’s proceed to permit the consumer who simply registered to log in to generate a brief random token to entry the creator desk by following these steps:
- Click on the Authorization tab.
- Choose primary authentication below the sort part.
- Then fill within the username and password type with the username and password you beforehand registered with.
- Lastly, hit the submit button to login and generate a random token.
As soon as the consumer has efficiently logged in, a random token shall be generated for the consumer as proven within the screenshot.
We’ll make use of the generated random token to entry the creator desk.
On this part, we add an creator’s data to the Authors desk through the POST methodology utilizing the next steps:
- Click on the Headers tab
- Add the next HTTP headers proven within the screenshot
- Then click on on the physique tab and enter the main points of the brand new creator
- Then hit the submit button so as to add the creator’s particulars to the creator desk
It’s also possible to retrieve the creator data within the Authors desk as follows:
- Ensure your generated token is within the headers part. if it isn’t there, you should fill it along with your token.
- Enter this URL subsequent to the submit button
http://127.0.0.1/authors
- Then change the HTTP methodology to GET and hit the submit button to retrieve the creator data.
Lastly, you may delete the creator(s) within the Authors desk through the DELETE
methodology utilizing the next steps:
- Ensure your token remains to be within the headers part. You may verify the Headers tab to ensure the mandatory data is there.
- Enter this URL subsequent to the submit button
http://127.0.0.1/sam
- Then press the submit button to delete the consumer you specified.
You will discover the complete supply code on Github. You may clone it and look at it in your laptop.