I am trying to implement Auth0 JWT-based authentication in my Django REST API using the django-rest-framework. I know that there is a JWT library available for the REST framework, and I have tried using it because the official Auth0 twitter account mentioned that it should work well with auth0 + Django.
EDIT: I am using the official auth0 python api guide for this code. It's written for flask, but I figured I could just port it to Django seeing as they work similarly.
Now, that didn't work out how I wanted to, so I am trying to write my own login_required
decorater for a view. The code I have here is as following:
def auth_required(f):def wrap(request, *args, **kwargs):auth = request.META.get('HTTP_AUTHORIZATION', None)if not auth:return authenticate({'code': 'authorization_header_missing', 'description': 'Authorization header is expected'})parts = auth.split()if parts[0].lower() != 'bearer':return authenticate({'code': 'invalid_header', 'description': 'Authorization header must start with Bearer'})elif len(parts) == 1:return authenticate({'code': 'invalid_header', 'description': 'Token not found'})elif len(parts) > 2:return authenticate({'code': 'invalid_header', 'description': 'Authorization header must be Bearer + \s + token'})token = parts[1]try:payload = jwt.decode(token,base64.b64decode(SECRET.replace("_","/").replace("-","+")),audience=CLIENT_ID,)except jwt.ExpiredSignature:return authenticate({'code': 'token_expired', 'description': 'token is expired'})except jwt.InvalidAudienceError:return authenticate({'code': 'invalid_audience', 'description': 'incorrect audience, expected: ' + CLIENT_ID})except jwt.DecodeError:return authenticate({'code': 'token_invalid_signature', 'description': 'token signature is invalid'})return f(request, *args, **kwargs)wrap.__doc__=f.__doc__wrap.__name__=f.__name__return wrap
Now, the authenticate()
is basically my custom implementation for Jsonify()
which is used in the documentation of Auth0 for Python API's. I have verified that this works, so that's not a problem.
SECRET
is my Auth0 secret, encoded in base64 (any other keys failed to decode)
CLIENT_ID
is my Auth0 client ID which is used as the audience, according to the Auth0 documentation.
I am using the Angular seed project on the frontend-side, and I have verified that the token indeed gets sent with the request, and I have verified that it's the exact same token that gets stored in the token
variable on the backend.
When jwt.decode()
is called, it will trigger the jwt.DecodeError
every time, and I have been spending countless hours trying to fix this, but I am absolutely stunned as to why this is not working. I have tried setting the JWT options to false, specifically the verify signature one. This worked, but I assume that it's unsafe to disable the verifying of the JWT signature.
I cannot figure out why this is failing me, I have tried this same code without it being in a decorator and it does the same thing. The view which is decorated is just an empty view which returns an OK HttpResponse.
Tldr; Using Django-REST + Auth0 JWT -- jwt.decode()
will not work no matter what I do.
EDIT2: It's worth mentioning I am corsheaders
for django-rest which allows me to make cross-domain requests. I have also followed the tip at the bottom of the Python API guide from Auth0 to uninstall and reinstall the JWT library, but this did nothing for me.
Am I overlooking something, is this implementation plain unsecure or do you have any better way to implement Auth0 with Django? Please let me know, this problem is causing me nightmares.