Tell the client how long the Mercure authorization cookie lives - #2012
Merged
Merged
Conversation
The hub authorises a subscription only at connect time, so a client that cannot know when its cookie expires has no way to renew before it does. mercure/auth now returns the configured lifetime next to the cookie it sets. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Exposes the Mercure authorization cookie lifetime so clients can renew before expiry.
Changes:
- Adds an authorization response DTO and OpenAPI schema.
- Returns the configured cookie lifetime from
/mercure/auth. - Adds HubService lifetime and expiry tests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/Mercure/Controller/JwtController.php |
Returns lifetime JSON with the cookie. |
src/Mercure/Schema/Authorization.php |
Defines the response DTO. |
src/Mercure/Service/HubService.php |
Exposes the configured lifetime. |
src/Mercure/Service/HubServiceInterface.php |
Adds the lifetime contract. |
tests/Unit/Mercure/Service/HubServiceTest.php |
Tests lifetime and cookie expiry. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The factory derived `exp` from `session.cookie_lifetime` (or 3600) instead, so a configured `cookie_lifetime` above that told the client to renew long after the hub had stopped accepting its token. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
markus-moser
approved these changes
Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Part of the fix for pimcore/platform-version#346.
Problem
The Mercure hub authorises a subscription exactly once, when the
EventSourceconnects, from themercureAuthorizationcookie sent with that request. The cookie livescookie_lifetimeseconds(3600 by default) while a Studio tab lives for as long as the user leaves it open, and the hub
closes every stream on its own
write_timeout(600s by default) so the browser reconnects roughlyevery nine minutes. Any reconnect made after the cookie expired is accepted as an anonymous
subscription by a hub that allows those, and then receives no private update ever again: no error,
no
onerror, and the client keeps reporting a healthy stream.The client has to renew the cookie before it expires, and today it has no way to know when that is.
Change
POST /mercure/authnow returns the configured lifetime next to the cookie it sets:{ "cookieLifetime": 3600 }Mercure\Schema\Authorizationresponse DTO (OpenAPI documented asMercureAuthorization)HubServiceInterface::getCookieLifetime()exposes the configuredpimcore_studio_backend.mercure_settings.cookie_lifetimeJwtController::auth()returns that DTO as the response bodyReturning the lifetime rather than an absolute expiry keeps it immune to clock differences
between server and browser: the value is relative to the response the client just received.
Backward compatibility
Additive only. The action's return type stays
Response(JsonResponseis one), the status codeand the
Set-Cookieheader are unchanged, and a client that ignores the body behaves exactly asbefore.
HubServiceInterfaceis@internal.The consuming side is pimcore/studio-ui-bundle#4009, which reads the field defensively and falls
back to a one hour assumption, so the two can be merged in either order.
Verification
HubServiceTest(3 cases), including a regression test that the advertised lifetime and theactual cookie expiry are derived from the same value: if they drift, a client that renews "in
time" still reconnects with a dead cookie, which is precisely the failure this is meant to end
vendor/bin/codecept run Unit tests/Unit/Mercuregreen (15 tests)src/Mercure{"cookieLifetime":3600}