Skip to content

Release/1.1.2 - #34

Merged
adumont-payplug merged 1 commit into
masterfrom
release/1.1.2
Sep 15, 2026
Merged

adumont-payplug merged 1 commit into
masterfrom
release/1.1.2

Conversation

@adumont-payplug

@adumont-payplug adumont-payplug commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Release 1.1.2. release/1.1.2 is master (at 1.1.1) plus exactly one commit — nothing else
rides along:

  • PRE-3631: expose the OAuth id_token on TokenOutput

What it does

Exposes the OpenID Connect id_token on TokenOutput, so a consuming plugin can identify who
authorized a connection, not just which account the resulting token authorizes.

The Sylius plugin needs to display the connected PayPlug account's email on its gateway-configuration
admin screen. That email is not reachable from anywhere it currently looks:

  • GET /account returns only id, company_ref, country, object, is_live, configuration,
    permissions, payment_methods — no email, at any depth (verified live against several QA accounts).
  • The client_credentials token used for every background API call authenticates a machine, so it
    names no user either.

The only carrier is the id_token from the interactive authorization-code exchange, which
OAuth2Client::requestToken() was discarding before constructing its TokenOutput.

  • Output/TokenOutput — new nullable idToken property, set from a 4th constructor argument
    defaulting to null.
  • Auth/OAuth2Client::requestToken() — reads id_token off the token-endpoint response when present
    and passes it through.

Two deliberate design points:

  • Additive and backward-compatible. idToken is a trailing argument with a default, so every
    pre-existing 3-argument caller keeps working unchanged.
  • Optional and unvalidated, on purpose. requestToken() is shared by exchangeAuthorizationCode()
    and getClientCredentialsToken(); only the former can ever produce an id_token, so asserting on it
    would reject a perfectly usable client-credentials response. UPC does not parse the JWT — consumers
    decode whichever claim they need.

Related Issue

Ticket: PRE-3631

Type of Change

  • ✨ New feature
  • 🚀 Release (release/* branch targeting master)

✅ Quality Checklist

Local Environment & Hooks

  • Local Git hooks (CaptainHook) are installed and executed cleanly (make install).
  • Commit messages strictly follow the (PRE|SMP)-XXXX: description pattern.
  • Branch name follows (feature|fix|hotfix|refactor)/(PRE|SMP)-XXXX... or (release|patch)/x.y.z.

Testing & Code Quality

  • Coding style rules have been applied locally (make cs-fix).
  • Static analysis passes with no new regressions (make stan — PHPStan level 8).
  • I have added/updated PHPUnit tests if applicable (make test).
  • No PHP syntax newer than 7.1 introduced in src/ or tests/ (no typed properties, arrow
    functions, constructor property promotion, match, enum).

CI/CD Deployment Context

  • The CI pipeline passes fully on GitHub, including the compatibility matrix
    (PHP 7.1 / 7.4 / 8.0 / 8.1 / 8.2) and the quality job.

Notes for Reviewer

Upgrade impact on plugins that bump to 1.1.2 and change nothing: none.

  • TokenOutput is final, so nobody can have subclassed it with a 3-argument constructor that the
    new signature would invalidate.
  • The new parameter is trailing with a null default; the new property is purely additive. Existing
    reads of accessToken / expiresIn / tokenType are untouched.
  • The new read is isset($data['id_token']) && \is_string(...) — it cannot throw and adds no failure
    path. A response without an id_token behaves exactly as before.
  • No cache invalidation needed. TokenManager stores only the bare access-token string, never
    the object, so the token-cache format is unchanged. Nothing in UPC serializes, json_encodes or
    get_object_vars() a TokenOutput either.
  • PHP 7.1 floor holds (?string is 7.1 syntax) — confirmed by make verify-71, on top of the CI
    compatibility matrix.

They also wouldn't see a value: idToken is non-null only when a caller uses
exchangeAuthorizationCode() and passes a scope containing openid/email. Today PrestaShop
consumes UPC only for PhoneHelper and the exception types and runs its own OAuth through the
payplug-php SDK; WooCommerce and Magento don't depend on UPC at all. Sylius is the sole consumer of
the auth layer.

One behaviour change that could reach a plugin passively: if a consumer ever dumps a whole
TokenOutput for debugging (print_r, var_dump, json_encode, or a logger that serializes context
objects), an id_token would now appear in that output where nothing did before — and an id_token is
a JWT carrying PII (email, sub). No current consumer does this, and it only affects the
authorization-code path. Flagging it rather than pre-emptively adding a redacting __debugInfo(),
which would also hide the field from the consumer that legitimately wants it. Say if you'd rather it
be redacted.

Where the tests are:

  • tests/Output/TokenOutputTest.php — assignment, the null default, and one case asserting the
    constructor explicitly does not validate idToken (an empty one must not invalidate an otherwise
    usable response).
  • tests/Auth/OAuth2ClientTest.php — id_token surfaced from an authorization-code response, left
    null when the response omits it, and left null for client_credentials. Those last two guard the
    optionality: they fail the day someone makes id_token required in the shared requestToken().

make quality green locally on this exact tree: cs-lint 0/104 fixable, PHPStan level 8 clean,
339 tests / 904 assertions.

Downstream: the Sylius plugin's PRE-3631 branch pins ^1.1.2 and cannot go green until this is
merged and the 1.1.2 tag is pushed on master.

CLAUDE.md is updated in the same commit (Output/ and src/Auth/ bullets), per this repo's
rule that a category's documentation moves with the code.

@adumont-payplug adumont-payplug changed the title PRE-3631: expose the OAuth id_token on TokenOutput Release/1.1.2 Sep 15, 2026
@adumont-payplug
adumont-payplug merged commit 10ead91 into master Sep 15, 2026
34 checks passed
@adumont-payplug
adumont-payplug deleted the release/1.1.2 branch September 15, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant