Skip to content

DeviceCodeGrant.validate_token_request tries to authenticate public clients #919

@hekhuisk

Description

@hekhuisk

Describe the bug
The DeviceCodeGrant.validate_token_request method always tries to authenticate the client

        if not self.request_validator.authenticate_client(request):
            raise rfc6749_errors.InvalidClientError(request=request)
        elif not hasattr(request.client, "client_id"):
            raise NotImplementedError(
                "Authenticate client must set the "
                "request.client.client_id attribute "
                "in authenticate_client."
            )

For the device workflow though, the vast majority of the time, the clients are public and don't need to be authenticated, so I believe they should be following the AuthorizationCodeGrant.validate_token_request method where it handles both confidential and public clients.

        if self.request_validator.client_authentication_required(request):
            # If the client type is confidential or the client was issued client
            # credentials (or assigned other authentication requirements), the
            # client MUST authenticate with the authorization server as described
            # in Section 3.2.1.
            # https://tools.ietf.org/html/rfc6749#section-3.2.1
            if not self.request_validator.authenticate_client(request):
                log.debug('Client authentication failed, %r.', request)
                raise errors.InvalidClientError(request=request)
        elif not self.request_validator.authenticate_client_id(request.client_id, request):
            # REQUIRED, if the client is not authenticating with the
            # authorization server as described in Section 3.2.1.
            # https://tools.ietf.org/html/rfc6749#section-3.2.1
            log.debug('Client authentication failed, %r.', request)
            raise errors.InvalidClientError(request=request)

How to reproduce

Do the device workflow and try to call the /token endpoint with a public client when your implementation of self.request_validator.authenticate_client assumes it will only ever be called for a confidential client that needs to be authenticated.

Expected behavior

I would expect self.request_validator.authenticate_client to not be called for a public client and instead have it call self.request_validator.authenticate_client_id.

Additional context

Please provide any further context here.

  • Are you using OAuth1, OAuth2 or OIDC? OAuth2
  • Are you writing client or server side code? Server
  • If client, what provider are you connecting to?
  • Are you using a downstream library, such as requests-oauthlib, django-oauth-toolkit, ...? No

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions