Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7k
Description
Hey guys!
Such a situation has arisen. When I tried to execute a request in my API (being unauthorized), I received a corresponding message stating that I could not do this without authorization.
But I noticed that the text of the message in the response is from error 401, and the error code is from 403.
DRF versiondjangorestframework >= 3.14, < 3.15
.
Problem description:
The whole point is thatBasicAuthentication
has an implementation of theauthenticate_header
method (this method is not implemented in theSessionAuthentication
class, it simply inherits fromBaseAuthentication'). And at the key moment of the program execution, the
APIView class (
ViewSetinherits from
APIView) and the
get_authenticate_headermethod receive a tuple of the
BasicAuthenticationand
SessionAuthenticationelements/classes passed to
DEFAULT_AUTHENTICATION_CLASSES (settings.py).
Next, the first class from this tuple is strictly taken, and in turn the methodauthenticate_header
is used (in the case of theBasicAuthentication
class, the specific value is returned, and theSessionAuthentication
class returns `None').
Example (Response):
CodeDetails403 Error: UnauthorizedUndocumented
{"type":"client_error","errors": [ {"code":"not_authenticated","detail":"Authentication credentials were not provided.","attr":null } ]}
Is this a mistake or was it originally intended that way (and can it be fixed at the library level)?
Here's how I managed to solve my problem, but it looks like a crutch:
classMyViewSet(ViewSet):defdispatch(self,request,*args,**kwargs):""" `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """self.args=argsself.kwargs=kwargsrequest=self.initialize_request(request,*args,**kwargs)self.request=requestself.headers=self.default_response_headers# deprecate?try:self.initial(request,*args,**kwargs)print('# dispatch `initial`')# Get the appropriate handler methodifrequest.method.lower()inself.http_method_names:handler=getattr(self,request.method.lower(),self.http_method_not_allowed)else:handler=self.http_method_not_allowedresponse=handler(request,*args,**kwargs)print(f'# dispatch `initial`: response:{response}')exceptExceptionasexc:response=self.handle_exception(exc)# BEGIN# This code --->ifresponse.status_code==status.HTTP_403_FORBIDDEN:ifresponse.data:errors=response.data['errors']iferrors:iferrors[0]['detail']==drf_exceptions.NotAuthenticated.default_detail:response.status_code=status.HTTP_401_UNAUTHORIZED# END <---self.response=self.finalize_response(request,response,*args,**kwargs)returnself.response