Following with previous post we can go now to authentication and permissions.
Everything is well documented in Django Rest Framework web site:
They even have this beautiful tutorial: http://www.django-rest-framework.org/tutorial/quickstart/
However I will explain a litte bit in the basic but pay attention to a corner case: when we don't need to authenticate but at the same time you need to be sure that only from specific IPs the API can be used.
Suppose you need some other external partner to post to your APIs. In our case we need to receive leads from Boberdoo(a Lead Distribution system) and receive information from Salesforce too.
We decided we should have a model with IPs that we should allow in our system and we have some APIs using a custom permission class that will reject the request.
Our first move was to install ipcalc:
pip instal ipcalc==1.1.3
Then we created a model called TrustedIP
network_help_txt = 'Insert one ip address or a network mask (i.e. 10.1.1.0/24) to include a whole network.'
title = models.CharField('Title', max_length=100)
network = models.CharField('IP network', max_length=18, help_text=network_help_txt)
verbose_name = 'IP mask to include'
verbose_name_plural = 'IP masks to include'
> ./manage.py makemigrations
> ./manage.py migrate
We added the model to the admin:
list_display = ('title', 'network', )
search_fields = ('title', 'network')
In order to test, you must insert IPs to the table so we can see that is working.
We are ready now to create custom permission class:
from rest_framework import permissions
from . import models
ip = req.META['REMOTE_ADDR']
# forwarded proxy fix for proxy passing setups
if (not ip or ip == '127.0.0.1') and req.META.has_key('HTTP_X_FORWARDED_FOR'):
ip = req.META['HTTP_X_FORWARDED_FOR']
def is_ip_in_nets(ip, nets):
for net in nets:
if ip in net:
Global permission check for white listed IPs.
def has_permission(self, request, view):
request_ip = get_ip(request)
trusted_ips = [i.get_network() for i in models.TrustedIP.objects.only('network')]
return is_ip_in_nets(request_ip, trusted_ips)
As you can see you only have to inherit from permissions.BasePermission and create has_permission method.
But we still are missing the link between the view and the permission class. You can do that using rest framework decorators for example.
from rest_framework.decorators import permission_classes
model = Lead
serializer_class = LeadSerializer
queryset = Lead.objects.all()
Finally, after these little tricks we are ready to insert Boberdoo and Salesforce IPs into TrustedIP model and the API start working smoothly.
Let me know if it was helpful.
Thanks.Share on Twitter Share on Facebook