API Request Signing in Django (2)

Adding a permission layer

Ahmed Hosny
Elements blog
2 min readSep 7, 2018

--

This article is the second and final part on API request using Django Rest Framework. In the first part we explained what API signing is, why and how to apply it in your Django projects. Basically, we implemented the API signing functionality as a middleware in Django. You can check and review the first part here.

Photo by Kai Pilger on Unsplash

Sometimes you want to have more control on your endpoints, so you may decide that for some endpoints you want to bypass the API signature. Also, maybe you want this signature-check to be done not in a middleware layer, but in the permission layer instead.

Django Rest Framework Permission Class

So, you can have more control on when API signing should be applied in different ways; you can implement it as a decorator class or function or you may implement it as class that is only invoked whenever you explicitly want. One of the ways also is to implement it in the permission layer provided by the framework you use. Since Django Rest Framework one of the mostly used frameworks to build API in Django, I’ll present how we can implement the API signing in DRF permission layer.

Create a file called app/signing_permission.py which contains a custom DRF permission class. Actually it is the same as the middleware, but instead of implementing the __call__ method, we are implementing a has_permission method in a class inherited from BasePermission:

from rest_framework.permissions import BasePermission
class APISigningPermission(BasePermission):
def has_permission(self, request, *args, **kwargs):
"""Validate signed requests."""
api_signature = request.META.get('HTTP_SIGNATURE')
secret = settings.SECRET_KEY
params = [
secret, request.method,
request.path, request.body
]
data = "-".join(params)
data = data.encode('utf-8')
computed_sig = hmac.new(
secret.encode('utf-8'),
msg=data, digestmod=sha256
).digest()
signature = b64encode(computed_sig).decode()
return signature == api_signature

Now, you can apply this permission in all your endpoints in the settings.py ;

REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': {
'app.signing_permission.APISigningPermission',
}
}

You can also add this permission class per DRF view;

from app.signing_permission import APISigningPermission
class APIViewSet(ViewSet):
permission_classes = (APISigningPermission, )
...
...

API Signing for Django and DRF Package

I’ve built a package that letting you doing the API Signing in DRF projects with a matter of some configurations in the settings (drf-simple-api-signing). I highly encourage you to check it, contribute, use and report issues and bugs. Yet, there is a lot that can be enhanced and added to this package, but it will provide you with all you want to start with.

Have some doubts or thoughts to share? Feel free to leave a comment or reach out to me directly on Twitter.

--

--

Ahmed Hosny
Elements blog

I'm a Software Engineer, Tech Philosopher and Backend Developer ⚔️. I love knowledge sharing, helping others and tech debates. Code ⌨️ & Coffee ☕️Addict ☠️.