Mobile and web development
for your business

Providing high-quality development outsourcing for build-to-suit projects

Contact us




React Native















Our services
social network
for gamers
Our projects
Our projects
smart watches
with voice assistant
flutter | django
Our projects
online teaching platform
react | django
Our projects
Team stacked with professionals
With 3+ years of experience is ready to deliver the best solution for your business
And most importantly

We are ready to start working with your project right now

Years on the market
hours of work
successfully released
10 000+
Contact us
And within one day we will send you the final price after detailed discussion of your needs.

How to create blacklist for JWT tokens in Django
Recently, in one of the projects, we had to provide the user with the opportunity to change the password, so that they logged out from all other devices at the same time. Because authentication was done on JWT tokens, what happened was that it was impossible to manually expire the token after creation, as it is stateless and stored on the client side.
In this article, we will analyze the generation of a JWT token with the possibility of blacklisting it using an empty project as an example, and we will also test the result using Postman.

Briefly about JWT
JSON Web Token (JWT) is a JSON object that is defined in the open standard RFC 7519. It is considered one of the secure ways to transfer information between two parties. Its main feature is that all the necessary authentication data is stored in the token itself. It consists of 3 main parts: header, payload and signature. Header is a JSON object that contains information about the token type and encryption method:
Payload usually stores the user ID, the lifetime of the token, or any other information at the discretion of the issuer. However, there are reserved field names, and it is not recommended to change their purpose:
  • iss: a string with the unique identifier of the party generating the token.
  • sub: a string that is the unique identifier of the party about which information is contained in this token (subject).
  • aud: an array of case-sensitive strings or a URI that is a list of the recipients of this token.
  • exp: A time in Unix Time format that determines when the token will become invalid (expiration).
  • nbf: opposite to the exp key, this is a Unix Time that determines when the token will become valid (not before).
  • jti: a string that specifies the unique identifier for this token (JWT ID).
  • iat: a time in Unix Time format that specifies when the token was created.
Signature is formed as follows:
1. Header and Payload are converted to base64 format.
2. Next, they are connected in one line through a dot.
3. According to the algorithm specified in the header, the received string is hashed based on the secret key.
The result of this algorithm is a signature. To get the JWT itself, you need to connect the header, payload and signature through the dot.

Authentication through JWT
Typically, a user receives a JWT upon registration or first login. They save it on their device and, on subsequent calls to the API, pass this token with all requests. As a general rule, the token is placed in the request header. Having received a token, the application first checks its signature. After verifying that the signature is valid, the application extracts information about the user from the payload part and authorizes the user based on it.
Token lifetime
The lifetime of the token is a very important point when using JWT. There is no universal answer to this question, it all depends on the service. However, 2 points must be taken into account:
1. If the token lifetime is too long, it can cause security issues. For example, if an attacker manages to compromise a user’s token, they can use it until its lifetime expires.
2. A short token lifetime can lead to excessive load on the server, as the user will have to constantly refresh the old token (request a new one)
Hence the need to give the user an opportunity to reset all their tokens. For example, to give them the opportunity to change the password or log out from all devices if the token is compromised by an attacker.
There are several ways to revoke existing tokens, such as issuing tokens based on a unique user ID, or creating a blacklist for issued tokens.
Let’s take a look at the example about how to blacklist tokens on Django using the django rest framework and the Simple JWT library. Note that the Simple JWT library immediately provides us with a convenient Black List application that we will use.

Initial project setup
Receiving tokens, user registration, user information
At this stage, we are all set to write the main API points. Let’s create a users/ file and write the main serializers there:
Adding existing tokens to the “Black List”

Now the user can register in our application and get information about themselves. What is left for us to do is to give them the opportunity to log out from all devices (blacklist the tokens). The simple_jwt library provides us with two models, OutstandingToken and BlacklistedToken. We will use them to blacklist tokens.

To do this, let’s write another view in the users/ file:

Now we can test the resulting API using Postman. First, we need to send the following request:
Note that because we defined access_token and refresh_token as dynamic properties in the User model and specified them in the serializer, we do not need to additionally request them after registration.

After registration, the user can get information about their account. For this, the Authorization header with the value Bearer {access_token} must be added to the request:

Let’s create an empty project with the django-admin startproject jwt_auth_project command. Let’s immediately create an application for working with users with the python startapp users command and register it in INSTALLED_APPS in the file:

Let’s create a virtualized environment, install the djangorestframework and djangorestframework-simplejwt libraries and write in the

Set permissions only for authenticated users in REST_FRAMEWORK and specify the class provided by the simplejwt library as the authentication backend.
The settings for simplejwt are also written in the file. In this article, we will not go into detail about each of them, as they are all described in detail in the documentation. Note that we chose 5 minutes for the token lifetime, and 2 days for the refresh token.

After that, we should update INSTALLED_APPS:

In the users application, we will create a file and register it in the jwt_auth_project/ file:
Next, we need to write a custom manager for the future user model. In the users application, create a file and type the following code:
Now we can create our own user model in the users/ file:
The next step is to tell Django which user model to use for authentication. To do this, write the following line in the settings file:
Now you can start the server with python runserver create and run migrations with python makemigrations and python migrate. After that, the necessary tables for further work will be created in our database.
After that, in the users/ file, we will write a view for registering and returning information about the user:
Now we need to define the routes for our views in the users/ file:
Note that the rest_framework_simplejwt library provides us with views for obtaining a token and a refresh and there is no need to write them manually.
And register it in users/
Testing the resulting API with Postman

Flutter and working with native code
How to fix the shortcomings in native libraries while working with Flutter, using NFC as an example.

In most cases when working with flutter, the developer doesn’t have to interact with the native code at all (Java/Kotlin and ObjectiveC/Swift), as the flutter’s toolbox is quite rich. But in some cases, you simply can’t do what you need without it. The most popular example is working with phone sensors.
Let’s work through this problem: imagine that you have to read the card data using NFC. We chose the plugin, in our case it was nfc_manager 3.1.0, which will allow us to do such things, but the needed card number doesn’t get returned to the android because of it. What do you do? We have recently encountered such a problem and now we will tell you how to solve it

A word of advice: if there are several of these packages, it is better to put them in a separate folder at the same nesting level and call it “packages”, for example.

Then we need to localize the moment, in which the reading of the bank card number is not happening. To start the reading from flutter, the “startSession” method is being called, which, in turn, calls the native method “Nfc#startSession”. Inside it, everything is set up fairly simply:

Now we need to slightly modify the current code, so that we would be able to send the card number to flutter.

To do this, at first we need to import a corresponding native library into the build.grade file:

implementation ‘com.github.devnied.emvnfccard:library:3.0.1’

Then we need to make an implementation for the interface from this library IProvider, which transfers commands to the card. The needed implementation looks like this:

Then we will edit the code itself before sending the data to flutter in “onDiscovered”.

To read the card data, we need to add the interface implementation, created above, as well as config and parser. Now the code looks something like this:

Then we need to connect to the card and read the needed data:

And then we will finally send the needed data to flutter, by adding to map the received card data:
Now we can receive the card data using NFC.

To solve this problem, you need to perform several steps. First you need to copy the library’s code into your project. It should look like this:

One more flutter vs react native comparison, but on a real case
Big finance company was thinking about launching a new product with a mobile app. They needed a fast solution for both platforms and they started to choose between two cross platform frameworks. It was React Native and Flutter.
When this company approached us with this problem, we decided, in addition to answering standard questions, to show them the difference using a real example by building an mvp with minimal functionality that will answer many of their questions, since both expertises were present in our team.

Project: app with 2 screens.
1 — read data from credit card with camera
2 — read data form credit card with nfc


Stable 60 fps, support for 120 Hz displays, warming up shaders, good at animations, fast animation development, fast application start

React Native:
Up to 60 fps, does not cope well with heavy animations, application startup takes longer.

Framework support

Supported by Google and the community, they develop ready-made libraries for use, as well as a very large number of popular libraries from the community.

React Native:
Supported by the facebook team, lots of libraries, big community, easy to access because javascript is very popular.

Integration with native platform (android and ios)

Stable and fast bridges are used to deliver messages with (if necessary) payload. Native libraries are connected in the same way as when developing a native application and are used in the same way. You can also open native screens and use all other native functionality.

React Native:
To work with the native, it is necessary to develop communication bridges with the native, which are difficult to develop and still have several unresolved problems.

Developing speed

Fast due to hot reload, hot restart and widget system. A large number of ready-made widgets.

React Native:
There is a similar hot refresh, but in most cases it does not work stably, breaking the work of libraries, javascript is unsafe, many components need to be updated manually.


Widget testing, unit tests, integration testing. Test SDK comes with Flutter.

React Native:
Testing tools are inefficient as different javascript engines are used for different debugging modes.


Fewer resumes and vacancies due to relative novelty, but Dart is a mixture of other OOP languages, which significantly lowers the threshold for entering the language for a completely unfamiliar person, which affects the quality and speed of selection, and the average salary is higher.

React Native:
More vacancies and resumes, low entry threshold due to javascript, which has a greater negative impact on the quality and speed of selection.

Hours for developing demo project:

Flutter: 10

React Native: 16

Problems encountered during this development:

There was no flutter library to read the card number. In the native part of the library, I had to use part of the code from another native library.

React Native:
Problems with the gradle version for connecting libraries, long project initialization, non-working project release due to library versions.

Application build time from scratch (Macbook Pro m1), sec

Flutter: 60s

React Native: 2m 40s

Assembly file size (debug version), mb

Flutter: 30,8

React Native: 50,4

As a result, after analyzing the risks, the company chose Flutter to develop its product.
Would love to hear your opinion on that, we are always happy to discuss it

Besides parameters such as performance, framerate, battery consumption — there are some valuable business characteristics like hiring difficulty, team cost expertise support.
Made on