Django REST framework introduction Part 2: Auth, Token and Permissions
Tags: python, django, beginners, turorial
Published: 2021-09-06 11:43:29

---
title: Django REST framework introduction Part 2: Auth, Token and Permissions
published: true
description: How to create a REST API with Python and Django step by step 
tags: python, django, beginner, turorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9m4bvoeczt01zrr1ator.png
series: Django REST-Framework
canonical_url: https://eric-the-coder.com/django-rest-framework-introduction-part-2-auth-token-and-permissions
---

A web developer worthy of the name must be able to create a REST API. 

In part 1 we help you understand everything there is to know to build your first API using the Python language and the Django REST Framework.

In part 2 we will secure our API. After all, not every action (ex. DELETE) can be authorized. We will add REST Framework authentication, token and permissions to our API.

To not miss anything, click Follow and/or follow me on Twitter: https://twitter.com/EricTheCoder_

# What is the next step ?
The next step is to secure our API.

Until now, anyone who knows our URL can send a read, create, update, and delete request to our API. Not good!

So the goal being to allow create, update and the deletion of
a post only for authenticated user and only allow those to update and delete their own posts

In order to determine what the identity of the request user is, we will also have to add an authentication (login) to our API

# How authentication work in REST Framework?

There are several ways to manage authentication with REST-Framework.

In this article, I will show you one that is often used: Token Authentication

## What is Token Authentication?
Token authentication allows users to verify their identity, and in return receive a unique access token. During the life of the token, users then access the API that the token has been issued for, rather than having to re-enter credentials each time they go back to the same API.

Auth tokens work like a stamped ticket. The user retains access as long as the token remains valid. 

Token-based authentication is different from traditional password-based or server-based authentication techniques. Tokens offer a second layer of security, and administrators have detailed control over each action and transaction. 

In short, it means that when you will make a login request (ex: api/login), our API will give you back a Token.

It will then be possible to use this Token to have access to certain action protected by the API (ex: DELETE api/posts/1)

### How to use the Token?
To use the Token, In the request header, you need to add an 'Authorization' key:
```
'Authorization' : 'Token 622af924b5e828dd35dd6'
```

Here a JavaScript fetch() example to delete post no 3
```javascript
const token = 'YOUR_TOKEN_HERE';
const response = await fetch('api/posts/3', {
    method: 'DELETE',
    headers: {
      Authorization: `Token ${token}`
    },
  });
```

# Implement a Token base auth in REST-Framework
To implement this pattern in our API we need 2 things:

First, we need to create a login API endpoint (ex: api/login). That login will authenticate users and return the Token.

Second, we need to modify our update and delete API endpoint to allow only an authenticated user to perform those actions on their own posts. This will be implemented with the Authorization  and Permissions class in REST-Framework
 

## Create a Login endpoint
That part will be pretty easy because REST-Framework already have a login view pre-created for us.

In posts application folder, open views.py and add this code
```python
from rest_framework.authtoken.views import ObtainAuthToken 
from rest_framework.settings import api_settings

class UserLoginApiView(ObtainAuthToken):
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
```
Noted, for simplicity, I only show code related to the Login view. 

This UserLoginAPIView inherit from ObtainAuthToken that contain all the code to create the login view and all the methods to authenticate a user and return a Token.

Next we need to create a URL that point to this login view

Open posts application urls.py and add this URL path:
```python
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet, UserLoginApiView

router = DefaultRouter()
router.register('posts', PostViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('login/', UserLoginApiView.as_view()),
]
```

Finally, in order to use the REST-Framework auth libraries, we need to add a reference to 'rest_framework.authtoken' to our project settings.py files.
```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'posts',
    'rest_framework.authtoken',
]
```
And re-run the 'migrate' terminal command
```bash
python manage.py migrate
```
That action will create the database table to support authtoken functionalities

If everything code right, you can start your server and visit api/login 
```bash
python manage.py runserver
```
![Screen Shot 2021-09-03 at 12.09.10 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630685480035/dM8ByXLl8.png)
You can use your superuser credentials (we create in part one) to login.

You can also add users with the admin panel if needed.

Once logged in, the API will return you a Token

![Screen Shot 2021-09-03 at 12.11.01 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630685525396/6QWezrTyP.png)

## Add Authorization and Permissions to Update and Delete API endpoint 
Here the objective is to limit access to our API. In particular, the Update and Delete actions. So only users who are authenticated will be able to perform these actions.

But we also need to check if the authenticated user is the author of the post. Only author of their own posts will be able to do Update and Delete request.

## Permissions class
REST-Framework has a class to manage permissions. We can create one and associated the permissions class to our API view

Create a new file under posts application folder and name it permissions.py. Inside that file add the following code:
```python
from rest_framework import permissions

class UpdateOwnProfile(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        
        return obj.user.id == request.user.id
```
If the action to be executed is considered "safe" (request.method in permissions.SAFE_METHODS), it can be executed (return True)

If on the other hand, the action is not safe (Create, Update and Delete action) then it checks that the authenticated user and are the author of the post are the same (obj.user.id == request.user.id) 

## Bind permissions to our API
Now that our Permission object is created, we can bind it to our API.

In posts application folder, open views.py and add this code:
```python
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticatedOrReadOnly

from .models import Post
from .serializers import PostSerializer
from .permissions import UpdateOwnProfile

class PostViewSet(viewsets.ModelViewSet):
    serializer_class = PostSerializer
    authentication_classes = (TokenAuthentication,)
    permission_classes = (
        UpdateOwnProfile,
        IsAuthenticatedOrReadOnly,
    )
    queryset = Post.objects.all()
```
We add 2 thing here. First we set the authetification_classes to TokenAuthetification and then we set our permissions_classes to our custom permission class. The isAuthenticatedOrReadOnly will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the "safe" methods like GET (read post).

# Test your API
Our API is now secure, it's time to give it a try.

This time we cannot test our API in the browser because for auth we need a way to send the Token with the request.

We will use an API testing application.  Postman is one of the most use app but today I will use a VSCode extension call Thunder Client. It's a light version of Postman easy to install and use

## Install Thunder Client
From VSCode, go to extension, find and then install the Thunder Client application.

![Screen Shot 2021-09-03 at 1.23.35 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630700311629/p3C5ldzD2.png)

Once install, open the app and click on 'New Request' button and type the API URL you want to test (ex: api/posts) then click 'Send' and the response would appear in the right portion of the screen

![Screen Shot 2021-09-03 at 1.26.11 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630700423487/fs7Kk-aar.png)

## Login and Token example
To login you need to do a POST request with credentials to api/login. First, click the 'New Request' button, choose POST from the request type dropdown, type the request URL (ex: api/login/), click the Body tab and add the credential in JSON format:
```json
{
    "username": "ericthecoder",
    "password": "yourpassword"
}
```
Click 'Send' and the response section on the right should display the received Token
![Screen Shot 2021-09-03 at 1.43.40 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630700564087/41uFQpwhn.png)

## Create a new Post
Now that we have our Token, we can do action that required permissions. So let's create a new Post.

Click 'New Request', choose POST from dropdown and type the create post URL (ex: api/posts/). Click the Body tab and enter the create post JSON Content:
```json
{
    "title": "My First Blog Title",
    "body": "My first Blog body Content",
    "user": 1
}
```
Click send, and the API will return a 401 Unauthorized message. That's normal, since we did not send the Token with the request.
![Screen Shot 2021-09-03 at 4.45.20 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630701932795/EKLef-iqc.png)

To do so, click on Headers tab and add the Authorization key and Token
![Screen Shot 2021-09-03 at 1.54.49 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630701832037/ApHnuluJu.png)

Click 'Send' and now the Post should be created with success
![Screen Shot 2021-09-03 at 1.54.36 PM.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630701977930/vZLDaygrG.png)

# Test all API endpoints
With your Token now in hand, you can now test all our API endpoint:
```bash
POST api/login/ (login with credentials)

GET api/posts (Read all post)
POST api/posts/ (Create a new post)

GET api/posts/1/ (Read a specific Post)
PUT api/posts/1/ (Update a specific Post)
PATCH api/posts/1/ (Partial Update a specific Post)
DELETE api/posts/1/ (Delete a specific Post)
```

### End of part 2
That's all for today. You now have a secure API, in the next part, we will discuss search, pagination and image upload.

To not miss anything, click Follow and/or also follow me on Twitter: https://twitter.com/EricTheCoder_