Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tastypie - Allow read-only perms for unauthenticated users while letting authorized write permissions

I am using Tastypie 0.9.11 and I want to have unauthenticated users be allowed read-only permissions to the API while on the same time, if a user authenticates with an API Key authentication, that user can perform add/change/delete operations on those same models.

Using API Key Authentication + Django Authorization doesn't satisfy requirement 1 (unauthenticated users can't access the API at all). Using No authentication doesn't let users authenticates with an API key (which doesn't satisfy requirement 2).

I bet there is a simple way to achieve this behaviour, please help.

Many thanks, Yuval Cohen

like image 358
Yuval Cohen Avatar asked Sep 03 '12 13:09

Yuval Cohen


1 Answers

There are two things which you need to consider. Authentication and authorization.

First you need to authenticate all users no matter the API key if the request method is GET, for all other methods use the ApiKeyAuthentication.

Now, all authenticated users are subject to authorization. Here you also need to make sure that GET requests are always allowed. Something like this should get you started:

from tastypie.resources import ModelResource
from tastypie.authentication import ApiKeyAuthentication
from tastypie.authorization import DjangoAuthorization

class MyAuthentication(ApiKeyAuthentication):
    """
    Authenticates everyone if the request is GET otherwise performs
    ApiKeyAuthentication.
    """

    def is_authenticated(self, request, **kwargs):
        if request.method == 'GET':
            return True
        return super(MyAuthentication, self).is_authenticated(request, **kwargs)

class MyAuthorization(DjangoAuthorization)
    """
    Authorizes every authenticated user to perform GET, for all others
    performs DjangoAuthorization.
    """

    def is_authorized(self, request, object=None):
        if request.method == 'GET':
            return True
        else:
            return super(MyAuthorization, self).is_authorized(request, object)

class MyResource(ModelResource):

    class Meta:
        authentication = MyAuthentication()
        authorization = MyAuthorization()

So basically your approach for using ApiKeyAuthentication and DjangoAuthorization only lacked special treatment for GET requests.

like image 86
kgr Avatar answered Sep 28 '22 11:09

kgr