You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
4.3 spends its whole cycle preparing 5.0: every removal the major makes is deprecated there, every class it seals is annotated, and every contract it changes carries a BC NOTE. This issue is the inventory of what 5.0 has to do with that preparation, so that the 5.0.x branch can start the day 4.3.0 is tagged.
It is an umbrella: #653 tracks the RSA1_5 CEK size on its own.
1. Remove the deprecated API
52 @deprecated annotations and 4 deprecated arguments (count of 2026-09-13, after #732–#736).
Output parameters, replaced by the result objects of 4.3
JWSLoader::loadAndVerifyWithKey() and loadAndVerifyWithKeySet() → loadAndVerify()
JWSVerifier::verifyWithKeySet() → verify()
JWEDecrypter::decryptUsingKey() and decryptUsingKeySet() → decrypt()
JWELoader::loadAndDecryptWithKey() and loadAndDecryptWithKeySet() → loadAndDecrypt()
the same seven methods on EventDispatchingJWSLoader, EventDispatchingJWSVerifier, EventDispatchingJWEDecrypter and EventDispatchingJWELoader, which survive the removal of the deprecated subclasses below
the $signature argument of NestedTokenLoader::load() and of EventDispatchingNestedTokenLoader::load()
the $name argument of JWSSerializerManager::unserialize() and JWESerializerManager::unserialize()
Immutability
JWSBuilder::create() and JWEBuilder::create()
AlgorithmManager::add()
JWSSerializerManagerFactory::names() and JWESerializerManagerFactory::names() → aliases()
Key management
the 16 static methods of JWKFactory → JWKFactoryInterface
the UrlKeySetFactory class and UrlKeySetFactoryTrait::enabledCache() (deprecated since 4.1)
the 10 matching factories still build those subclasses today, since returning the EventDispatching* decorators would have changed their return type in a minor: rewire them, and widen create() to the interfaces
Algorithms
Jose\Component\Signature\Algorithm\None and Jose\Component\Encryption\Algorithm\KeyEncryption\RSA15, the two shims kept for the migration to web-token/jwt-unsecured and web-token/jwt-rsa15
drop the require on those two packages from web-token/jwt-library: it exists only so the shims can extend their replacement
Core\Util\InheritanceChecker (13 call sites) and Core\Util\InternalCallChecker (2 call sites)
2. Seal what 4.3 announced
final on the 11 services carrying @final: JWSBuilder, JWSVerifier, JWSLoader, JWEBuilder, JWEDecrypter, JWELoader, NestedTokenBuilder, NestedTokenLoader, JWKFactory (also readonly), Checker\ClaimCheckerManager and Checker\HeaderCheckerManager
final readonly on JWK, JWKSet, JWS, JWE and Signature, with the state given to the constructor. This removes JWS::addSignature() and JWE::withPayload(), the two mutators sealed in 4.3, so the builders and the serializers have to assemble the object in one go
Signature: throw instead of deprecating when a protected header is passed without its encoded form
final on the three classes left open only so their deprecated shim can extend them: Jose\Unsecured\Signature\None, Jose\Rsa15\KeyEncryption\RSA15 and Jose\Component\Signature\Algorithm\ES256K
WrappedKey as the return type of KeyEncryption::encryptKey(), KeyWrapping::wrapKey(), KeyAgreement::getAgreementKey() and KeyAgreementWithKeyWrapping::wrapAgreementKey() (announced for the fourth one in feat(core): announce the 5.0.0 breaks that were still silent #715), dropping the array &$additionalHeader output parameter
EncryptedContent as the return type of ContentEncryptionAlgorithm::encryptContent(), dropping ?string &$tag
EncryptionAlgorithmManagers: reject the algorithms that are neither key encryption nor content encryption instead of ignoring them, and give the builder and the decrypter the two managers
merge MissingPayloadRuntimeException and MissingPayloadLogicException into a single class
4. Housekeeping
open the 5.0.x branch
raise the PHP floor (>=8.2 today) and the Symfony one (^7.0|^8.0), prune brick/math: ^0.12|…|^0.19
keep symfony/deprecation-contracts: 5.x will deprecate again
write migration/from-v4.3-to-v5.0.md in the documentation
Done when
On 5.0.x, each of these greps returns nothing in src/:
@deprecated
trigger_deprecation
func_num_args|func_get_arg
@final
BC NOTE
5\.0
The func_num_args() one is the useful cross-check: every remaining crutch belongs either to a deprecated method removed in section 1, or to the CEK size argument declared in section 3.
2026-09-13 — #715 and #716 merged: the WrappedKey and TokenHeaders announcements of section 3 are in place. #732–#736 added two deprecations (the ES256K shim, EdDSA) and three classes left open for a shim: folded into sections 1, 2 and 4 above.
4.3 spends its whole cycle preparing 5.0: every removal the major makes is deprecated there, every class it seals is annotated, and every contract it changes carries a
BC NOTE. This issue is the inventory of what 5.0 has to do with that preparation, so that the5.0.xbranch can start the day 4.3.0 is tagged.It is an umbrella: #653 tracks the RSA1_5 CEK size on its own.
1. Remove the deprecated API
52
@deprecatedannotations and 4 deprecated arguments (count of 2026-09-13, after #732–#736).Output parameters, replaced by the result objects of 4.3
JWSLoader::loadAndVerifyWithKey()andloadAndVerifyWithKeySet()→loadAndVerify()JWSVerifier::verifyWithKeySet()→verify()JWEDecrypter::decryptUsingKey()anddecryptUsingKeySet()→decrypt()JWELoader::loadAndDecryptWithKey()andloadAndDecryptWithKeySet()→loadAndDecrypt()EventDispatchingJWSLoader,EventDispatchingJWSVerifier,EventDispatchingJWEDecrypterandEventDispatchingJWELoader, which survive the removal of the deprecated subclasses below$signatureargument ofNestedTokenLoader::load()and ofEventDispatchingNestedTokenLoader::load()$nameargument ofJWSSerializerManager::unserialize()andJWESerializerManager::unserialize()Immutability
JWSBuilder::create()andJWEBuilder::create()AlgorithmManager::add()JWSSerializerManagerFactory::names()andJWESerializerManagerFactory::names()→aliases()Key management
JWKFactory→JWKFactoryInterfaceUrlKeySetFactoryclass andUrlKeySetFactoryTrait::enabledCache()(deprecated since 4.1)Core
JWKSet::sortKeys()Bundle
Services\*subclasses:JWSBuilder,JWSVerifier,JWSLoader,JWEBuilder,JWEDecrypter,JWELoader,NestedTokenBuilder,NestedTokenLoader,ClaimCheckerManager,HeaderCheckerManagerEventDispatching*decorators would have changed their return type in a minor: rewire them, and widencreate()to the interfacesAlgorithms
Jose\Component\Signature\Algorithm\NoneandJose\Component\Encryption\Algorithm\KeyEncryption\RSA15, the two shims kept for the migration toweb-token/jwt-unsecuredandweb-token/jwt-rsa15requireon those two packages fromweb-token/jwt-library: it exists only so the shims can extend their replacementJose\Experimental\Signature\ES256K, the shim kept since feat(signature): move ES256K from the experimental package to the library (RFC 8812) #736 moved the algorithm to the library, and its deprecated service in the bundle'ssignature_experimental.phpEdDSA: RFC 9864 deprecates the polymorphic identifier and feat(signature): Ed25519 and Ed448 fully-specified algorithms, X448 for ECDH-ES (RFC 9864, RFC 8037) #734 deprecates signing with it, verification stays silent so the tokens in circulation keep working. Its docblock calls the removal "a candidate for 5.0.0" — either remove the class, or keep it verify-only and say soJose\Experimental\Signature\ES256K, the alias kept once the algorithm moves toJose\Component\Signature\Algorithm\ES256K(RFC 8812) — refactor(signature): move ES256K out of the experimental package (RFC 8812) #727Jose\Component\Signature\Algorithm\EdDSA, deprecated by RFC 9864 in favour ofEd25519/Ed448— feat(signature): Ed25519 and Ed448 fully-specified algorithms, EdDSA deprecated (RFC 9864); X448 for ECDH-ES (RFC 8037) #724 adds the replacements in 4.3; decide here whether the polymorphic identifier is removed or merely kept deprecated (interop:EdDSAis still what most issuers emit)Deprecation plumbing
Core\Util\InheritanceChecker(13 call sites) andCore\Util\InternalCallChecker(2 call sites)2. Seal what 4.3 announced
finalon the 11 services carrying@final:JWSBuilder,JWSVerifier,JWSLoader,JWEBuilder,JWEDecrypter,JWELoader,NestedTokenBuilder,NestedTokenLoader,JWKFactory(alsoreadonly),Checker\ClaimCheckerManagerandChecker\HeaderCheckerManagerfinal readonlyonJWK,JWKSet,JWS,JWEandSignature, with the state given to the constructor. This removesJWS::addSignature()andJWE::withPayload(), the two mutators sealed in 4.3, so the builders and the serializers have to assemble the object in one goSignature: throw instead of deprecating when a protected header is passed without its encoded formfinalon the three classes left open only so their deprecated shim can extend them:Jose\Unsecured\Signature\None,Jose\Rsa15\KeyEncryption\RSA15andJose\Component\Signature\Algorithm\ES256KJWE::getIV()andgetTag(): narrow tostringand drop the tworeturn.unusedTypeentries added to the PHPStan baseline in feat(core): announce the 5.0.0 breaks that were still silent #7153. Change the contracts
WrappedKeyas the return type ofKeyEncryption::encryptKey(),KeyWrapping::wrapKey(),KeyAgreement::getAgreementKey()andKeyAgreementWithKeyWrapping::wrapAgreementKey()(announced for the fourth one in feat(core): announce the 5.0.0 breaks that were still silent #715), dropping thearray &$additionalHeaderoutput parameterEncryptedContentas the return type ofContentEncryptionAlgorithm::encryptContent(), dropping?string &$tagTokenHeadersas the return type ofTokenTypeSupport::retrieveTokenHeaders()(feat(checker): announce the object replacing the token type support headers #716), dropping its twoarray &$headerKeyEncryption::decryptKey()andKeyWrapping::unwrapKey(), deleteCEK_LENGTHSfromJose\Rsa15\KeyEncryption\RSA15and drop the two@phpstan-ignore arguments.countofJWEDecrypter— RSA1_5: pass the expected CEK size as a parameter instead of the hardcoded CEK_LENGTHS table #653EncryptionAlgorithmManagers: reject the algorithms that are neither key encryption nor content encryption instead of ignoring them, and give the builder and the decrypter the two managersMissingPayloadRuntimeExceptionandMissingPayloadLogicExceptioninto a single class4. Housekeeping
5.0.xbranch>=8.2today) and the Symfony one (^7.0|^8.0), prunebrick/math: ^0.12|…|^0.19symfony/deprecation-contracts: 5.x will deprecate againAlgorithmManagerTest,JWSBuilderImmutabilityTest,JWEBuilderImmutabilityTest), the 2 tests documenting the algorithm shims (NoneSignatureTest,RSAKeyEncryptionTest), and the inheritance cases ofServiceInterfacesTestandSealedValueObjectsTest; since feat(signature): Ed25519 and Ed448 fully-specified algorithms, X448 for ECDH-ES (RFC 9864, RFC 8037) #734/feat(signature): move ES256K from the experimental package to the library (RFC 8812) #736, alsoDeprecatedES256KConsumer, the shim cases ofExperimentalAlgorithmsTestandES256KSignatureTest, and theEdDSAcases ofEdDSAAlgorithmsTestandOKPKeyAnalyzerTestmigration/from-v4.3-to-v5.0.mdin the documentationDone when
On
5.0.x, each of these greps returns nothing insrc/:The
func_num_args()one is the useful cross-check: every remaining crutch belongs either to a deprecated method removed in section 1, or to the CEK size argument declared in section 3.2026-09-13 — #715 and #716 merged: the
WrappedKeyandTokenHeadersannouncements of section 3 are in place. #732–#736 added two deprecations (theES256Kshim,EdDSA) and three classes left open for a shim: folded into sections 1, 2 and 4 above.