Skip to content

Introspection endpoint doesn't require "introspection" scope when used in client-credentials flow #1451

Open
@makulatur

Description

@makulatur

Hi. I am not entirely sure if this is a bug or I am misunderstanding something about OAuth2, I'd like to apologize in advance if it's the latter.

Describe the bug

I followed the tutorial to create an access token and tried using the IntrospectTokenView with that token. This view is a ClientProtectedScopedResourceView that includes required_scopes = ["introspection"]. My understanding of the documentation around these made me believe that if I use a bearer token without the appropriate scope, my request will fail. To my surprise, the call succeeds regardless of the scopes in the token I use.

To Reproduce

  • Set up a basic OAuth2 provider as suggested by the tutorial.
  • Use these steps to create an access token.
  • Try accessing the introspect endpoint like so: curl -X POST -H "Authorization: Basic ${CREDENTIAL}" -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" "http://127.0.0.1:8000/o/introspect/" -d "token=..."

Expected behavior
Even when using the client-credentials flow, I expect a token that doesn't have the introspection scope to be rejected when calling an endpoint declaring required_scopes = ["introspection"].

Version
2.4.0

  • I have tested with the latest published release and it's still a problem.
  • I have tested with the master branch and it's still a problem.

Additional context
I googled around and found this Auth0 thread for a similar question. There it is suggested that scopes in a token are not considered at all if using client-credentials. However, in that example the client itself has associated scopes. This isn't the case for the default setup of DOT, as far as I can see.

As it stands, when using client-credentials, any token can be inspected by any client. If this is the desired behavior that's fine with me. If not, however, you might consider a small change to IntrospectTokenView.get_token_response that uses cls.required_scopes:

@classmethod
def get_token_response(cls, token_value=None):
    try:
        ...
    except ObjectDoesNotExist:
        return JsonResponse({"active": False}, status=200)
    else:
        if token.is_valid(cls.required_scopes):
            ...

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions