Authentication and Permissions¶
Note
Django-REST-Framework’s Authentication and Django-REST-Framework’s Permissions pattern was referenced for this implementation.
Insanic takes Sanic’s Class-Based Views and extends it to handle authentication and check for permissions.
To register authentication and permissions, we must first create or use the general authentication and permissions provided by Insanic.
Insanic only provides JWT
authentication because
it is most suitable for microservices. Session based implementations
require state and synchronizing states across services introduces
complexity. You might wonder, what about verifying if the token
with its respective key requires state? In my humble opinion,
one of the better practices, is to have an API Gateway that will handle the
JWT verification for you. This way you don’t need to verify the request
in the application, and only use the JWT payload for creating request
context.
Views¶
from sanic.response import json
from insanic import permissions, authentication
from insanic.views import InsanicView
class GottaGoInsanelyFastView(InsanicView):
permission_classes = (permissions.AllowAny,)
authentication_classes = (
authentication.JSONWebTokenAuthentication,
)
async def get(self, request, *args, **kwargs):
return json({"how fast?": "insanely fast"})
This will authenticate the request with the declared
authentication_classes
, in this case the
JSONWebTokenAuthentication
. The authentication class will decode the
jwt
token from the headers and sets the user
attribute on the request object.
Then the permission_classes
are iterated through to
determine this user has the necessary permissions to
access this view. In this case AllowAny
allows everyone
to request this view.
JSONWebTokenAuthentication¶
The general flow for the authentication class is as follows:
1. Get the authorization header from the request object and compares the prefix it to the JWT_AUTH_HEADER_PREFIX defined in the settings.
Decode the
JWT
token. While decoding the following exceptions may occurException if it determines the signature has expired
Exception when decoding signature
Exception if an Invalid token
3. Lastly, deems the user authenticated and sets the user to the
request
object.
ServiceJWTAuthentication¶
The ServiceJWTAuthentication
verifies the JWT
was from
another Insanic service and sets the service to the request object.
When making intra service requests, both the service and user properties become available from the request object after authentication.
Permissions¶
There are couple general usage permission classes in insanic
AllowAny
IsAuthenticated
IsAdminUser
IsAuthenticatedOrReadOnly
IsOwnerOrAdmin
IsServiceOnly
Basic flow for permissions is as follows
Iterates though the list of permission_classes as defined in the view.
Calls the has_permission method of the permission class
If ALL result in True the request is valid
If any is False, raises
PermissionDenied
error.
View the insanic.permissions API Reference for more details.
Custom Permissions¶
If Insanic’s permissions are not enough, the developer has option
to create their own custom permission. However, it should inherit
the BasePermission
class and have it’s own has_permission
method implemented.
# permissions.py
from insanic.permissions import BasePermission
class IsReadOrStaff(BasePermission):
async def has_permission(self, request, view):
if request.method.upper() in ['GET']:
return True
user = request.user
if user['is_staff']:
return True
return False