How auth-server-php works
auth-server-php mirrors auth-server-ts
directory-for-directory. Read that page first if you’ve worked with the
TS core — most concepts translate verbatim.
The PHP-specific differences:
PSR-driven ports
| TS port | PHP equivalent | Standard |
|---|---|---|
HttpTransport | Transport | PSR-18 (Client) + PSR-17 (Factory) |
RevocationCache | RevocationCache | PSR-16 SimpleCache |
LoggerPort | LoggerInterface | PSR-3 |
Clock | Clock | (custom, PSR-20 was too restrictive) |
SessionStore | SessionStore | (custom) |
This means you can pull in guzzlehttp/psr7 + guzzlehttp/guzzle for
the transport, your framework’s cache for revocation, and Monolog for
logging — no extra wrappers.
No reactive snapshot
PHP is single-process per request — there’s no equivalent to the TS
AuthClient.on('logged_in', ...) event bus. The PHP facade exposes
imperative login() / refresh() / logout() methods that return the
new state directly.
Events namespace exists but is for server-side hooks (audit log,
metrics) — not a browser-style event subscription.
Composition
AuthClient ├── Config (authServerUrl, appCode, jwtIssuer, jwtAudience, …) ├── Transport — HttpTransport (default, PSR-18) ├── TokenValidator — JwtValidator (HS256 + rotation + revocation gate) ├── SessionStore — InMemorySessionStore ├── Clock — SystemClock └── LoggerInterface — NullLogger (default)Construct via AuthClient::build(config, transport, ...) (recommended)
or new AuthClient(config, transport, ...) for full control.
Token validation flow
Same as the TS core — verify HS256 signature against active secret,
fall back to JWT_ACCESS_SECRET_PREVIOUS on signature mismatch only,
check iss / aud / exp / nbf / iat, check tv against
revocation cache, check jti against blacklist.
Error map
| Exception | Maps from |
|---|---|
TokenExpiredException | 401 with code token_expired |
TokenRevokedException | 401 with code token_revoked |
TokenInvalidException | 401 with code token_invalid |
InvalidCredentialsException | 401 with code invalid_credentials |
TwoFactorRequiredException | 401 with {requires_2fa: true} |
UnauthorizedException | 401 (other) |
ForbiddenException | 403 |
NotFoundException | 404 |
ConflictException | 409 |
ValidationException | 400 / 422 |
RateLimitedException | 429 (with retryAfter) |
ServerException | 5xx |
NetworkException | connection failures |
OfflineModeException | bootstrap-equivalent (rare in PHP) |
VenAuthException is the root. Every flow method declares @throws VenAuthException and consumers can instanceof to narrow.
Refresh handling
Refresh is a one-shot call ($auth->refresh($refreshToken)) — no
mutex needed in PHP because the request lifecycle is single-process. If
your application spans multiple workers (e.g. CLI + HTTP), share token
state via a SessionStore backed by Redis or your framework’s session.
Where to plug in custom adapters
| Port | Implement | When |
|---|---|---|
Transport | Wrap your PSR-18 client | Custom retry; tracing headers |
RevocationCache | Wrap your PSR-16 cache | Shared revocation across replicas |
SessionStore | Implement SessionStore | Cross-process session sharing |
Clock | Implement Clock | Deterministic tests |
LoggerInterface | Use Monolog or your framework’s logger | Production logging |