Monday, January 15, 2018

Setting up Django Rest API with JWT authentication - Part 1

In this post, I will cover how to setup project and application for REST API and secure it using JWT.

Software used -
1) OS - Windows 10
2) Python - 3.6 (command: Python --version)
3) Django - 1.11.2 (Command: python -c "import django; print(django.get_version())")
4) Django Rest Framework - 3.6.3
5) Django Rest Framework JWT - 1.11.0 dist
6) Eclipse IDE

Setting up of Project and folder structures

Step 1 - Create a django project by clicking on File > New > Other and then selecting PyDev Django Project

Step 2 - Open command prompt and go to the location where the project is present and type the below command -
    django-admin.py startproject djangowebs
   
    Then in order to create an app inside the project you need to use
    python manage.py webs
    You can have any name of your choice in place of webs.

Configuration of the database and authentication    

Step 3 - Open the settings.py in your project and add the below one in place of the existing DATABASES (This will be pointing to sqllite3 by default). I have used postgres in this case.


    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': '<Name of the database>',
            'USER': '<Name of the user having access to db>',
            'PASSWORD': '<PASSWORD>',
            'HOST': '<Server name or ipaddress>',
            'PORT': '<Port number, if it is default it can be left blank>',
        }
    }

   
Step 4 - Now, lets move the authentication tables into the database. This is done in 3 steps:
    a) To allow django to make scripts for migration using the command -
        python manage.py makemigrations
    b) To make the changes into the database based on the configurations made in Step 3 -
        python manage.py migrate
    Once this is done, login into the database and ensure that the new tables and functions (in case of postgres) appear in the database.
    c) To create a superuser who has complete access to the entire db and application.
        python manage.py createsuperuser
        This will prompt you for userid and password along with confirmation of password.
       
    Once you add this, start the app: this usually will be http://127.0.0.1:8000/admin
    login using the superuser created above and it should allow you to login.



Django App Settings:

Step 5 - Add the below to your INSTALLED_APPS

    'webs',  -> This will be the app you just created in step 2
    'rest_framework.authtoken', -> This is used for authentication
    'rest_framework_jwt',  -> This is used for authentication via JSON Web Tokens (JWT)

Your INSTALLED_APPS should look like the below:


        INSTALLED_APPS = [
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'rest_framework',
            'webs',
            'rest_framework.authtoken',
            'rest_framework_jwt',
        ]


Step 6 - In order to use JWT based authentication you need to add REST_FRAMEWORK. Please ensure the order is maintained as shown in the snippet below:
        REST_FRAMEWORK = {
            'DEFAULT_AUTHENTICATION_CLASSES': (
                'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
                'rest_framework.authentication.TokenAuthentication',
                'rest_framework.authentication.BasicAuthentication',
                'rest_framework.authentication.SessionAuthentication',
            ),
            'DEFAULT_PERMISSION_CLASSES': (
                'rest_framework.permissions.IsAuthenticated',
                #'rest_framework.permissions.AllowAny', (To be used instead of IsAuthenticated if you do not want any authentication for the web API)
            )
        }


Step 7 - Add the below for JWT settings:

       
JWT_AUTH = {
            'JWT_ENCODE_HANDLER':'rest_framework_jwt.utils.jwt_encode_handler',
            'JWT_DECODE_HANDLER':'rest_framework_jwt.utils.jwt_decode_handler',
            'JWT_PAYLOAD_HANDLER':'rest_framework_jwt.utils.jwt_payload_handler',
            'JWT_PAYLOAD_GET_USER_ID_HANDLER':'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
            'JWT_RESPONSE_PAYLOAD_HANDLER':'rest_framework_jwt.utils.jwt_response_payload_handler',
            'JWT_SECRET_KEY': SECRET_KEY,
            'JWT_GET_USER_SECRET_KEY': None,
            'JWT_PUBLIC_KEY': None,
            'JWT_PRIVATE_KEY': None,
            'JWT_ALGORITHM': 'HS256',
            'JWT_VERIFY': True,
            'JWT_VERIFY_EXPIRATION': True,
            'JWT_LEEWAY': 0,
            'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
            'JWT_AUDIENCE': None,
            'JWT_ISSUER': None,
            'JWT_ALLOW_REFRESH': True,
            'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
            'JWT_AUTH_HEADER_PREFIX': ('JWT','Bearer'),
            'JWT_AUTH_COOKIE': None,
        }

       
Step 8 - Setting up urls in the project to make it understand the app which you have installed.

        url(r'^webs/',include('webs.urls')),
       
        Your urls.py in the main project file should look like:

       
        from django.conf.urls import url, include
        from django.contrib import admin

        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^webs/',include('webs.urls')),
        ]

       

Step 9 - Setting up the app urls for authentication related tasks
       
        imports which need to be added:

       
        from rest_framework_jwt.views import obtain_jwt_token
        from rest_framework_jwt.views import refresh_jwt_token
        from rest_framework_jwt.views import verify_jwt_token

       
        urls which need to be added within urlpatterns -
       
        url(r'^auth-jwt/', obtain_jwt_token),
        url(r'^auth-jwt-refresh/', refresh_jwt_token),
        url(r'^auth-jwt-verify/', verify_jwt_token),

       
To test the above application -

1) use http://127.0.0.1:8000/admin and provide userid and password used for superadmin, it should allow you to login.
2) To test the JWT part, install postman plugin in chrome, then provide the url along with User ID and password used for super admin in header and you can see the token as shown in the image below. 




In the up coming posts, I shall cover
1) Creating CRUD rest api using code first approach.
2) Creating CRUD rest api using database first approach using sqlalchemy
3) Creating CRUD rest api using stored procedure / functions in database and not using any ORM.

No comments:

Post a Comment