New in Symfony 8.2 (in development). Signed URLs, login links, "remember me" cookies and signed Messenger messages all rely on a secret. Changing it, after a leak or out of plain hygiene, broke everything it had signed at once: the links already sent by email stopped working.
A list of secrets
Each feature that signs now has its secret option, which accepts a list. The first one signs, all of them check; each one defaults to kernel.secret.
# config/packages/framework.yaml framework: uri_signer: secret: ['%env(URI_SIGNER_SECRET)%', '%kernel.secret%'] messenger: serializer: signing_secret: ['%env(MESSENGER_SIGNING_SECRET)%', '%kernel.secret%']
# config/packages/security.yaml security: firewalls: main: remember_me: secret: ['%env(REMEMBER_ME_SECRET)%', '%kernel.secret%']
You remove the old secret when nothing it signed is in use anymore: once the links sent with it have expired. Messenger messages are signed again on each retry, and "remember me" cookies on each login: they move to the new secret by themselves.
Symfony 8.2 also adds sign: true on a Messenger transport: all its messages are signed, and a badly signed message is rejected before it is even read.
Your task
On October 24, the team replaced the secret that signs invitations: URI_SIGNER_SECRET holds the new one, URI_SIGNER_OLD_SECRET the old one (see config/packages/secrets.yaml). Since then, every invitation sent before answers 404.
- The invitations already sent must work until they expire, and the new ones must be signed with the new secret.
- The controller signs without an expiration, which Symfony 8.2 deprecates: give links a default expiration of seven days, in the configuration.