Created
June 2, 2017 13:32
-
-
Save elnygren/618d8b34c318a5bbce61c6997aea807e to your computer and use it in GitHub Desktop.
Django Rest Framework custom authorization header
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
[API] uses the DRF TokenAuthentication with one customisation: | |
Token is read from 'X-Mirror-Authorization' instead of the 'Authorization' header. | |
Unfortunately, this is not a simple setting in DRF so we need to override the | |
contents of get_authorization_header and TokenAuthentication.authenticate. | |
You may refer to: | |
https://github.com/encode/django-rest-framework/blob/master/rest_framework/authentication.py | |
Note: we could've monkeypatched get_authorization_header, but this solution | |
is a bit safer (although more verbose). | |
""" | |
from django.utils.six import text_type | |
from rest_framework.authentication import TokenAuthentication | |
from rest_framework import HTTP_HEADER_ENCODING, exceptions | |
# should this be in settings.py ? | |
AUTHORIZATION_HEADER = 'HTTP_X_CUSTOM_AUTHORIZATION' | |
def get_authorization_header(request): | |
""" | |
Return request's 'X-Mirror-Authorization:' header, as a bytestring. | |
Hide some test client ickyness where the header can be unicode. | |
""" | |
auth = request.META.get(AUTHORIZATION_HEADER, b'') | |
if isinstance(auth, text_type): | |
# Work around django test client oddness | |
auth = auth.encode(HTTP_HEADER_ENCODING) | |
return auth | |
class XMirrorTokenAuthentication(TokenAuthentication): | |
"""DRF TokenAuthentication that uses X-Mirror-Authorization header.""" | |
def authenticate(self, request): | |
"""Authenticate request. | |
Identical to DRF's implementation except we use a different | |
`get_authorization_header` function | |
""" | |
auth = get_authorization_header(request).split() | |
if not auth or auth[0].lower() != self.keyword.lower().encode(): | |
return None | |
if len(auth) == 1: | |
msg = _('Invalid token header. No credentials provided.') | |
raise exceptions.AuthenticationFailed(msg) | |
elif len(auth) > 2: | |
msg = _('Invalid token header. Token string should not contain spaces.') | |
raise exceptions.AuthenticationFailed(msg) | |
try: | |
token = auth[1].decode() | |
except UnicodeError: | |
msg = _('Invalid token header. Token string should not contain invalid characters.') | |
raise exceptions.AuthenticationFailed(msg) | |
return self.authenticate_credentials(token) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment