Problem with authorization through SwaggerUI
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 of TokenHasScope.
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 of rest_framework.permissions.OR (I don't know how to treat AND or NOT) and, if so, recursively verify each side of it.
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.