Authentication and authorisation

Authentication is the process of determining which user is performing an HTTP request, or whether it is being performed by an anonymous client. Authorisation is the process of determining whether a user (be they authenticated or anonymous) is permitted to perform a specific option. When writing authenticators, it should be assumed that the user property of a Django request object is populated, either with an authenticated or anonymous user.

Authentication

The default authenticator is DjangoSessionAuthenticator, which is useful for unit- testing but should be extended in production, as it doesn’t have any tested CSRF protection.

Creating an authenticator

A very simple authenticator might look like this:

from api.authentication import AuthenticatorBase
from django.conf import settings

class APIKeyAuthenticator(AuthenticatorBase):
    def authenticate(self, request):
        return request.GET.get('key') == settings.API_KEY

To use it in all API endpoints, add it to your settings:

API_DEFAULT_AUTHENTICATORS = (
    'myapp.auth.APIKeyAuthenticator',
    ...
)

You can chain multiple authenticators together. The first one that successfully authenticates (returns True) will be used, and all further authenticators will be ignored.

To use your authenticator in an endpoint created via the REST shortcut, you can pass in an authenticators keyword argument, specifying your custom class (as a reference, not a string) in a list or tuple:

urlpatterns = rest(
    List,
    fields=(...),
    authenticators=[APIKeyAuthenticator]
)

To use your authenticator in a view extending ModelViewBase, simply set the authenticators property like so:

class TaskListView(ListView):
    authenticators = [APIKeyAuthenticator]

Bundles

When authorisation is successful, an AuthBundle object is created, which represents the current context of the view (whether it’s a list or detail view), and an arbitrary data property which can store any values. Most commonly, the data dictionary will contain an object key (for detail views), which denotes the object the API user wants to interact with. This can be utilised by the authoriser to determine whether an object- specific permission should be granted.

Authorisation

The default authoriser is GuestReadOnlyOrDjangoUserAuthoriser, which allows anonymous users to read data, but requires that users be logged in and have the correct model permissions in order to perform creations, updates or deletions.

Creating an authoriser

A very simple authoriser might look like this:

from api.authorisation import AuthoriserBase
from api.exceptions import NotAuthenticatedError, ForbiddenError
from django.conf import settings

class SuperUserAuthoriser(AuthoriserBase):
    def authorise(self, request, bundle):
        if request.user.is_anonymous:
            raise NotAuthenticatedError('User is not authenticated.')

        if not request.user.is_superuser:
            raise ForbiddenError('User is not a superuser.')

To use it in all API endpoints, add it to your settings:

API_DEFAULT_AUTHORISERS = (
    'myapp.auth.SuperUserAuthoriser',
    ...
)

You can chain multiple authorisers together. The first one that successfully authenticates (returns without raising a ForbiddenError or NotAuthenticatedError exception) will be used, and all further authorisers will be ignored.

To use your authoriser in an endpoint created via the REST shortcut, you can pass in an authorisers keyword argument, specifying your custom class (as a reference, not a string) in a list or tuple:

urlpatterns = rest(
    List,
    fields=(...),
    authorisers=[SuperUserAuthoriser]
)

To use your authoriser in a view extending ModelViewBase, simply set the authorisers property like so:

class TaskListView(ListView):
    authorisers = [SuperUserAuthoriser]

API reference