Problem/Motivation

Part of #3630879: Allow OAuth2 clients that are not saved consumer entities

TokenAuthUser::__construct() loads the consumer from $token->get('client')->entity and uses it twice:

  • As the fallback subject: when the token has no auth_user_id (client credentials), it uses the consumer's user_id.
  • For getConsumer(). Its only caller is SimpleOauthAuthenticationProvider::authenticate(), which sets the X-Consumer-ID request header for the Consumers negotiator.

The OAuth flows get their client from simple_oauth.repositories.client. This is the one lookup during request authentication that bypasses it, and it runs on every authenticated request.

Proposed resolution

  • Inject simple_oauth.repositories.client into SimpleOauthAuthenticationProvider.
  • Resolve the client with getClientEntity($token->get('client_id')->value) and pass it to TokenAuthUser. Throw OAuthServerException::invalidClient() when it returns NULL.
  • Add TokenAuthUser::getClient(): ClientEntityInterface.
  • Deprecate TokenAuthUser::getConsumer() and have it return $this->getClient()->getDrupalEntity().
  • Set X-Consumer-ID from getClient()->getIdentifier().

The Consumers negotiator still loads consumers by client_id from storage. Clients served by another repository won't resolve there. That belongs in the Consumers queue, not here.

Remaining tasks

  • MR with a kernel test that decorates ClientRepository and authenticates a request.
  • Change record for the deprecation.

API changes

  • New: TokenAuthUser::getClient().
  • Deprecated: TokenAuthUser::getConsumer().
  • The TokenAuthUser constructor signature changes. It's built only by SimpleOauthAuthenticationProvider.

AI disclosure

AI-Generated: Yes. I drafted this issue summary with Claude Code and reviewed it before filing.

Comments

mglaman created an issue. See original summary.

mglaman’s picture

Category: Task » Feature request
vidit.anjaria’s picture