diff --git a/src/Bundle/JoseFramework/DependencyInjection/Compiler/SymfonySerializerCompilerPass.php b/src/Bundle/JoseFramework/DependencyInjection/Compiler/SymfonySerializerCompilerPass.php index 578e9e2c..be2e18e0 100644 --- a/src/Bundle/JoseFramework/DependencyInjection/Compiler/SymfonySerializerCompilerPass.php +++ b/src/Bundle/JoseFramework/DependencyInjection/Compiler/SymfonySerializerCompilerPass.php @@ -4,7 +4,9 @@ namespace Jose\Bundle\JoseFramework\DependencyInjection\Compiler; +use Jose\Bundle\JoseFramework\Serializer\JWEEncoder; use Jose\Bundle\JoseFramework\Serializer\JWESerializer; +use Jose\Bundle\JoseFramework\Serializer\JWSEncoder; use Jose\Bundle\JoseFramework\Serializer\JWSSerializer; use Jose\Component\Encryption\Serializer\JWESerializerManagerFactory; use Jose\Component\Signature\Serializer\JWSSerializerManagerFactory; @@ -15,22 +17,34 @@ class SymfonySerializerCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container): void { - if (! class_exists('Symfony\Component\Serializer\Serializer')) { + if (! class_exists('Symfony\\Component\\Serializer\\Serializer')) { return; } if ($container->hasDefinition(JWSSerializerManagerFactory::class)) { - $container->autowire(JWSSerializer::class, JWSSerializer::class) + $container + ->autowire(JWSSerializer::class, JWSSerializer::class) ->setPublic(false) - ->addTag('serializer.encoder') ->addTag('serializer.normalizer') ; + + $container + ->autowire(JWSEncoder::class, JWSEncoder::class) + ->setPublic(false) + ->addTag('serializer.encoder') + ; } if ($container->hasDefinition(JWESerializerManagerFactory::class)) { - $container->autowire(JWESerializer::class, JWESerializer::class) + $container + ->autowire(JWESerializer::class, JWESerializer::class) ->setPublic(false) - ->addTag('serializer.encoder') ->addTag('serializer.normalizer') ; + + $container + ->autowire(JWEEncoder::class, JWEEncoder::class) + ->setPublic(false) + ->addTag('serializer.encoder') + ; } } } diff --git a/src/Bundle/JoseFramework/Serializer/JWEEncoder.php b/src/Bundle/JoseFramework/Serializer/JWEEncoder.php new file mode 100644 index 00000000..ac54a98f --- /dev/null +++ b/src/Bundle/JoseFramework/Serializer/JWEEncoder.php @@ -0,0 +1,91 @@ +create($serializerManagerFactory->names()); + } + $this->serializerManager = $serializerManager; + } + + public function supportsEncoding(string $format): bool + { + return class_exists(JWESerializerManager::class) && $this->formatSupported($format); + } + + public function supportsDecoding(string $format): bool + { + return class_exists(JWESerializerManager::class) && $this->formatSupported($format); + } + + public function encode(mixed $data, string $format, array $context = []): string + { + if ($data instanceof JWE === false) { + throw new LogicException('Expected data to be a JWE.'); + } + + try { + return $this->serializerManager->serialize( + mb_strtolower($format), + $data, + $this->getRecipientIndex($context) + ); + } catch (Throwable $ex) { + throw new NotEncodableValueException(sprintf('Cannot encode JWE to %s format.', $format), 0, $ex); + } + } + + public function decode(string $data, string $format, array $context = []): JWE + { + try { + return $this->serializerManager->unserialize($data); + } catch (Exception $ex) { + throw new NotEncodableValueException(sprintf('Cannot decode JWE from %s format.', $format), 0, $ex); + } + } + + /** + * Get JWE recipient index from context. + */ + private function getRecipientIndex(array $context): int + { + if (isset($context['recipient_index']) && is_int($context['recipient_index'])) { + return $context['recipient_index']; + } + + return 0; + } + + /** + * Check if format is supported. + */ + private function formatSupported(?string $format): bool + { + return $format !== null + && in_array(mb_strtolower($format), $this->serializerManager->names(), true); + } +} diff --git a/src/Bundle/JoseFramework/Serializer/JWESerializer.php b/src/Bundle/JoseFramework/Serializer/JWESerializer.php index 4e21a2f4..227efb2a 100644 --- a/src/Bundle/JoseFramework/Serializer/JWESerializer.php +++ b/src/Bundle/JoseFramework/Serializer/JWESerializer.php @@ -4,22 +4,15 @@ namespace Jose\Bundle\JoseFramework\Serializer; -use Exception; use function in_array; -use function is_int; use Jose\Component\Encryption\JWE; use Jose\Component\Encryption\Serializer\JWESerializerManager; use Jose\Component\Encryption\Serializer\JWESerializerManagerFactory; use LogicException; use function mb_strtolower; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; -use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Throwable; -final class JWESerializer implements DenormalizerInterface, EncoderInterface, DecoderInterface, NormalizationAwareInterface +final class JWESerializer implements DenormalizerInterface { private JWESerializerManager $serializerManager; @@ -33,49 +26,13 @@ public function __construct( $this->serializerManager = $serializerManager; } - public function supportsEncoding(string $format): bool - { - return $this->formatSupported($format); - } - - public function supportsDecoding(string $format): bool - { - return $this->formatSupported($format); - } - public function supportsDenormalization(mixed $data, string $type, string $format = null): bool { return $type === JWE::class - && $this->componentInstalled() + && class_exists(JWESerializerManager::class) && $this->formatSupported($format); } - public function encode(mixed $data, string $format, array $context = []): string - { - if ($data instanceof JWE === false) { - throw new LogicException('Expected data to be a JWE.'); - } - - try { - return $this->serializerManager->serialize( - mb_strtolower($format), - $data, - $this->getRecipientIndex($context) - ); - } catch (Throwable $ex) { - throw new NotEncodableValueException(sprintf('Cannot encode JWE to %s format.', $format), 0, $ex); - } - } - - public function decode(string $data, string $format, array $context = []): JWE - { - try { - return $this->serializerManager->unserialize($data); - } catch (Exception $ex) { - throw new NotEncodableValueException(sprintf('Cannot decode JWE from %s format.', $format), 0, $ex); - } - } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): JWE { if ($data instanceof JWE === false) { @@ -85,26 +42,6 @@ public function denormalize(mixed $data, string $type, string $format = null, ar return $data; } - /** - * Get JWE recipient index from context. - */ - private function getRecipientIndex(array $context): int - { - if (isset($context['recipient_index']) && is_int($context['recipient_index'])) { - return $context['recipient_index']; - } - - return 0; - } - - /** - * Check if encryption component is installed. - */ - private function componentInstalled(): bool - { - return class_exists(JWESerializerManager::class); - } - /** * Check if format is supported. */ diff --git a/src/Bundle/JoseFramework/Serializer/JWSEncoder.php b/src/Bundle/JoseFramework/Serializer/JWSEncoder.php new file mode 100644 index 00000000..ea835b1a --- /dev/null +++ b/src/Bundle/JoseFramework/Serializer/JWSEncoder.php @@ -0,0 +1,90 @@ +create($serializerManagerFactory->names()); + } + $this->serializerManager = $serializerManager; + } + + public function supportsEncoding(string $format): bool + { + return class_exists(JWSSerializerManager::class) && $this->formatSupported($format); + } + + public function supportsDecoding(string $format): bool + { + return class_exists(JWSSerializerManager::class) && $this->formatSupported($format); + } + + public function encode($data, $format, array $context = []): string + { + if ($data instanceof JWS === false) { + throw new LogicException('Expected data to be a JWS.'); + } + + try { + return $this->serializerManager->serialize( + mb_strtolower($format), + $data, + $this->getSignatureIndex($context) + ); + } catch (Exception $ex) { + throw new NotEncodableValueException(sprintf('Cannot encode JWS to %s format.', $format), 0, $ex); + } + } + + public function decode($data, $format, array $context = []): JWS + { + try { + return $this->serializerManager->unserialize($data); + } catch (Exception $ex) { + throw new NotEncodableValueException(sprintf('Cannot decode JWS from %s format.', $format), 0, $ex); + } + } + + /** + * Get JWS signature index from context. + */ + private function getSignatureIndex(array $context): int + { + if (isset($context['signature_index']) && is_int($context['signature_index'])) { + return $context['signature_index']; + } + + return 0; + } + + /** + * Check if format is supported. + */ + private function formatSupported(?string $format): bool + { + return $format !== null + && in_array(mb_strtolower($format), $this->serializerManager->list(), true); + } +} diff --git a/src/Bundle/JoseFramework/Serializer/JWSSerializer.php b/src/Bundle/JoseFramework/Serializer/JWSSerializer.php index 6e5ac535..a9a456d7 100644 --- a/src/Bundle/JoseFramework/Serializer/JWSSerializer.php +++ b/src/Bundle/JoseFramework/Serializer/JWSSerializer.php @@ -4,21 +4,15 @@ namespace Jose\Bundle\JoseFramework\Serializer; -use Exception; use function in_array; -use function is_int; use Jose\Component\Signature\JWS; use Jose\Component\Signature\Serializer\JWSSerializerManager; use Jose\Component\Signature\Serializer\JWSSerializerManagerFactory; use LogicException; use function mb_strtolower; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; -use Symfony\Component\Serializer\Encoder\NormalizationAwareInterface; -use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -final class JWSSerializer implements DenormalizerInterface, EncoderInterface, DecoderInterface, NormalizationAwareInterface +final class JWSSerializer implements DenormalizerInterface { private JWSSerializerManager $serializerManager; @@ -32,49 +26,13 @@ public function __construct( $this->serializerManager = $serializerManager; } - public function supportsEncoding(string $format): bool - { - return $this->formatSupported($format); - } - - public function supportsDecoding(string $format): bool - { - return $this->formatSupported($format); - } - public function supportsDenormalization(mixed $data, string $type, string $format = null): bool { return $type === JWS::class - && $this->componentInstalled() + && class_exists(JWSSerializerManager::class) && $this->formatSupported($format); } - public function encode($data, $format, array $context = []): string - { - if ($data instanceof JWS === false) { - throw new LogicException('Expected data to be a JWS.'); - } - - try { - return $this->serializerManager->serialize( - mb_strtolower($format), - $data, - $this->getSignatureIndex($context) - ); - } catch (Exception $ex) { - throw new NotEncodableValueException(sprintf('Cannot encode JWS to %s format.', $format), 0, $ex); - } - } - - public function decode($data, $format, array $context = []): JWS - { - try { - return $this->serializerManager->unserialize($data); - } catch (Exception $ex) { - throw new NotEncodableValueException(sprintf('Cannot decode JWS from %s format.', $format), 0, $ex); - } - } - public function denormalize(mixed $data, string $type, string $format = null, array $context = []): JWS { if ($data instanceof JWS === false) { @@ -84,26 +42,6 @@ public function denormalize(mixed $data, string $type, string $format = null, ar return $data; } - /** - * Get JWS signature index from context. - */ - private function getSignatureIndex(array $context): int - { - if (isset($context['signature_index']) && is_int($context['signature_index'])) { - return $context['signature_index']; - } - - return 0; - } - - /** - * Check if signature component is installed. - */ - private function componentInstalled(): bool - { - return class_exists(JWSSerializerManager::class); - } - /** * Check if format is supported. */ diff --git a/tests/Bundle/JoseFramework/Functional/Serializer/JWEEncoderTest.php b/tests/Bundle/JoseFramework/Functional/Serializer/JWEEncoderTest.php new file mode 100644 index 00000000..6f7b9a94 --- /dev/null +++ b/tests/Bundle/JoseFramework/Functional/Serializer/JWEEncoderTest.php @@ -0,0 +1,281 @@ +get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + static::assertTrue($serializer->supportsEncoding($format)); + static::assertInstanceOf(DecoderInterface::class, $serializer); + static::assertTrue($serializer->supportsDecoding($format)); + } + + /** + * @test + * @dataProvider jweFormatDataProvider + */ + public function aJWECanBeEncodedInAllFormats(string $format, string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jwk' => $jwk, 'jwe' => $jwe] = $this->createJWE(); + + $jweString = $serializer->encode($jwe, $format); + $this->assertEncodedJWEValid($jweString, $format); + static::assertSame(0, $this->loadJWE($jweString, $jwk)); + } + + /** + * @test + * @dataProvider jweFormatDataProvider + */ + public function aJWECanBeEncodedWithSpecificRecipient(string $format, string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jwk' => $jwk, 'jwk2' => $jwk2, 'jwe' => $jwe] = $this->createJWE(); + + // Recipient index = 0 + $jweString = $serializer->encode($jwe, $format, [ + 'recipient_index' => 0, + ]); + $this->assertEncodedJWEValid($jweString, $format); + static::assertSame(0, $this->loadJWE($jweString, $jwk)); + unset($recipient); + + // Recipient index = 1 + $jweString = $serializer->encode($jwe, $format, [ + 'recipient_index' => 1, + ]); + $this->assertEncodedJWEValid($jweString, $format); + static::assertSame($format === 'jwe_json_general' ? 1 : 0, $this->loadJWE($jweString, $jwk2)); + } + + /** + * @test + * @dataProvider encoderServiceDataProvider + */ + public function theJWEEncoderThrowsOnNonExistingRecipient(string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jwe' => $jwe] = $this->createJWE(); + + $this->expectExceptionMessage(sprintf('Cannot encode JWE to %s format.', 'jwe_compact')); + $serializer->encode($jwe, 'jwe_compact', [ + 'recipient_index' => 2, + ]); + } + + /** + * @test + */ + public function aJWECanBeEncodedWithCustomSerializerManager(): void + { + $container = static::getContainer(); + $jweSerializerManager = new JWESerializerManager([new CompactSerializer()]); + $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); + static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); + $serializer = new JWEEncoder($jweSerializerManagerFactory, $jweSerializerManager); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jwk' => $jwk, 'jwe' => $jwe] = $this->createJWE(); + + static::assertTrue($serializer->supportsEncoding('jwe_compact')); + static::assertFalse($serializer->supportsEncoding('jwe_json_flattened')); + static::assertFalse($serializer->supportsEncoding('jwe_json_general')); + static::assertTrue($serializer->supportsDecoding('jwe_compact')); + static::assertFalse($serializer->supportsDecoding('jwe_json_flattened')); + static::assertFalse($serializer->supportsDecoding('jwe_json_general')); + + $jweString = $serializer->encode($jwe, 'jwe_compact'); + $this->assertEncodedJWEValid($jweString, 'jwe_compact'); + static::assertSame(0, $this->loadJWE($jweString, $jwk)); + } + + /** + * @test + */ + public function theJWEEncoderShouldThrowOnUnsupportedFormatWhenEncoding(): void + { + $container = static::getContainer(); + $jweSerializerManager = new JWESerializerManager([new CompactSerializer()]); + $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); + static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); + $serializer = new JWEEncoder($jweSerializerManagerFactory, $jweSerializerManager); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jwe' => $jwe] = $this->createJWE(); + + $this->expectExceptionMessage('Cannot encode JWE to jwe_json_flattened format.'); + $serializer->encode($jwe, 'jwe_json_flattened'); + } + + /** + * @test + * @dataProvider jweFormatDataProvider + */ + public function aJWECanBeDecodedInAllFormats(string $format, string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(DecoderInterface::class, $serializer); + + $jweData = $this->createJWE(); + + $jwe = $serializer->decode($jweData[$format], $format); + static::assertInstanceOf(JWE::class, $jwe); + } + + /** + * @test + */ + public function theJWEEncoderShouldThrowOnUnsupportedFormatWhenDecoding(): void + { + $container = static::getContainer(); + $jweSerializerManager = new JWESerializerManager([new CompactSerializer()]); + $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); + static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); + $serializer = new JWEEncoder($jweSerializerManagerFactory, $jweSerializerManager); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jwe_json_flattened' => $jweString] = $this->createJWE(); + + $this->expectExceptionMessage('Cannot decode JWE from jwe_json_flattened format.'); + $serializer->decode($jweString, 'jwe_json_flattened'); + } + + public function encoderServiceDataProvider(): array + { + return [ + 'indirect serializer' => ['serializer'], + 'direct serializer' => [JWEEncoder::class], + ]; + } + + public function jweFormatDataProvider(): array + { + return [ + 'jwe_compact with indirect serializer' => ['jwe_compact', 'serializer'], + 'jwe_compact with direct serializer' => ['jwe_compact', JWEEncoder::class], + 'jwe_json_flattened with indirect serializer' => ['jwe_json_flattened', 'serializer'], + 'jwe_json_flattened with direct serializer' => ['jwe_json_flattened', JWEEncoder::class], + 'jwe_json_general with indirect serializer' => ['jwe_json_general', 'serializer'], + 'jwe_json_general with direct serializer' => ['jwe_json_general', JWEEncoder::class], + ]; + } + + private function assertEncodedJWEValid(string $jwe, string $format): void + { + if ($format === 'jwe_compact') { + static::assertMatchesRegularExpression('/^.+\..+\..+$/', $jwe); + static::assertStringStartsWith('eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0', $jwe); + + return; + } + + static::assertJson($jwe); + } + + private function loadJWE(string $jwe, JWK $jwk): int + { + $container = static::getContainer(); + $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); + static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); + $jweLoaderFactory = $container->get(JWELoaderFactory::class); + static::assertInstanceOf(JWELoaderFactory::class, $jweLoaderFactory); + $loader = $jweLoaderFactory->create($jweSerializerManagerFactory->names(), ['A256KW'], ['A256CBC-HS512'], []); + + $loader->loadAndDecryptWithKey($jwe, $jwk, $recipient); + + return $recipient; + } + + private function createJWE(): array + { + $container = static::getContainer(); + $jweFactory = $container->get(JWEBuilderFactory::class); + static::assertInstanceOf(JWEBuilderFactory::class, $jweFactory); + $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); + static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); + $jweSerializerManager = $jweSerializerManagerFactory->create($jweSerializerManagerFactory->names()); + static::assertInstanceOf(JWESerializerManager::class, $jweSerializerManager); + + $builder = $jweFactory->create(['A256KW'], ['A256CBC-HS512'], []); + + $jwk = new JWK([ + 'kty' => 'oct', + 'k' => '3pWc2vAZpHoV7XmCT-z2hWhdQquwQwW5a3XTojbf87c', + ]); + $jwk2 = new JWK([ + 'kty' => 'oct', + 'k' => '1MVYnFKurkDCueAM6FaMlojPPUMrKitzgzCEt3qrQdc', + ]); + + $jwe = $builder + ->create() + ->withPayload('Hello World!') + ->withSharedProtectedHeader([ + 'alg' => 'A256KW', + 'enc' => 'A256CBC-HS512', + ]) + ->addRecipient($jwk) + ->addRecipient($jwk2) + ->build() + ; + + return [ + 'jwk' => $jwk, + 'jwk2' => $jwk2, + 'jwe' => $jwe, + 'alg' => 'A256KW', + 'enc' => 'A256CBC-HS512', + 'jwe_compact' => $jweSerializerManager->serialize('jwe_compact', $jwe), + 'jwe_json_flattened' => $jweSerializerManager->serialize('jwe_json_flattened', $jwe), + 'jwe_json_general' => $jweSerializerManager->serialize('jwe_json_general', $jwe), + ]; + } +} diff --git a/tests/Bundle/JoseFramework/Functional/Serializer/JWESerializerTest.php b/tests/Bundle/JoseFramework/Functional/Serializer/JWESerializerTest.php index e5ece51e..68da06f5 100644 --- a/tests/Bundle/JoseFramework/Functional/Serializer/JWESerializerTest.php +++ b/tests/Bundle/JoseFramework/Functional/Serializer/JWESerializerTest.php @@ -6,16 +6,12 @@ use Jose\Bundle\JoseFramework\Serializer\JWESerializer; use Jose\Bundle\JoseFramework\Services\JWEBuilderFactory; -use Jose\Bundle\JoseFramework\Services\JWELoaderFactory; use Jose\Component\Core\JWK; use Jose\Component\Encryption\JWE; use Jose\Component\Encryption\JWEBuilderFactory as BaseJWEBuilderFactory; -use Jose\Component\Encryption\Serializer\CompactSerializer; use Jose\Component\Encryption\Serializer\JWESerializerManager; use Jose\Component\Encryption\Serializer\JWESerializerManagerFactory; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Serializer; @@ -43,10 +39,8 @@ public function theJWESerializerSupportsAllFormatsByDefault(string $format, stri { $container = static::getContainer(); $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - static::assertTrue($serializer->supportsEncoding($format)); - static::assertInstanceOf(DecoderInterface::class, $serializer); - static::assertTrue($serializer->supportsDecoding($format)); + static::assertInstanceOf(DenormalizerInterface::class, $serializer); + static::assertTrue($serializer->supportsDenormalization(null, JWE::class, $format)); } /** @@ -63,147 +57,6 @@ public function aJWECannotBeNormalized(): void static::assertFalse(method_exists($serializer, 'supportsNormalization')); } - /** - * @test - * @dataProvider jweFormatDataProvider - */ - public function aJWECanBeEncodedInAllFormats(string $format, string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jwk' => $jwk, 'jwe' => $jwe] = $this->createJWE(); - - $jweString = $serializer->encode($jwe, $format); - $this->assertEncodedJWEValid($jweString, $format); - static::assertSame(0, $this->loadJWE($jweString, $jwk)); - } - - /** - * @test - * @dataProvider jweFormatDataProvider - */ - public function aJWECanBeEncodedWithSpecificRecipient(string $format, string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jwk' => $jwk, 'jwk2' => $jwk2, 'jwe' => $jwe] = $this->createJWE(); - - // Recipient index = 0 - $jweString = $serializer->encode($jwe, $format, [ - 'recipient_index' => 0, - ]); - $this->assertEncodedJWEValid($jweString, $format); - static::assertSame(0, $this->loadJWE($jweString, $jwk)); - unset($recipient); - - // Recipient index = 1 - $jweString = $serializer->encode($jwe, $format, [ - 'recipient_index' => 1, - ]); - $this->assertEncodedJWEValid($jweString, $format); - static::assertSame($format === 'jwe_json_general' ? 1 : 0, $this->loadJWE($jweString, $jwk2)); - } - - /** - * @test - * @dataProvider serializerServiceDataProvider - */ - public function theJWESerializerThrowsOnNonExistingRecipient(string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jwe' => $jwe] = $this->createJWE(); - - $this->expectExceptionMessage(sprintf('Cannot encode JWE to %s format.', 'jwe_compact')); - $serializer->encode($jwe, 'jwe_compact', [ - 'recipient_index' => 2, - ]); - } - - /** - * @test - */ - public function aJWECanBeEncodedWithCustomSerializerManager(): void - { - $container = static::getContainer(); - $jweSerializerManager = new JWESerializerManager([new CompactSerializer()]); - $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); - static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); - $serializer = new JWESerializer($jweSerializerManagerFactory, $jweSerializerManager); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jwk' => $jwk, 'jwe' => $jwe] = $this->createJWE(); - - static::assertTrue($serializer->supportsEncoding('jwe_compact')); - static::assertFalse($serializer->supportsEncoding('jwe_json_flattened')); - static::assertFalse($serializer->supportsEncoding('jwe_json_general')); - static::assertTrue($serializer->supportsDecoding('jwe_compact')); - static::assertFalse($serializer->supportsDecoding('jwe_json_flattened')); - static::assertFalse($serializer->supportsDecoding('jwe_json_general')); - - $jweString = $serializer->encode($jwe, 'jwe_compact'); - $this->assertEncodedJWEValid($jweString, 'jwe_compact'); - static::assertSame(0, $this->loadJWE($jweString, $jwk)); - } - - /** - * @test - */ - public function theJWESerializerShouldThrowOnUnsupportedFormatWhenEncoding(): void - { - $container = static::getContainer(); - $jweSerializerManager = new JWESerializerManager([new CompactSerializer()]); - $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); - static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); - $serializer = new JWESerializer($jweSerializerManagerFactory, $jweSerializerManager); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jwe' => $jwe] = $this->createJWE(); - - $this->expectExceptionMessage('Cannot encode JWE to jwe_json_flattened format.'); - $serializer->encode($jwe, 'jwe_json_flattened'); - } - - /** - * @test - * @dataProvider jweFormatDataProvider - */ - public function aJWECanBeDecodedInAllFormats(string $format, string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(DecoderInterface::class, $serializer); - - $jweData = $this->createJWE(); - - $jwe = $serializer->decode($jweData[$format], $format); - static::assertInstanceOf(JWE::class, $jwe); - } - - /** - * @test - */ - public function theJWESerializerShouldThrowOnUnsupportedFormatWhenDecoding(): void - { - $container = static::getContainer(); - $jweSerializerManager = new JWESerializerManager([new CompactSerializer()]); - $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); - static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); - $serializer = new JWESerializer($jweSerializerManagerFactory, $jweSerializerManager); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jwe_json_flattened' => $jweString] = $this->createJWE(); - - $this->expectExceptionMessage('Cannot decode JWE from jwe_json_flattened format.'); - $serializer->decode($jweString, 'jwe_json_flattened'); - } - /** * @test * @dataProvider jweFormatDataProvider @@ -240,32 +93,6 @@ public function jweFormatDataProvider(): array ]; } - private function assertEncodedJWEValid(string $jwe, string $format): void - { - if ($format === 'jwe_compact') { - static::assertMatchesRegularExpression('/^.+\..+\..+$/', $jwe); - static::assertStringStartsWith('eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0', $jwe); - - return; - } - - static::assertJson($jwe); - } - - private function loadJWE(string $jwe, JWK $jwk): int - { - $container = static::getContainer(); - $jweSerializerManagerFactory = $container->get(JWESerializerManagerFactory::class); - static::assertInstanceOf(JWESerializerManagerFactory::class, $jweSerializerManagerFactory); - $jweLoaderFactory = $container->get(JWELoaderFactory::class); - static::assertInstanceOf(JWELoaderFactory::class, $jweLoaderFactory); - $loader = $jweLoaderFactory->create($jweSerializerManagerFactory->names(), ['A256KW'], ['A256CBC-HS512'], []); - - $loader->loadAndDecryptWithKey($jwe, $jwk, $recipient); - - return $recipient; - } - private function createJWE(): array { $container = static::getContainer(); diff --git a/tests/Bundle/JoseFramework/Functional/Serializer/JWSEncoderTest.php b/tests/Bundle/JoseFramework/Functional/Serializer/JWSEncoderTest.php new file mode 100644 index 00000000..230e6e2c --- /dev/null +++ b/tests/Bundle/JoseFramework/Functional/Serializer/JWSEncoderTest.php @@ -0,0 +1,254 @@ +get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + static::assertTrue($serializer->supportsEncoding($format)); + static::assertInstanceOf(DecoderInterface::class, $serializer); + static::assertTrue($serializer->supportsDecoding($format)); + } + + /** + * @test + * @dataProvider jwsFormatDataProvider + */ + public function aJWSCanBeEncodedInAllFormats(string $format, string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jws' => $jws] = $this->createJWS(true); + + $jwsString = $serializer->encode($jws, $format); + $expected = [ + 'jws_compact' => 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY', + 'jws_json_flattened' => '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY"}', + 'jws_json_general' => '{"payload":"SGVsbG8gV29ybGQh","signatures":[{"signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY","protected":"eyJhbGciOiJIUzI1NiJ9"},{"signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU","protected":"eyJhbGciOiJIUzI1NiJ9"}]}', + ]; + static::assertSame($expected[$format], $jwsString); + } + + /** + * @test + * @dataProvider jwsFormatDataProvider + */ + public function aJWSCanBeEncodedWithSpecificSignature(string $format, string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jws' => $jws] = $this->createJWS(true); + + // Recipient index = 0 + $jwsString = $serializer->encode($jws, $format, [ + 'signature_index' => 0, + ]); + $expected = [ + 'jws_compact' => 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY', + 'jws_json_flattened' => '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY"}', + 'jws_json_general' => '{"payload":"SGVsbG8gV29ybGQh","signatures":[{"signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY","protected":"eyJhbGciOiJIUzI1NiJ9"},{"signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU","protected":"eyJhbGciOiJIUzI1NiJ9"}]}', + ]; + static::assertSame($expected[$format], $jwsString); + + // Recipient index = 1 + $jwsString = $serializer->encode($jws, $format, [ + 'signature_index' => 1, + ]); + $expected = [ + 'jws_compact' => 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU', + 'jws_json_flattened' => '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU"}', + 'jws_json_general' => '{"payload":"SGVsbG8gV29ybGQh","signatures":[{"signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY","protected":"eyJhbGciOiJIUzI1NiJ9"},{"signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU","protected":"eyJhbGciOiJIUzI1NiJ9"}]}', + ]; + static::assertSame($expected[$format], $jwsString); + } + + /** + * @test + */ + public function aJWSCanBeEncodedWithCustomSerializerManager(): void + { + $container = static::getContainer(); + $jwsSerializerManager = new JWSSerializerManager([new CompactSerializer()]); + $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); + static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); + $serializer = new JWSEncoder($jwsSerializerManagerFactory, $jwsSerializerManager); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jws' => $jws] = $this->createJWS(); + + static::assertTrue($serializer->supportsEncoding('jws_compact')); + static::assertFalse($serializer->supportsEncoding('jws_json_flattened')); + static::assertFalse($serializer->supportsEncoding('jws_json_general')); + static::assertTrue($serializer->supportsDecoding('jws_compact')); + static::assertFalse($serializer->supportsDecoding('jws_json_flattened')); + static::assertFalse($serializer->supportsDecoding('jws_json_general')); + + static::assertSame( + 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY', + $serializer->encode($jws, 'jws_compact') + ); + } + + /** + * @test + */ + public function theJWSSerializerShouldThrowOnUnsupportedFormatWhenEncoding(): void + { + $container = static::getContainer(); + $jwsSerializerManager = new JWSSerializerManager([new CompactSerializer()]); + $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); + static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); + $serializer = new JWSEncoder($jwsSerializerManagerFactory, $jwsSerializerManager); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + ['jws' => $jws] = $this->createJWS(); + + $this->expectExceptionMessage('Cannot encode JWS to jws_json_flattened format.'); + $serializer->encode($jws, 'jws_json_flattened'); + } + + /** + * @test + * @dataProvider jwsFormatDataProvider + */ + public function aJWSCanBeDecodedInAllFormats(string $format, string $serializerId): void + { + $container = static::getContainer(); + $serializer = $container->get($serializerId); + static::assertInstanceOf(DecoderInterface::class, $serializer); + + $jwsData = $this->createJWS(); + + $jws = $serializer->decode($jwsData[$format], $format); + static::assertInstanceOf(JWS::class, $jws); + static::assertEqualsCanonicalizing($jwsData['jws'], $jws); + } + + /** + * @test + */ + public function theJWSSerializerShouldThrowOnUnsupportedFormatWhenDecoding(): void + { + $container = static::getContainer(); + $jwsSerializerManager = new JWSSerializerManager([new CompactSerializer()]); + $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); + static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); + $serializer = new JWSEncoder($jwsSerializerManagerFactory, $jwsSerializerManager); + static::assertInstanceOf(EncoderInterface::class, $serializer); + + $jwsString = '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU"}'; + + $this->expectExceptionMessage('Cannot decode JWS from jws_json_flattened format.'); + $serializer->decode($jwsString, 'jws_json_flattened'); + } + + public function serializerServiceDataProvider(): array + { + return [ + 'indirect serializer' => ['serializer'], + 'direct serializer' => [JWSEncoder::class], + ]; + } + + public function jwsFormatDataProvider(): array + { + return [ + 'jws_compact with indirect serializer' => ['jws_compact', 'serializer'], + 'jws_compact with direct serializer' => ['jws_compact', JWSEncoder::class], + 'jws_json_flattened with indirect serializer' => ['jws_json_flattened', 'serializer'], + 'jws_json_flattened with direct serializer' => ['jws_json_flattened', JWSEncoder::class], + 'jws_json_general with indirect serializer' => ['jws_json_general', 'serializer'], + 'jws_json_general with direct serializer' => ['jws_json_general', JWSEncoder::class], + ]; + } + + private function createJWS(bool $multiSignature = false): array + { + $container = static::getContainer(); + $jwsFactory = $container->get(JWSBuilderFactory::class); + static::assertInstanceOf(JWSBuilderFactory::class, $jwsFactory); + $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); + static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); + $jwsSerializerManager = $jwsSerializerManagerFactory->create($jwsSerializerManagerFactory->names()); + static::assertInstanceOf(JWSSerializerManager::class, $jwsSerializerManager); + + $builder = $jwsFactory->create(['HS256']); + + $jwk = new JWK([ + 'kty' => 'oct', + 'k' => '3pWc2vAZpHoV7XmCT-z2hWhdQquwQwW5a3XTojbf87c', + ]); + $jwk2 = $multiSignature + ? new JWK([ + 'kty' => 'oct', + 'k' => '45d2aGyfduzrkcmL7duvUTDTlXS2s3u4uMER2feQruU', + ]) + : null; + + $jwsBuilder = $builder + ->create() + ->withPayload('Hello World!') + ->addSignature($jwk, [ + 'alg' => 'HS256', + ]) + ; + + if ($multiSignature) { + $jwsBuilder = $jwsBuilder->addSignature($jwk2, [ + 'alg' => 'HS256', + ]); + } + + $jws = $jwsBuilder->build(); + + return [ + 'jwk' => $jwk, + 'jwk2' => $jwk2, + 'jws' => $jws, + 'alg' => 'HS256', + 'jws_compact' => $jwsSerializerManager->serialize('jws_compact', $jws), + 'jws_json_flattened' => $jwsSerializerManager->serialize('jws_json_flattened', $jws), + 'jws_json_general' => $jwsSerializerManager->serialize('jws_json_general', $jws), + ]; + } +} diff --git a/tests/Bundle/JoseFramework/Functional/Serializer/JWSSerializerTest.php b/tests/Bundle/JoseFramework/Functional/Serializer/JWSSerializerTest.php index 2c2ebc2f..b409be44 100644 --- a/tests/Bundle/JoseFramework/Functional/Serializer/JWSSerializerTest.php +++ b/tests/Bundle/JoseFramework/Functional/Serializer/JWSSerializerTest.php @@ -9,12 +9,9 @@ use Jose\Component\Core\JWK; use Jose\Component\Signature\JWS; use Jose\Component\Signature\JWSBuilderFactory as BaseJWSBuilderFactory; -use Jose\Component\Signature\Serializer\CompactSerializer; use Jose\Component\Signature\Serializer\JWSSerializerManager; use Jose\Component\Signature\Serializer\JWSSerializerManagerFactory; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Serializer; @@ -42,10 +39,8 @@ public function theJWSSerializerSupportsAllFormatsByDefault(string $format, stri { $container = static::getContainer(); $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - static::assertTrue($serializer->supportsEncoding($format)); - static::assertInstanceOf(DecoderInterface::class, $serializer); - static::assertTrue($serializer->supportsDecoding($format)); + static::assertInstanceOf(DenormalizerInterface::class, $serializer); + static::assertTrue($serializer->supportsDenormalization(null, JWS::class, $format)); } /** @@ -62,142 +57,6 @@ public function aJWSCannotBeNormalized(): void static::assertFalse(method_exists($serializer, 'supportsNormalization')); } - /** - * @test - * @dataProvider jwsFormatDataProvider - */ - public function aJWSCanBeEncodedInAllFormats(string $format, string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jws' => $jws] = $this->createJWS(true); - - $jwsString = $serializer->encode($jws, $format); - $expected = [ - 'jws_compact' => 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY', - 'jws_json_flattened' => '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY"}', - 'jws_json_general' => '{"payload":"SGVsbG8gV29ybGQh","signatures":[{"signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY","protected":"eyJhbGciOiJIUzI1NiJ9"},{"signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU","protected":"eyJhbGciOiJIUzI1NiJ9"}]}', - ]; - static::assertSame($expected[$format], $jwsString); - } - - /** - * @test - * @dataProvider jwsFormatDataProvider - */ - public function aJWSCanBeEncodedWithSpecificSignature(string $format, string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jws' => $jws] = $this->createJWS(true); - - // Recipient index = 0 - $jwsString = $serializer->encode($jws, $format, [ - 'signature_index' => 0, - ]); - $expected = [ - 'jws_compact' => 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY', - 'jws_json_flattened' => '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY"}', - 'jws_json_general' => '{"payload":"SGVsbG8gV29ybGQh","signatures":[{"signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY","protected":"eyJhbGciOiJIUzI1NiJ9"},{"signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU","protected":"eyJhbGciOiJIUzI1NiJ9"}]}', - ]; - static::assertSame($expected[$format], $jwsString); - - // Recipient index = 1 - $jwsString = $serializer->encode($jws, $format, [ - 'signature_index' => 1, - ]); - $expected = [ - 'jws_compact' => 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU', - 'jws_json_flattened' => '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU"}', - 'jws_json_general' => '{"payload":"SGVsbG8gV29ybGQh","signatures":[{"signature":"qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY","protected":"eyJhbGciOiJIUzI1NiJ9"},{"signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU","protected":"eyJhbGciOiJIUzI1NiJ9"}]}', - ]; - static::assertSame($expected[$format], $jwsString); - } - - /** - * @test - */ - public function aJWSCanBeEncodedWithCustomSerializerManager(): void - { - $container = static::getContainer(); - $jwsSerializerManager = new JWSSerializerManager([new CompactSerializer()]); - $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); - static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); - $serializer = new JWSSerializer($jwsSerializerManagerFactory, $jwsSerializerManager); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jws' => $jws] = $this->createJWS(); - - static::assertTrue($serializer->supportsEncoding('jws_compact')); - static::assertFalse($serializer->supportsEncoding('jws_json_flattened')); - static::assertFalse($serializer->supportsEncoding('jws_json_general')); - static::assertTrue($serializer->supportsDecoding('jws_compact')); - static::assertFalse($serializer->supportsDecoding('jws_json_flattened')); - static::assertFalse($serializer->supportsDecoding('jws_json_general')); - - static::assertSame( - 'eyJhbGciOiJIUzI1NiJ9.SGVsbG8gV29ybGQh.qTzr2HflJbt-MDo1Ye7i5W85avH4hrhvb1U6tbd_mzY', - $serializer->encode($jws, 'jws_compact') - ); - } - - /** - * @test - */ - public function theJWSSerializerShouldThrowOnUnsupportedFormatWhenEncoding(): void - { - $container = static::getContainer(); - $jwsSerializerManager = new JWSSerializerManager([new CompactSerializer()]); - $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); - static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); - $serializer = new JWSSerializer($jwsSerializerManagerFactory, $jwsSerializerManager); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - ['jws' => $jws] = $this->createJWS(); - - $this->expectExceptionMessage('Cannot encode JWS to jws_json_flattened format.'); - $serializer->encode($jws, 'jws_json_flattened'); - } - - /** - * @test - * @dataProvider jwsFormatDataProvider - */ - public function aJWSCanBeDecodedInAllFormats(string $format, string $serializerId): void - { - $container = static::getContainer(); - $serializer = $container->get($serializerId); - static::assertInstanceOf(DecoderInterface::class, $serializer); - - $jwsData = $this->createJWS(); - - $jws = $serializer->decode($jwsData[$format], $format); - static::assertInstanceOf(JWS::class, $jws); - static::assertEqualsCanonicalizing($jwsData['jws'], $jws); - } - - /** - * @test - */ - public function theJWSSerializerShouldThrowOnUnsupportedFormatWhenDecoding(): void - { - $container = static::getContainer(); - $jwsSerializerManager = new JWSSerializerManager([new CompactSerializer()]); - $jwsSerializerManagerFactory = $container->get(JWSSerializerManagerFactory::class); - static::assertInstanceOf(JWSSerializerManagerFactory::class, $jwsSerializerManagerFactory); - $serializer = new JWSSerializer($jwsSerializerManagerFactory, $jwsSerializerManager); - static::assertInstanceOf(EncoderInterface::class, $serializer); - - $jwsString = '{"payload":"SGVsbG8gV29ybGQh","protected":"eyJhbGciOiJIUzI1NiJ9","signature":"ZIKPsa3NtNoACjvh6fhfg6PZgmKiuss_9sDPtMZxtNU"}'; - - $this->expectExceptionMessage('Cannot decode JWS from jws_json_flattened format.'); - $serializer->decode($jwsString, 'jws_json_flattened'); - } - /** * @test * @dataProvider jwsFormatDataProvider