Django APIs

axioms-drf-py PyPI

axioms-drf-py is a Python package for Django Rest Framework (DRF) which helps you to secure your DRF APIs using Axioms Authentication and Authorization.

Prerequisite

  • Python 3.7+
  • An Axioms client which can obtain access token after user's authentication and authorization and include obtained access token as bearer in Authorization header of all API request sent to Python/Flask application server.

Install SDK

Install axioms-drf-py in you DRF API project,

pip install axioms-drf-py

Add .env file

Create a .env file in your main Django app and add following configs,

.env
AXIOMS_DOMAIN=<your-axioms-slug>.axioms.io
AXIOMS_AUDIENCE=<your-axioms-resource-identifier-or-endpoint>

Load Config

In your Django project settings.py,

settings.py
import os
import environ
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
)
# reading .env file
environ.Env.read_env()
AXIOMS_DOMAIN=env('AXIOMS_DOMAIN')
AXIOMS_AUDIENCE=env('AXIOMS_AUDIENCE')

Guard Your API Views

Use authentication and permission classes to guard you API views.

ClassDescriptionParameters
axioms_drf.authentication.
HasValidAccessToken
Checks if API request includes a valid bearer access token as authorization header. Check performed includes: token signature validation, expiry datetime validation, and token audience validation.
axioms_drf.permissions.
HasRequiredScopes
Check any of the given scopes included in scope claim of the access token.access_token_scopes; An array of strings as conditional OR representing any of the allowed scope or scopes for the view as parameter. For instance, to check openid or profile pass ['profile', 'openid'] as parameter.
axioms_drf.permissions.
HasRequiredRoles
Check any of the given roles included in roles claim of the access token.access_token_roles; An array of strings as conditional OR representing any of the allowed role or roles for the view as parameter. For instance, to check sample:role1 or sample:role2 roles you will pass ['sample:role1', 'sample:role2'] as parameter.
axioms_drf.permissions.
HasRequiredPermissions
Check any of the given permissions included in permissions claim of the access token.access_token_permissions; An array of strings as conditional OR representing any of the allowed permission or permissions for the view as parameter. For instance, to check sample:create or sample:update permissions you will pass ['sample:create', 'sample:update'] as parameter.

Examples

  • Check openid or profile scope present in the token
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from axioms_drf.authentication import HasValidAccessToken
from axioms_drf.permissions import HasRequiredScopes
class APIPrivate(APIView):
authentication_classes = [HasValidAccessToken]
permission_classes = (HasAccessTokenScopes,)
access_token_scopes = ["openid", "profile"] # noqa
"""
Private API - authentication required
"""
def get(self, request):
return Response(
{"message": "All good. You are authenticated!"}, status=status.HTTP_200_OK
)
  • Check sample:role role present in the token
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from axioms_drf.authentication import HasValidAccessToken
from axioms_drf.permissions import HasAccessTokenRoles
class SampleRole(APIView):
"""
Sample role - create, update, read, delete
"""
authentication_classes = [HasValidAccessToken]
permission_classes = (HasAccessTokenRoles,)
access_token_roles = ["sample:role"] # noqa
def get(self, request):
return Response({"message": "Sample read."}, status=status.HTTP_200_OK,)
def post(self, request):
return Response({"message": "Sample created."}, status=status.HTTP_200_OK,)
def patch(self, request):
return Response({"message": "Sample updated."}, status=status.HTTP_200_OK,)
def delete(self, request):
return Response({"message": "Sample deleted."}, status=status.HTTP_200_OK,)
  • Check permission present in the token at API method level
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from axioms_drf.authentication import HasValidAccessToken
from axioms_drf.permissions import HasAccessTokenPermissions
class SamplePermission(APIView):
"""
Sample permission applied to method level
"""
authentication_classes = [HasValidAccessToken]
permission_classes = (HasAccessTokenPermissions,)
@property
def access_token_permissions(self):
method_permissions = {
'GET': ["sample:read"] ,
'POST': ["sample:create"],
'PATCH': ["sample:update"],
'DELETE': ["sample:delete"]
}
return method_permissions[self.request.method]
def get(self, request):
return Response({"message": "Sample read."}, status=status.HTTP_200_OK,)
def post(self, request):
return Response({"message": "Sample created."}, status=status.HTTP_200_OK,)
def patch(self, request):
return Response({"message": "Sample updated."}, status=status.HTTP_200_OK,)
def delete(self, request):
return Response({"message": "Sample deleted."}, status=status.HTTP_200_OK,)

DRF Sample

To see a complete working example download DRF sample from our Github repository or simply deploy to Heroku by clicking following button. You will need to provide Axioms domain and Axioms audience to complete deployment.

Deploy