Open Danfs64 opened 11 months ago
thanks for the detailed explanation. could you also add am example (mock) view that shows this problem? it is easier to talk about.
Sure thing!
class BookView(APIView):
authentication_classes = [OAuth2Authentication]
permission_classes = [TokenHasScope1 | TokenHasScope2]
def get(self, request):
return Response({"message": "success"}, 200)
where TokenHasScope1
and 2 are like:
class TokenHasScope1(TokenHasScope):
def get_scopes(self, request, view):
return ['scope1']
If you're interested, I'd like to make a PR fixing this, although I'm not sure what is the expected behaviour on ORs: adding the Authorization header if either side of a OR has a TokenHasScope, or if both sides should be TokenHasScope. An AND would definitely require just one side having a TokenHasScope.
Describe the bug If I setup a Django project using ClientCredentials Oauth2 for authentication, and have a view using
oauth2_provider.contrib.rest_framework.OAuth2Authentication
as authentication_class and a permission class that is, or specializes,oauth2_provider.contrib.rest_framework.TokenHasScope
, I can authorize myself using SwaggerUI, and the request will properly have the Authorization header.However, if my permission_class is a logic OR ( | ) between 2 permissions, of which at least one is or specializes from
oauth2_provider.contrib.rest_framework.TokenHasScope
, authorizing myself through SwaggerUI won't result in the Authorization header being passed when I make the request. This behavior happens even if both permissions are instances ofTokenHasScope
.To Reproduce Just have any view's permission_class be a OR containing a
TokenHasScope
specialization. I can easily upload a repository demonstrating it, if you guys want.Expected behavior Since a OR containing a
TokenHasScope
Permission will still need the Authorization header, it should be passed when doing the request using SwaggerUI, after using the Authorize button.Notes I think I tracked down this behavior all the way to
drf_spectacular.contrib.django_oauth_toolkit.DjangoOAuthToolkitScheme.get_security_requirement()
. I think that this function should also check if a permission is an instance ofrest_framework.permissions.OR
(I don't know how to treatAND
orNOT
) and, if so, recursively verify each side of it.