Skip to content

build(deps): bump gesdinet/jwt-refresh-token-bundle from 2.2.2 to 3.0.0 in /backend in the major group - #577

Merged
algirdasc merged 2 commits into
mainfrom
dependabot/composer/backend/major-911ce0eda0
Aug 16, 2026
Merged

build(deps): bump gesdinet/jwt-refresh-token-bundle from 2.2.2 to 3.0.0 in /backend in the major group#577
algirdasc merged 2 commits into
mainfrom
dependabot/composer/backend/major-911ce0eda0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Aug 15, 2026

Copy link
Copy Markdown
Contributor

Bumps the major group in /backend with 1 update: gesdinet/jwt-refresh-token-bundle.

Updates gesdinet/jwt-refresh-token-bundle from 2.2.2 to 3.0.0

Release notes

Sourced from gesdinet/jwt-refresh-token-bundle's releases.

v3.0.0

Symfony 8, PHP 8.4 and LexikJWTAuthenticationBundle 3.

This release needs a schema change before the application will run. Refresh tokens gained family and family_valid columns, and Doctrine reads every mapped field.

php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate

Read https://github.com/markitosgv/JWTRefreshTokenBundle/blob/HEAD/UPGRADE-3.0.md first, and https://github.com/markitosgv/JWTRefreshTokenBundle/blob/HEAD/UPGRADE-RECTOR.md if you are coming from further back than 2.2.

If you are on Symfony 6.4 or 7.x, stay on 2.2. It is maintained, and Symfony 7.4 is supported until November 2028.

What a session is now

Refresh tokens belong to a chain. A token issued in place of another carries the family of the one it replaced, so a login and every refresh descending from it share one value — which is what makes a session addressable. Without it, "end this session" can only mean "delete this one token", and with single_use that token has usually already been replaced.

Everything below is built on that, and all of it is off by default.

  • reuse_detection — recognises a spent token being presented again and revokes the whole chain. Rotation on its own leaves a stolen token working until the legitimate client happens to refresh, and nobody learns why it broke. It cannot tell theft from a client racing itself, so it revokes either way and dispatches an event for the judgement it cannot make.
  • max_session_lifetime — a ceiling on how long a chain may go on for, whatever ttl says.
  • block_jwts_on_revocation — refuses the JWTs already issued to a user when revokeAllForUser() takes their refresh tokens away. Lexik's blocklist is keyed by jti and cannot do this; what is recorded instead is when the revocation happened.
  • SessionLister — the "where you are signed in" screen and the button next to each row, grouped by chain rather than by token.
  • rate_limiter — consumed before the token is looked at, so a refusal costs no query and its timing says nothing about whether the token exists.
  • cache_pool — stores the tokens in a PSR-6 pool, where expiry is the pool's job. It implements only what a pool can honour and says so about the rest.
  • Per-firewall configurationttl, single_use and the rest on the refresh_jwt authenticator, which is the longest-standing thing this bundle could not do.

Breaking changes

  • PHP 8.4, Symfony 8.0, LexikJWTAuthenticationBundle 3, doctrine/dbal 4
  • check_path is required on refresh_jwt
  • RefreshEvent takes the request, and $firewallName loses its default
  • dbal_columns, when configured, has to name the id column
  • Nine classes are final; the token models and repositories are deliberately not

The full list is in the changelog.

Changelog

Sourced from gesdinet/jwt-refresh-token-bundle's changelog.

3.0.0

See https://github.com/markitosgv/JWTRefreshTokenBundle/blob/master/UPGRADE-3.0.md for what to check before upgrading, and https://github.com/markitosgv/JWTRefreshTokenBundle/blob/master/UPGRADE-RECTOR.md if you are coming from further back than 2.2.

This release needs a schema change before the application will run. Refresh tokens gained family and family_valid columns, and Doctrine reads every mapped field.

Added

  • Refresh tokens belong to a family: a token issued in place of another carries the family of the one it replaced, so a login and every refresh descending from it share one value. That is what makes a session addressable — without it, "end this session" can only mean "delete this one token", which the next refresh has already replaced. Kept in Model\FamilyAwareRefreshTokenInterface and Model\RefreshTokenFamilyTrait, separate from RefreshTokenInterface so a token class of your own is untouched. Model\FamilyRefreshTokenManagerInterface::revokeFamily() revokes a whole chain
  • reuse_detection, which recognises a single use refresh token being presented after it was spent and revokes the chain it belonged to. Rotation alone leaves a stolen token working until the legitimate client happens to refresh, and nobody learns why it broke; a spent token is deleted, so a replay is indistinguishable from any other unknown token unless spent ones are remembered. Off by default, refused without single_use, and it dispatches RefreshTokenReuseDetectedEvent because the bundle cannot tell theft from a client racing itself
  • max_session_lifetime, a ceiling on how long a chain of refreshes may go on for, whatever ttl says. A ttl that starts over on every rotation means a session never ends. The deadline is set when a chain starts and carried along it unchanged
  • block_jwts_on_revocation, which refuses the JWTs already issued to a user when revokeAllForUser() takes their refresh tokens away. Lexik's blocklist cannot do this — it is keyed by jti, so it withdraws a token you are holding, and these are in clients — so what is recorded is when the revocation happened, per user, and any JWT issued at or before it is refused on decode
  • rate_limiter, bounding how often the refresh endpoint will answer. Consumed before the token is looked at, so a refusal costs no query and its timing says nothing about whether the token exists. Refused requests answer 429 with Retry-After. Keyed by IP or by token, which is a trade-off rather than a detail. Needs symfony/rate-limiter
  • Session\SessionLister, for showing a user where they are signed in and letting them end one. Grouping by chain is what turns findAllForUser() from a list of moments into a list of sessions. end() checks the chain belongs to the caller, since a session list is exactly where such an identifier gets handed out
  • cache_pool, storing the tokens in a PSR-6 pool instead of a database. Expiry is then the pool's job, so nothing has to be scheduled to clear them. It implements only what a pool can honour, and max_tokens_per_user and reuse_detection are configuration errors alongside it rather than options that quietly do nothing
  • The refresh behaviour can be configured per firewall: ttl, ttl_update, token_parameter_name, single_use, single_use_ttl_update, max_session_lifetime, max_tokens_per_user, return_expiration and return_expiration_parameter_name on the refresh_jwt authenticator. Every one defaults to null, meaning "whatever the bundle says", which is not the same as defaulting to its current value. Cookie settings stay global
  • block_previous_jwt, which blocks the JWT a refresh replaces through LexikJWTAuthenticationBundle 3's blocklist, so refreshing no longer leaves the previous JWT usable for the rest of its lifetime. A request carrying no JWT, and a JWT that no longer parses, are left alone: an expired one is refused everywhere already. Off by default, and reported at compile time when Lexik's blocklist_token is not on
  • Rector rule sets for every hop from 1.5 to 3.0, under rector/sets, with the upgrade path in https://github.com/markitosgv/JWTRefreshTokenBundle/blob/master/UPGRADE-RECTOR.md. Only the 1.5 to 2.0 set rewrites anything; the other three are empty and say why

Changed

  • BC break: PHP 8.4 or later, Symfony 8.0 or later, and LexikJWTAuthenticationBundle 3. Symfony 6.4 and the 7 branch are dropped, which takes PHP 8.2 and 8.3 with them since Symfony 8 needs 8.4
  • BC break: check_path is required on the refresh_jwt authenticator. It defaulted to /login_check, Lexik's login path, which is never right for a refresh endpoint: left alone the authenticator took no requests and the router reported the refresh route as having no controller
  • BC break: RefreshEvent takes the request the refresh was made with, and $firewallName loses its default. Listeners gain getRequest(); only code constructing the event is affected
  • BC break: doctrine/dbal 3 is dropped, along with the shims for quoteIdentifier() and setPrimaryKey()
  • dbal_columns, when configured, has to name the id column. A map without one produced a table whose expired tokens could never be revoked: batches are deleted by identifier, so with none to delete by, gesdinet:jwt:clear read the same batch forever
  • BC break: the exceptions, the bundle class, the failure response and the post-refresh security token are final. The token models, AbstractRefreshToken and the two repositories are deliberately left extendable, being the documented way to bring your own
  • Every file declares strict_types, so the calls this bundle makes pass their arguments without coercion
  • The codebase uses the PHP 8.4 syntax its minimum already requires, and rector.php and .php-cs-fixer.php now keep it that way. rector/rector had been a development dependency for a long time with nothing configured to run it

Fixed

  • DBAL index names include the table name. UNIQ_REFRESH_TOKEN, IDX_USERNAME and IDX_VALID were fixed whatever the table was called, and index names are scoped to the schema on PostgreSQL and to the whole database on SQLite — so a second table managed by the bundle could not be created, and the error named an index rather than anything identifying this bundle. Existing tables are untouched, since the schema is only built when absent
  • Session\SessionLister keys chains by array-key rather than string. A family is 32 hex characters, and PHP turns one that happens to be all digits into an integer key
  • The nineteen open code scanning alerts. Seven were real, including a missing mutation annotation on RefreshTokenFamilyTrait that stopped psalm's taint analysis reasoning about where a family came from, and four array shapes that were sealed promises about keys the method never looks at. The rest are by design or belong to Symfony, Doctrine and API Platform, and are suppressed in psalm.xml.dist scoped to the files they concern, each with the reason

2.2.1

Fixed

  • ttl and max_tokens_per_user can be read from an environment variable again. Both were checked with a validate() closure, which rejects every %env(int:...)% put in front of them: the container is compiled a second time with a sample value of the declared type in place, and for an integer that sample is 0. min() is skipped while a placeholder is being handled and a closure is not, so the built-in constraint is used instead. Reported as #431 against 2.2.0, where the ttl check was introduced; 2.1.0 has no such check and is unaffected

2.2.0

Released 2026-08-04. See https://github.com/markitosgv/JWTRefreshTokenBundle/blob/master/UPGRADE-2.2.md for what to check before upgrading.

Changed

... (truncated)

Commits
  • fd8d573 docs: write the 3.0.0 changelog and move the branch alias to 3.x
  • 7baa737 build: hold the hosted check to a baseline it and php-cs-fixer agree on
  • 59378f5 fix: clear the code scanning alerts
  • 550a51e style: let Symfony's convention win where StyleCI deviates
  • 02acdfc style: treat the config file comments as comments
  • 8846e2e style: match the four rules the hosted check actually applies
  • 6472b3b build: align php-cs-fixer, StyleCI and Rector so they stop fighting
  • 9d96ba5 refactor: drop the wrapping parentheses on new in method calls
  • 602c055 refactor: declare strict types
  • fb7587c build: pick up root files and run Rector in parallel
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  • @dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  • @dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  • @dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency
  • @dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditions

Bumps the major group in /backend with 1 update: [gesdinet/jwt-refresh-token-bundle](https://github.com/markitosgv/JWTRefreshTokenBundle).


Updates `gesdinet/jwt-refresh-token-bundle` from 2.2.2 to 3.0.0
- [Release notes](https://github.com/markitosgv/JWTRefreshTokenBundle/releases)
- [Changelog](https://github.com/markitosgv/JWTRefreshTokenBundle/blob/master/CHANGELOG.md)
- [Commits](markitosgv/JWTRefreshTokenBundle@v2.2.2...v3.0.0)

---
updated-dependencies:
- dependency-name: gesdinet/jwt-refresh-token-bundle
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: major
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file php Pull requests that update Php code labels Aug 15, 2026
@algirdasc
algirdasc merged commit 62792c2 into main Aug 16, 2026
4 checks passed
@algirdasc
algirdasc deleted the dependabot/composer/backend/major-911ce0eda0 branch August 16, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file php Pull requests that update Php code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant