GraphQL with JWT authentication for Redis using Flask in Python

Raul Alves
5 min readApr 20, 2020

--

1 — Introduction

In this article, we will build a backend service that holds a simple banking application. It’s only composed by client’s information and their credit card data, stored in different databases. The GraphQL queries will retrieve the clients data, protected by JWT. The data will be stored in Redis and the endpoint will be created using Flask, in Python.

The full code is available on my Github page: https://github.com/raullalves/graphql_redis_flask

2 — Basic concepts

Why GraphQL ?

Nowadays, most companies are using GraphQL, replacing the old REST endpoints. There are two main reasons for that:

  • Gives more control to the frontend to request exactly the data needed
  • Removes the process of when changing the endpoints parameters, the Swagger or other tool should also be modified for generating the JS interfaces.

A GraphQL query is simply acquiring information from the database. A GraphQL mutation is just like a POST, where data is inserted in the database.

In Python, we will use Graphene, which is the API for GraphQL.

Why Redis ?

Redis is an open source database. The data is stored as a key-value, being extremally simple and fast to save and access data during runtime in productions servers. It is also used as a message broker for queueing.

I chose to explore redis with GraphQL because other databases already have tons of code available (eg. Graphene with SQL and Graphene with Mongo).

Why Flask ?

Flask is a Python API that makes it easy to create the backend of a web application or a microsservice. Despite Django being more recommended for production development of large applications, I chose Flask because I think it’s simpler =).

Flask-GraphQL is the API used in this article.

Why JWT ?

JWT stands for Json Web Token. For security reasons, each endpoint of any application or microservice needs to have authentication/authorization mechanisms.

First, the user needs to say who he/she is, performing the login through a GraphQL mutation. That login generates a token, that holds information about the user, its privileges and its expiration date. That is basically the authentication mechanism adopted in this article.

Then, that token is going to be used in each GraphQL query. The token is placed in the header of the requisition. In the code, before actually performing the query, the backend needs to evaluate the authorization of the provided token, to make sure it has the privileges to access those resources.

That is a simple way to controll access of the resources of your microservices.

3— Setting up

Installing Redis

In case you don’t have Docker installed, install it =)

I run redis as a docker container simply by:

The command above exposes the port 6379, and run the Redis version 3.2.5-alpine.

Installing required python libraries

I’m using Python 3.7.4 with windows 10. In case of a different combination of OS or Python version, probabily some of the libraries versions may change.

Installing Postman

Postman is a powerful application that enables you to create requests without using noisy Curl commands. In GraphQL applications, the GraphiQL is commonly used for sending queries. However, as far as I know, it’s not possible to embed the authorization header in the request. That’s why I recommend installing Postman.

4 — The data

Redis enables us to separate the data in different databases. The data is distributed as bellow

  • Database 0: The user/password information for login
  • Database 1: The client’s information
  • Database 2: The credit card information

User/Password information:

The key is the username. The value is the password.

The client’s information:

The key is the client’s automatically generated primary key. The value is a dict containing

  • First name
  • Last name
  • Age
  • City
  • The id for its credit card information

Credit card information:

The key is its automatically generated primary key. The value is a dict containing:

  • Credit card number
  • CVV

Creating the Redis client in Python

First, we should have a Redis Client, that inserts and retrieves data from Redis

The decorator @connect_to_redis performs the connection, in case it wasn’t previously set. It is defined as following:

Then, we gotta define three Redis instances for each of our databases, previously stated:

Populating Redis

Let’s use the following script to populate redis with automatic data.

First, let’s create a method for generating random strings:

Random login information possibilities:

Creating random login information:

Random Client’s information possibilities:

Random Credit card info:

Let’s randomly pick combinations and insert into Redis in each Database:

Now, let’s populate the login database.

Obviously, I will set a default login and password, so that you can use it, instead of searching in redis among the random values.

  • Login: admin
  • Password: admin

5 Creating the GraphQL queries and mutation

Our application will simply have the following functionalities:

  • Login
  • Get info of a specific user
  • Get all info

If using REST, we would have 3 endpoints:

  • /login: Where the request sends the user and password, and receives the token as a response
  • /get_user_info/<user_id>: The user id is passed by parameter and the response is all user info. If we only want one specific field of that user, we need to, either create another parameter in the request or send the desired info in the body of the requisition. Hence, it should be a POST
  • /get_all_users_info: The backend would return all users info. Again, if only one one specific information is needed, the backend should be modified.

In the GraphQL world, only ONE endpoint is needed.

Let’s create our app and specify that endpoint

We need to create a method that, given an app instance, creates the only endpoint needed.

The add_url_rule method allows us to setup the GraphQL, using frask_graphql. The endpoint created is /simple_bank_app.

As you can see, the previous method is missing the Query and Mutation definition. The mutation is only needed for the login. Let’s define it:

If success = True, that means the user and password is correct. Here is an login example:

The response is:

That token is going to be used in the following requests.

Now, let’s create an decorator for evaluating the provided token in the queries.

Now, only the Query class is missing. First, we have to define what a Client is.

As discussed before, a client has id, first_name, last_name, age, city and its credit card information. Remember, in Redis, the credit card info is not stored on the sabe database as the client. Here it goes:

In our Query object, it’s possible to access a single client information and also all clients in once. Here it is:

6- A few query examples

  • Query only the credit card number of a specific client id

The response is:

  • Query only the clients name

The response should be

That’s it. Hope that helps

--

--