Lets say the API endpoint to GET a list of users is this
/api_auth/user/
But I want to restrict access to this list only to people with an api_key
/api_auth/user/?access_key=$omeRandomHash3252532
How do I implement such an access system using the Django Rest Framework?
Should I use Permissions to implement this?
This is not supported out of the box for django-rest-framework, however it can easily be implemented:
If you take a look at http://www.django-rest-framework.org/api-guide/authentication/ you'll see an Example of a custom authentication method. Baased on that, you'll need to implement something like this:
from django.contrib.auth.models import User from rest_framework import authentication from rest_framework import exceptions class APIKeyAuthentication(authentication.BaseAuthentication): def authenticate(self, request): api_key = request.GET.get('api_key') if not api_key: return None try: user = get_user_from_api_key(api_key) except User.DoesNotExist: raise exceptions.AuthenticationFailed('No user for API KEY') return (user, None)
The APIKeyAuthentication
should be put on an authentication.py module and be configured with REST_FRAMEWORK
setting on settings.py, like this
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'my_custom_package.authentication.APIKeyAuthentication', ) }
Now, what the above does is that it checks if the api_key
parameter is present (if not it will return None to check if the request can be authenticated differently -- if you don't want to check any other authentication classes then just raise an exceptions.AuthenticationFailed
exception like we do when we dont find the user below. Now, we need to implement a get_user_from_api_key
function that will return a User
instance from an API_KEY. If the user that is correlated with the passed api_key is found then it will be returned, if not an exceptions.AuthenticationFailed
exception will be thrown.
Concerning the get_user_from_api_key
function, its implementation depends on your requirements. For instance, if you want to create a new api key for each user, you should create an APIKey
model that will have an api_key
CharField
and a ForeignKey
to the User
that has this api_key
. The get_user_from_api_key
function then will query the APIKey
model to get the user with the provided api_key
.
Update
If you want to use the django-rest-framework permissions instead of the authentication, you may create an APIKeyPermission
class like this:
from rest_framework import permissions class APIKeyPermission(permissions.BasePermission): def has_permission(self, request, view): api_key = request.GET.get('api_key') return check_permission(api_key, request)
Where the check_permission
function will check if the api_key passed has permissions for that specific request. Please check the examples on http://www.django-rest-framework.org/api-guide/permissions/ for more info - you may instead choose to implement has_object_permission
to implement object-level permissions instead of view-level permissions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With