# Nested Tokens

JWT can be signed or encrypted and both. A nested token is a signed token enclosed in an encrypted one. This order is very important: signed then encrypted.

The `NestedTokenLoader` and `NestedTokenBuilder` classes will help you to create nested tokens with ease. Just instal the package `web-token/jwt-nested-token`. It contains all the classes and dependencies will be directly managed by composer. You can install it if needed.

## Nested Token Loading

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

```php
use Jose\Component\NestedToken\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 index of the verified signature. This is only useful when multiple signature support is used.

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

## Nested Token Building

To instantiate the `NestedTokenBuilder`, you will need the following components:

* a `JWSBuilder`,
* a `JWEBuilder`,&#x20;
* a `JWESerializerManager`,
* a `JWSSerializerManager`

```php
use Jose\Component\NestedToken\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.

```php
$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 reminder, 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

### Configuration

Hereafter an example of a Symfony application configuration:

```yaml
jose:
    nested_token:
        loaders:
            loader_1:
                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
        builders:
            builder_1:
                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.

```php
class AcmeExtension extends Extension implements PrependExtensionInterface
{
    ...

    public function prepend(ContainerBuilder $container)
    {
        ConfigurationHelper::addNestedTokenLoader($container, 'loader_1', ['jwe_compact'], ['RSA-OAEP'], ['A128GCM'], [], ['jws_compact'], ['PS256'], [], true, []);
        ConfigurationHelper::addNestedTokenBuilder($container, 'builder_1', ['jwe_compact'], ['RSA-OAEP'], ['A128GCM'], ['jws_compact'], ['PS256'], true, []);
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://web-token.spomky-labs.com/v4.0/advanced-topics/nested-tokens.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
