Welcome to Django Auth Functional’s documentation!

What is this?

This library provides a set of decorators for working with authentication and authorization. These decorators can be used to decorate plain functions or method in class-based views and you can decide what http response you want to return in the cases where the authentication/authorization failed.

Authenticating your views

In order to authenticate your views all you need to do is decorate your view function:

from auth_functional import authentication
from django.template.response import TemplateResponse

@authentication
def profile(request):
    return TemplateResponse(request, 'user/profile.html')

Or, in case you’re using aa class-base view:

from auth_functional import authentication
from django.template.response import TemplateResponse
from django.views.generic import View

class SomeView(View):
    @authentication
    def get(self, request):
        return TemplateREsponse(request, 'user/profile.html')

With that in place, all the non-authenticated requests are gonna receive an HTTP 401 Unauthorized response.

Requesting client authentication

When you want the user agent to authenticate itself towards the server, you can send a request for authentication using the WWW-Authenticate header. Here’s an example using basic authentication:

from auth_functional import authentication
from django.template.response import TemplateResponse

@authentication(www_authenticate='Basic realm="private area"')
def profile(request):
    return TemplateResponse(request, 'user/profile.html')

Returning a different response

If you want to return a response different than the default HTTP 401 Unauthorized you can provide response_factory callable to the authentication decorator. If the authentication fails your response_factory callable will be called with the same parameters as the view.

from auth_functional import authentication
from django.template.response import TemplateResponse
from django import http


def unauthorized_response(request):
    response = http.HttpResponse(status=401)
    if 'application/json' in request.META.get('HTTP_ACCEPT'):
        response['Content-Type'] = 'application/json; charset=utf-8'
    return response


@authentication(response_factory=unauthorized_response)
def profile(request):
    return TemplateResponse(request, 'user/profile.html')

Authorizing your views

In order to authorize your views all you need to do is decorate your view function with the properly named authorization decorator passing a condition callable that is in charge of allowing or not the access to the resource/controller/store:

from auth_functional import authentication, authorization
from django.template.response import TemplateResponse


def is_staff(request):
    return request.user.is_staff


@authentication
@authorization(condition=is_staff)
def profile(request):
    return TemplateResponse(request, 'user/profile.html')

Or, in case you’re using aa class-base view:

from auth_functional import authentication, authorization
from django.template.response import TemplateResponse
from django.views.generic import View


def is_staff(request):
    return request.user.is_staff


class SomeView(View):
    @authentication
    @authorization(condition=is_staff)
    def get(self, request):
        return TemplateREsponse(request, 'user/profile.html')

With that in place, all the non-authorized requests are gonna receive an HTTP 403 Forbidden response which means that the client doesn’t have access.

Returning a different response

If you want to return a response different than the default HTTP 403 Forbidden you can provide response_factory callable to the authorization decorator. If the authorization fails your response_factory callable will be called with the same parameters as the view.

from auth_functional import authentication, authorization
from django.template.response import TemplateResponse
from django import http


def forbidden_response(request):
    response = http.HttpResponse(status=403)
    if 'application/json' in request.META.get('HTTP_ACCEPT'):
        response['Content-Type'] = 'application/json; charset=utf-8'
    return response


def is_staff(request):
    return request.user.is_staff


@authentication
@authorization(condition=is_staff, response_factory=forbidden_response)
def profile(request):
    return TemplateResponse(request, 'user/profile.html')

Combining multiple conditions

You can combine different condition callables by using the and_, or_ and not_ decorators:

from auth_functional import authentication, authorization, and_, not_
from django.template.response import TemplateResponse
from django import http


def forbidden_response(request):
    response = http.HttpResponse(status=403)
    if 'application/json' in request.META.get('HTTP_ACCEPT'):
        response['Content-Type'] = 'application/json; charset=utf-8'
    return response


def is_staff(request):
    return request.user.is_staff

def is_admin(request):
    return request.user.is_admin

@authentication
@authorization(condition=and_(is_staff, _not(is_admin)), response_factory=forbidden_response)
def profile(request):
    return TemplateResponse(request, 'user/profile.html')

Indices and tables