I'm trying to write my basic custom authentication for Django REST Framework. I have the following auth backend:
class JoeAuth(authentication.BaseAuthentication):
def authenticate(self, request):
username = request.META.get('HTTP_X_FORWARDED_USER')
if not username:
return
try:
user = User.objects.get(krb_name=username, active=True).name
except User.DoesNotExist:
raise PermissionDenied('Unauthorized user')
return (user, None)
Accompanied with a view:
@api_view()
def hello(request):
return Response(data='hello')
And of course enabled in settings.py
:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'helloworld.auth.JoeAuth',
)
}
Now, if a request comes in and does not specify the HTTP_X_FORWARDED_USER
header, the authenticate()
function returns None
. According so DRF docs:
To implement a custom authentication scheme, subclass BaseAuthentication and override the .authenticate(self, request) method. The method should return a two-tuple of (user, auth) if authentication succeeds, or None otherwise.
In some circumstances instead of returning None, you may want to raise an AuthenticationFailed exception from the .authenticate() method.
A None
means authentication failed and should ideally return 401 or 403. However, in practice this doesn't seem to be the case. A request without the HTTP_X_FORWARDED_USER
is simply allowed and 200 is returned:
$ http http://127.0.0.1:8000/ HTTP_X_FORWARDED_USER:joe
HTTP/1.1 200 OK
"hello"
$ http http://127.0.0.1:8000/
HTTP/1.1 200 OK
"hello"
Am I misunderstanding the documentation in the sense that a None
is considered a successful authentication attempt?