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]