Nested Tokens

Last updated last month

JWT can be signed or encrypted and both operations can be performed when you needed. This library is able to create and load nested tokens using dedicated classes.

The NestedTokenLoader and NestedTokenBuilder classes are available when the web-token/jwt-encryption component is installed. However, you must also install the following component to use it:

  • web-token/jwt-checker

  • web-token/jwt-signature

Nested Token Loading

To instantiate the NestedTokenLoader, you just need a JWSLoader and a JWELoader.

use Jose\Component\Encryption\NestedTokenLoader;
$nestedTokenLoader = new NestedTokenLoader($jweLoader, $jwsLoader);

Its use is very straightforward, you just have to call the method load using the token, the encryption and signature key sets. The last argument ($signature in the following example) will represents the signature used to verify the signed token. You should use this variable if the returned JWS object contains more than one signature.

$jws = $nestedTokenLoader->load($token, $encryptionKeySet, $signatureKeySet, $signature);

Nested Token Building

To instantiate the NestedTokenBuilderder, you will need a JWSBuilder, a JWEBuilder, a JWESerializerManager and a JWSSerializerManager.

use Jose\Component\Encryption\NestedTokenBuilder;
$nestedTokenBuilder = new NestedTokenBuilder($jweLoader, $jweSerializerManager, $jwsLoader, $jwsSerializerManager);

Its use is a bit more complicated than the loading as the nested token may be designed for several recipients or may have several signatures.

$token = $builder->create(
$payload, // The payload to protect
[[ // A list of signatures. 'key' is mandatory and at least one of 'protected_header'/'header' has to be set.
'key' => $signature_key, // The key used to sign. Mandatory.
'protected_header' => ['alg' => 'PS256'], // The protected header. Optional.
'header' => ['foo' => 'bar'], // The unprotected header. Optional.
'jws_json_flattened', // The serialization mode for the JWS
['alg' => 'RSA-OAEP', 'enc' => 'A128GCM'], // The shared protected header. Optional.
['foo' => 'bar'], // The shared unprotected header. Optional.
[[ // A list of recipients. 'key' is mandatory.
'key' => $encryption_key, // The recipient key.
'header' => ['bar' => 'foo'], // The recipient unprotected header.
'jwe_json_flattened' // The serialization mode for the JWE.
'1, 2, 3, 4' // Additional Authenticated Data (AAD). Optional.

As a remainder, if one of the following parameter is set, the compact serialization mode cannot be used:

  • signature unprotected header,

  • JWE shared unprotected header,

  • recipient unprotected header,

  • Additional Authenticated Data.

Symfony Bundle


Hereafter an example of a Symfony application configuration:

signature_algorithms: ['PS256']
key_encryption_algorithms: ['RSA-OAEP']
content_encryption_algorithms: ['A128GCM']
jws_serializers: ['jws_compact']
jws_header_checkers: [...]
jwe_serializers: ['jwe_compact']
jwe_header_checkers: [...]
is_public: true
signature_algorithms: ['PS256']
key_encryption_algorithms: ['RSA-OAEP']
content_encryption_algorithms: ['A128GCM']
jws_serializers: ['jws_compact']
jwe_serializers: ['jwe_compact']
is_public: true

This configuration will create two public services:

  • jose.nested_token_loader.loader_1

  • jose.nested_token_builder.builder_1

These services can be called from the container (unless private) or injected in your services.

Configuration Helper

As any other services, you can create a nested token loader or builder from another bundle extension. The following bundle extension class will create the same configuration and services as above.

class AcmeExtension extends Extension implements PrependExtensionInterface
* {@inheritdoc}
public function prepend(ContainerBuilder $container)
ConfigurationHelper::addNestedTokenLoader($container, 'loader_1', ['jwe_compact'], ['RSA-OAEP'], ['A128GCM'], ['DEF'], [], ['jws_compact'], ['PS256'], [], true, []);
ConfigurationHelper::addNestedTokenBuilder($container, 'builder_1', ['jwe_compact'], ['RSA-OAEP'], ['A128GCM'], ['DEF'], ['jws_compact'], ['PS256'], true, []);