Skip to content

Symfony bundle

The JWT Framework Symfony Bundle provides seamless integration of the JWT Framework into your Symfony applications. It leverages Symfony's dependency injection container to automatically configure and wire all services, making it easy to work with JSON Web Tokens in your Symfony projects.

Why use the Symfony bundle?

The bundle offers several advantages for Symfony developers:

๐ŸŽฏ Zero configuration

  • Auto-discovery of algorithms and services
  • Automatic service registration
  • Sensible defaults out of the box

๐Ÿ”ง Configuration-driven

  • YAML-based configuration for all components
  • Type-safe configuration validation
  • Environment variable support

๐Ÿ“Š Developer tools

  • Symfony Profiler integration
  • Debug toolbar with token inspection
  • Data collectors for performance monitoring

๐Ÿ”„ Event system

  • Token lifecycle events
  • Hook into token creation and validation
  • Perfect for logging and auditing

๐Ÿญ Factory services

  • Pre-configured factories for common operations
  • Easy creation of builders, loaders, and validators
  • Support for multiple configurations

Installation

Info

The bundle supports Symfony 7.0 and Symfony 8.0.

The bundle is automatically detected and installed when using Symfony Flex:

composer require web-token/jwt-bundle

Info

As the recipes are third party recipes not officially supported by Symfony, you will be asked whether to execute the recipe or not. When applied, the recipes will display a message: Web Token Framework is ready.

After installation, the bundle is automatically registered and ready to use!

Without Symfony Flex

If you're not using Symfony Flex, you need to register the bundle manually:

config/bundles.php
<?php

return [
    // ...
    Jose\Bundle\JoseFramework\JoseFrameworkBundle::class => ['all' => true],
];

Quick start example

After installation, you can configure a simple JWS service:

config/packages/jose.yaml
jose:
    # Configure the algorithm manager
    jws:
        builders:
            my_jws_builder:
                signature_algorithms: ['HS256']

        verifiers:
            my_jws_verifier:
                signature_algorithms: ['HS256']

Then use it in your services:

use Jose\Component\Signature\JWSBuilder;
use Jose\Component\Signature\JWSVerifier;

class TokenService
{
    public function __construct(
        private JWSBuilder $jwsBuilder,
        private JWSVerifier $jwsVerifier
    ) {}

    public function createToken(array $claims): string
    {
        // Your token creation logic
    }
}

Bundle features

The bundle provides comprehensive support for all JWT Framework components. Explore the documentation based on your needs:

Core features

Token operations

Advanced features

Service auto-wiring

All services created through the bundle configuration are automatically available for auto-wiring. You can inject them by type or by name:

use Jose\Component\Signature\JWSBuilderFactory;
use Jose\Component\Signature\JWSVerifierFactory;

class MyService
{
    public function __construct(
        JWSBuilderFactory $jwsBuilderFactory,
        JWSVerifierFactory $jwsVerifierFactory
    ) {
        // Services are automatically injected
    }
}

Auto-wiring by interface

Every service you declare in the configuration is aliased both with its concrete class and with its interface. Naming the argument after the service picks the right one:

jose:
    jws:
        builders:
            builder1:
                signature_algorithms: ['ES256']
        verifiers:
            verifier1:
                signature_algorithms: ['ES256']
use Jose\Component\Signature\JWSBuilderInterface;
use Jose\Component\Signature\JWSVerifierInterface;

class MyService
{
    public function __construct(
        JWSBuilderInterface $builder1JwsBuilder,   // jose.jws_builder.builder1
        JWSVerifierInterface $verifier1JwsVerifier, // jose.jws_verifier.verifier1
    ) {
    }
}

The argument name is the service name followed by the kind of service: builder1 + JwsBuilder. The same convention applies to JwsLoader, JweBuilder, JweDecrypter, JweLoader, NestedTokenBuilder and NestedTokenLoader.

Info

Interfaces were introduced in 4.3. Prefer them over the concrete classes: they are what the library type-hints internally, so a decorator can be injected in place of any service. Type-hinting the concrete class keeps working.

The key factory is aliased the same way:

use Jose\Component\KeyManagement\JWKFactoryInterface;

public function __construct(private JWKFactoryInterface $jwkFactory) {}

Decorating a service

Because every service is described by an interface, decorating one is standard Symfony:

#[AsDecorator('jose.jws_loader.jws_loader1')]
final readonly class LoggingJwsLoader implements JWSLoaderInterface
{
    public function __construct(
        #[AutowireDecorated] private JWSLoaderInterface $inner,
        private LoggerInterface $logger,
    ) {
    }

    public function loadAndVerify(string $token, JWK|JWKSet $keys, ?string $payload = null): LoadingResult
    {
        $result = $this->inner->loadAndVerify($token, $keys, $payload);
        $this->logger->info('Token verified', ['kid' => $result->getKey()->find('kid')]);

        return $result;
    }

    // ... the remaining methods of the interface delegate to $this->inner
}

Warning

Extending the concrete classes โ€” JWSLoader, JWEDecrypterโ€ฆ โ€” is deprecated since 4.3 and raises a notice. Implement the interface and decorate instead. The bundle itself did the same: its event dispatching services are decorators now, and the inheritance based ones are deprecated. They keep their class names, their service ids and their behaviour, so no configuration change is needed.

Configuration reference

For a complete configuration reference, run:

php bin/console config:dump-reference jose

Next steps