Symfony 8.2 is planned for the end of November 2026, with support scheduled through July 2027. The release requires PHP 8.4.0 or newer. It is still under development, so its APIs and details can change before the final version. The examples should be tested outside production.

AccountController.php
<?php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

class AccountController extends AbstractController
{
    #[Route('/account/delete', name: 'app_delete_account')]
    #[IsGranted('IS_AUTHENTICATED_VERY_RECENTLY')]
    public function deleteAccount(): Response
    {
    }
}

Each Symfony component will ship its own bundle, configuration and services. Symfony 8.2 adds 29 bundles, including CacheBundle, HttpClientBundle, MailerBundle and MessengerBundle. Components register their bundles automatically, so config/bundles.php needs no manual change. Existing framework.* settings continue to work without deprecation notices. The framework root can be removed gradually. framework.assets becomes asset, framework.translator becomes translation, and framework.workflows becomes workflow. Lock and semaphore can receive a DSN directly. The command for inspecting mailer configuration changes from debug:config framework mailer to debug:config mailer. Forms no longer enable validation automatically, because installing symfony/validator does that. RedirectController moves to Routing and TemplateController to TwigBundle. Bundle services are created on demand, so the additional registrations do not add request overhead. FrameworkBundle remains the core HTTP framework.

Bundle authors receive ConfigBuilder methods named aliasOf() and appendFromCallback(). The first forwards a root configuration node to another extension, which keeps framework.workflows compatible with the workflow configuration. The second adds nodes from a callback and preserves the fluent builder chain. Existing classes moved out of FrameworkBundle are deprecated.

Security adds sudo-style reauthentication. IS_AUTHENTICATED_RECENTLY accepts credentials entered within the previous two hours, and IS_AUTHENTICATED_VERY_RECENTLY uses a five-minute window by default. The checks work in access_control and Twig as well as with controller attributes. Security expressions gain is_recently_authenticated() and is_very_recently_authenticated(). A remember-me cookie never satisfies either check. Both lifetimes are configurable in seconds through recent_authentication_lifetime and very_recent_authentication_lifetime. A failed check returns HTTP 403 unless a reauthentication entry point is configured.

The new ReAuthenticationEntryPointInterface lets an application redirect the user to a password-confirmation page and return them to the original action. The firewall option is re_authentication_entry_point. Symfony’s OIDC authenticator implements the interface and can send the user back to the provider with prompt=login. Symfony also checks the ID token auth_time claim, so a silent sign-in through an old provider session does not count as recent authentication. Authentication tokens record methods and their latest timestamps. Method names follow RFC 8176, OIDC reads them from amr, and custom authenticators can add them with AuthenticationMethodBadge. A custom trust resolver can require evidence such as AuthenticationMethod::HARDWARE_KEY within a five-minute period.

Symfony 8.2 also adds a native oidc_login authenticator for the OpenID Connect Authorization Code Flow. Mathieu Santostefano led this work. The required packages are symfony/http-client and web-token/jwt-library. Provider endpoints come from the .well-known/openid-configuration document. Protected requests go to the provider, which returns to /oidc/callback by default. The Symfony Flex recipe imports the login routes, including _oidc_login_start_main. State and nonce protect the flow, PKCE is enabled by default, and ID token signatures are checked against cached JWKS keys. Symfony validates iss, aud, exp, iat and the response iss value. Provider endpoints require HTTPS, except loopback hosts in local development, and redirects are not followed.

The built-in OIDC provider can create users from claims. A custom AttributesBasedUserProviderInterface implementation receives all claims as the second argument of loadUserByIdentifier(). user_identifier_claim can select a claim such as email, and user_data_source can select the ID token over UserInfo. Authorization parameters can be set statically with authorization_params or dynamically through OidcAuthorizationRequestEvent. Client authentication supports client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt and none. Refresh tokens, provider logout and max_age are also supported. oidc_login deliberately adds no remember-me badge because the provider controls authentication. max_age or prompt=login controls its recency.

Messenger gains an outbox transport option and a claim_check option. The outbox first stores messages in a Doctrine transport that uses the application’s database connection, then a relay forwards them to AMQP, Amazon SQS or another target broker. A typical setup names the storage transport db_outbox and uses doctrine://default?queue_name=outbox. Separate workers run messenger:consume db_outbox and messenger:consume orders. Delays apply in the outbox. Relay failures use the outbox retry and failure transport, handling failures use the target transport, and forwarding order is not guaranteed.

claim_check stores messages above a configured encoded size, including body and headers, in a PSR-6 pool. The transport carries a random identifier and checksum. The worker retrieves and verifies the payload before handling it. Redis, Valkey, Memcached, PDO and Doctrine DBAL pools are supported. Producers and consumers need access to the same dedicated pool. Its default lifetime must cover delays, retries and failure-transport retention. Expired claims raise ClaimCheckNotFoundException inside MessageDecodingFailedException and follow the normal retry path.

Serializer changes make SerializedName and SerializedPath repeatable and let them accept groups, with YAML and XML mappings supported. A property can expose different names for API groups such as api_v1 and api_v2. AbstractNormalizer::IGNORED_GROUPS and withIgnoredGroups() exclude selected groups for a context, and #[Ignore] continues to exclude a property unconditionally. An opt-in context option adds the Validator-style Default group. Named serializers can now be assigned to MapRequestPayload, MapQueryString, Serialize and Messenger. An API serializer can use snake_case while messenger.transport.symfony_serializer uses another service. Validation errors still use the default serializer, and their property paths ignore a named serializer’s converter.

The experimental KeyManagement component provides a common API for AWS KMS, Azure Key Vault, Google Cloud KMS and HashiCorp Vault. symfony/key-management contains the interfaces, envelope encryption and local libsodium and OpenSSL backends. Provider bridges are symfony/aws-key-management, symfony/azure-keyvault-key-management, symfony/google-cloud-key-management and symfony/hashicorp-vault-key-management. The development package can be installed with composer require symfony/key-management:^8.2@dev.

Direct encryption sends data to a KMS and suits small values, with AWS KMS imposing a 4 KB limit. Envelope encryption obtains a data key, encrypts locally with AES-256-GCM and stores the wrapped key with the ciphertext. The application handles a key identifier such as an alias or ARN, never the master key. DSNs configure clients under key_management, and a sodium client with an inline key can serve development. EnvelopeEncrypterInterface, EncrypterInterface and DecrypterInterface expose the services, and #[Target] selects a non-default client. The component adds key-management:encrypt, key-management:decrypt, key-management:generate-data-key and key-management:rewrap-data-keys. The web debug toolbar shows client calls.

Doctrine bridges add an EncryptedType and a BlindIndexed attribute for searchable encrypted fields. Encryption uses randomized ciphertext, so the index stores a keyed digest for lookups. An Email index service needs a KMS client and a wrapped key generated by key-management:generate-data-key. Applications register their encrypted Doctrine types from an EncryptedTypes service during kernel boot. The DBAL bridge can store wrapped data keys in a table, leaving a 16-byte reference in each row and calling the KMS once per data key. Rewrapping can move keys to another master key or provider without rewriting encrypted data.

Other announced Symfony 8.2 work covers PGP/MIME signing and encryption through PgpSigner and PgpEncrypter. S/MIME adds on_missing_certificate, and its send_unencrypted default is deprecated because Symfony 9.0 will throw an exception for that case. Further changes include generated JSON Schema for configuration, wildcard role hierarchy inspection through debug:roles, profiler graphs, separate CDN and browser cache rules, Cache-Status reporting, faster Messenger workers with parallel processing and AMQP improvements, provider-hosted email templates with tracking controls, and broader performance work across web, API, console, development and cache-building workloads. The Symfony blog’s Living on the edge series tracks the announcements.