utopia-php / utopia-php/monorepo

An expired credential is unrecoverable, which defeats the dynamic token providers

Open
#197 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
PHP
Stars
3
Forks
4
Avg merge
12h 25m
Merged PRs (30d)
103

Description

Connection::UNRECOVERABLE_ERRORS lists authentication expired, so handleError()recycleDeadConnection(false) marks the connection dead instead of rebuilding it:

// packages/nats/src/Connection.php:73
private const array UNRECOVERABLE_ERRORS = [
    'authorization violation',
    'authentication timeout',
    'authentication expired',
    ...
];

The rationale in reconnectsAfter() is sound for most of that list — retrying credentials the server just rejected turns a hard failure into a hot loop. But it does not hold for an expiry, because the client may well have a different credential available by the time it reconnects:

// packages/nats/src/Connection.php:~658 (buildConnectPayload)
// Dynamic providers are resolved on every (re)connect so refreshed
// tokens/JWTs take effect without rebuilding the connection.
if ($this->options->tokenProvider instanceof \Closure) { ... }
if ($this->options->jwtProvider instanceof \Closure) { ... }

NATS sends -ERR 'Authentication Expired' exactly when a live connection's credential lapses, which is the case those providers exist to handle. Today a worker with a rotating JWT goes dead at the first expiry and every later call raises, even though a reconnect would have picked up a valid token.

authorization violation is different and should stay unrecoverable: same credential, same rejection, every time.

Fix: make the expiry case conditional on a provider being configured — reconnect when tokenProvider/jwtProvider is set (there is a new credential to present), mark dead otherwise (there is not). Bounded reconnect attempts already cap the hot-loop risk if a provider keeps handing back a stale token.

Found by a review sweep over main while resolving #192; not introduced by it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/nats/src/Connection.php, tracing handleError() through recycleDeadConnection(false) and reconnectsAfter(), then inspect buildConnectPayload() to see how tokenProvider and jwtProvider are resolved. Done means authentication expiry reconnects only when a provider is configured, while authorization violations and expiry without a provider remain unrecoverable; verify the relevant connection behavior with the project's tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
distributed-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.