Merge pull request #1938 from SchrodingersGat/auth-bug

Fix bug when using token based auth
This commit is contained in:
Oliver 2021-08-10 23:24:01 +10:00 committed by GitHub
commit 1bf2a3e23f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -21,28 +21,15 @@ class AuthRequiredMiddleware(object):
assert hasattr(request, 'user')
response = self.get_response(request)
# API requests are handled by the DRF library
if request.path_info.startswith('/api/'):
return self.get_response(request)
if not request.user.is_authenticated:
"""
Normally, a web-based session would use csrftoken based authentication.
However when running an external application (e.g. the InvenTree app),
we wish to use token-based auth to grab media files.
So, we will allow token-based authentication but ONLY for the /media/ directory.
What problem is this solving?
- The InvenTree mobile app does not use csrf token auth
- Token auth is used by the Django REST framework, but that is under the /api/ endpoint
- Media files (e.g. Part images) are required to be served to the app
- We do not want to make /media/ files accessible without login!
There is PROBABLY a better way of going about this?
a) Allow token-based authentication against a user?
b) Serve /media/ files in a duplicate location e.g. /api/media/ ?
c) Is there a "standard" way of solving this problem?
My [google|stackoverflow]-fu has failed me. So this hack has been created.
However when running an external application (e.g. the InvenTree app or Python library),
we must validate the user token manually.
"""
authorized = False
@ -56,20 +43,23 @@ class AuthRequiredMiddleware(object):
elif request.path_info.startswith('/accounts/'):
authorized = True
elif 'Authorization' in request.headers.keys():
auth = request.headers['Authorization'].strip()
elif 'Authorization' in request.headers.keys() or 'authorization' in request.headers.keys():
auth = request.headers.get('Authorization', request.headers.get('authorization')).strip()
if auth.startswith('Token') and len(auth.split()) == 2:
token = auth.split()[1]
if auth.lower().startswith('token') and len(auth.split()) == 2:
token_key = auth.split()[1]
# Does the provided token match a valid user?
if Token.objects.filter(key=token).exists():
try:
token = Token.objects.get(key=token_key)
allowed = ['/api/', '/media/']
# Provide the user information to the request
request.user = token.user
authorized = True
# Only allow token-auth for /media/ or /static/ dirs!
if any([request.path_info.startswith(a) for a in allowed]):
authorized = True
except Token.DoesNotExist:
logger.warning(f"Access denied for unknown token {token_key}")
pass
# No authorization was found for the request
if not authorized:
@ -92,8 +82,7 @@ class AuthRequiredMiddleware(object):
return redirect('%s?next=%s' % (reverse_lazy('login'), request.path))
# Code to be executed for each request/response after
# the view is called.
response = self.get_response(request)
return response