How the client gets api-key when using tastypie ApiKeyAuthentication?

412 views Asked by At

I am using django-tastypie for REST API and ApiKeyAuthentication for authentication. I have a CreateUserResource in api.py for creating a new user. Now in all the tutorials it is specified that whenever any GET or POST request is done, apikey must be specified. But how does the client receive this apikey?

Is it that while logging in, client is to be authenticated and given an apikey which is to be revoked when the client logs out?

1

There are 1 answers

0
Deepak On

For implementing the basic authentication in a single page app using Tastypie in backend:

  1. Let the user enter his username and password and post it on a resource which is only suppose to handle user authentication.
  2. Let this resource lookup the user and authenticate him, and in response send the "api key".
  3. In frontend catch this "api key" and store it in the local storage.
  4. Now use this "api key" from local storage and send it as header in all your requests. Which in case of tastypie will be "Authorization: ApiKey user_name:generated_api_token"
  5. Now if your resource is using ApiKeyAuthentication it will give error if the token is invalid or not present.
  6. Once the user logs out, delete the key from the local storage.

Such authentication resource might look like:

from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from tastypie.http import HttpUnauthorized, HttpForbidden, HttpNotFound
from tastypie.authentication import ApiKeyAuthentication
from django.conf.urls import url
from tastypie.resources import ModelResource
from tastypie.utils import trailing_slash

class AuthenticationResource(ModelResource):

    def __get_api_key_for_user(self, user):
        return '%s' % (user.api_key.key)

    class Meta:
        resource_name = 'authentication'

    def prepend_urls(self):
        return [
            url(r"^(?P<resource_name>%s)/login%s$" %
                (self._meta.resource_name, trailing_slash()),
                self.wrap_view('login'), name="api_login"),
        ]


    def login(self, request, **kwargs):
        self.method_check(request, allowed=['post'])
        data = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json'))
        username = data.get('username', '')
        password = data.get('password', '')
        user = authenticate(username=username, password=password)
        if user:
            if user.is_active:
                last_login = user.last_login
                login(request, user) // updates the last login
                return self.create_response(request, {
                    'api_key': self.__get_api_key_for_user(user),
                    'last_login': last_login,
                    'username': username
                    })
            else:
                return self.create_response(request, {
                    'success': False,
                    'reason': 'disabled',
                    }, HttpForbidden )
        else:
            return self.create_response(request, {
                'success': False,
                'reason': 'Incorrect user name or password',
                }, HttpUnauthorized )