Skip to content

feat: Factory pr Service for provider-scoped AuthenticatedHttpClient #90

@ralflang

Description

@ralflang

ClientFactory/ClientService

Apps that want to call external APIs on behalf of a user need an
AuthenticatedHttpClient (PSR-18 decorator from horde/oauth) wired with the
user's stored token and the provider's TokenRefresher config. Assembling
this from OAuthTokenService, OAuthProviderConfigRepository and PSR
factories is boilerplate every consumer would repeat.

Why not just provide the client?

That would be a H5ish model, deriving the "correct" client from all kinds of global and implicit context and binding it to the interface directly. While this works reasonably well for "act on behalf of the authenticated user's identity" it gets messy and hard to reason about as soon as we want users to own resources or services distinct from their own identity, stand in / do delegated tasks on behalf of other users etc. Let's be explicit without being verbose.

What do we need to build?

A Core-level method on OAuthTokenService that takes
($userId, $providerId) and returns a ready-to-use
AuthenticatedHttpClient. I think we should not frame it as a factory and reserve that term for deterministic, autowireable producers.

  • Load the TokenSet from the token repository.
  • Build a TokenRefresher from the provider config (token endpoint,
    client_id, client_secret).
  • Wrap the base PSR-18 ClientInterface in AuthenticatedHttpClient. In practice we need a Horde\Http\Client

Unlocked Capability

  • After the caller is done, the caller or a middleware checks
    getTokenSet() and persists back if changed.

The service should type-hint the result as AuthenticateHttpClient (is a: PSR HTTP ClientInterface) and throw a reasonably specific exception if no such service is available.

Metadata

Metadata

Assignees

Projects

Status

Todo

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions