Skip to content

Commit

Permalink
CS and PHPStan rules updated
Browse files Browse the repository at this point in the history
  • Loading branch information
Spomky committed Aug 1, 2020
1 parent 62fd1b2 commit 72c3d82
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 193 deletions.
5 changes: 5 additions & 0 deletions .php_cs.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ return PhpCsFixer\Config::create()
'@PSR1' => true,
'@PSR2' => true,
'@Symfony' => true,
'@PhpCsFixer' => true,
'@DoctrineAnnotation' => true,
'@PHP70Migration' => true,
'@PHP71Migration' => true,
Expand All @@ -34,8 +35,10 @@ return PhpCsFixer\Config::create()
'native_function_invocation' => [
'include' => ['@compiler_optimized'],
'scope' => 'namespaced',
'strict' => true,
],
'mb_str_functions' => true,
'method_chaining_indentation' => true,
'linebreak_after_opening_tag' => true,
'combine_consecutive_issets' => true,
'combine_consecutive_unsets' => true,
Expand All @@ -56,6 +59,8 @@ return PhpCsFixer\Config::create()
'style' => 'annotation',
],
'php_unit_test_case_static_method_calls' => true,
'php_unit_expectation' => true,
'php_unit_test_class_requires_covers' => false,
'global_namespace_import' => [
'import_classes' => true,
'import_constants' => true,
Expand Down
150 changes: 76 additions & 74 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,62 +32,63 @@ public function getConfigTreeBuilder(): TreeBuilder
}
$rootNode
->validate()
->ifTrue(static function(array $config): bool {
->ifTrue(static function (array $config): bool {
return !isset($config['key_set']) && !isset($config['key_set_remote']);
})
->thenInvalid('You must either configure a "key_set" or a "key_set_remote".')
->thenInvalid('You must either configure a "key_set" or a "key_set_remote".')
->end()
->addDefaultsIfNotSet()
->children()
->scalarNode('server_name')
->info('The name of the server. The recommended value is the server URL. This value will be used to check the issuer of the token.')
->isRequired()
->end()
->scalarNode('audience')
->info('The audience of the token. If not set `server_name` will be used.')
->end()
->integerNode('ttl')
->info('The lifetime of a token (in second). For security reasons, a value below 1 hour (3600 sec) is recommended.')
->min(0)
->defaultValue(1800)
->end()
->scalarNode('key_set')
->info('Private/Shared keys used by this server to validate signed tokens. Must be a JWKSet object.')
->end()
->arrayNode('key_set_remote')
->children()
->scalarNode('type')
->info('The type of the remote key set, either `jku` or `x5u`.')
->end()
->scalarNode('url')
->info('The URL from where the key set should be downloaded.')
->end()
->end()
->end()
->scalarNode('key_index')
->info('Index of the key in the key set used to sign the tokens. Could be an integer or the key ID.')
->isRequired()
->end()
->scalarNode('signature_algorithm')
->info('Signature algorithm used to sign the tokens.')
->isRequired()
->end()
->arrayNode('claim_checked')
->info('List of aliases to claim checkers.')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->treatNullLike([])
->treatFalseLike([])
->end()
->arrayNode('mandatory_claims')
->info('List of claims that must be present.')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->defaultValue([])
->treatNullLike([])
->treatFalseLike([])
->end()
->end();
->scalarNode('server_name')
->info('The name of the server. The recommended value is the server URL. This value will be used to check the issuer of the token.')
->isRequired()
->end()
->scalarNode('audience')
->info('The audience of the token. If not set `server_name` will be used.')
->end()
->integerNode('ttl')
->info('The lifetime of a token (in second). For security reasons, a value below 1 hour (3600 sec) is recommended.')
->min(0)
->defaultValue(1800)
->end()
->scalarNode('key_set')
->info('Private/Shared keys used by this server to validate signed tokens. Must be a JWKSet object.')
->end()
->arrayNode('key_set_remote')
->children()
->scalarNode('type')
->info('The type of the remote key set, either `jku` or `x5u`.')
->end()
->scalarNode('url')
->info('The URL from where the key set should be downloaded.')
->end()
->end()
->end()
->scalarNode('key_index')
->info('Index of the key in the key set used to sign the tokens. Could be an integer or the key ID.')
->isRequired()
->end()
->scalarNode('signature_algorithm')
->info('Signature algorithm used to sign the tokens.')
->isRequired()
->end()
->arrayNode('claim_checked')
->info('List of aliases to claim checkers.')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->treatNullLike([])
->treatFalseLike([])
->end()
->arrayNode('mandatory_claims')
->info('List of claims that must be present.')
->useAttributeAsKey('name')
->prototype('scalar')->end()
->defaultValue([])
->treatNullLike([])
->treatFalseLike([])
->end()
->end()
;

$this->addEncryptionSection($rootNode);

Expand All @@ -99,28 +100,29 @@ private function addEncryptionSection(ArrayNodeDefinition $node): void
$node
->addDefaultsIfNotSet()
->children()
->arrayNode('encryption')
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->scalarNode('key_set')
->info('Private/ Shared keys used by this server to decrypt the tokens. Must be a JWKSet object.')
->isRequired()
->end()
->scalarNode('key_index')
->isRequired()
->info('Index of the key in the key set used to encrypt the tokens. Could be an integer or the key ID.')
->end()
->scalarNode('key_encryption_algorithm')
->isRequired()
->info('Key encryption algorithm used to encrypt the tokens.')
->end()
->scalarNode('content_encryption_algorithm')
->info('Content encryption algorithm used to encrypt the tokens.')
->isRequired()
->end()
->end()
->end()
->end();
->arrayNode('encryption')
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->scalarNode('key_set')
->info('Private/ Shared keys used by this server to decrypt the tokens. Must be a JWKSet object.')
->isRequired()
->end()
->scalarNode('key_index')
->isRequired()
->info('Index of the key in the key set used to encrypt the tokens. Could be an integer or the key ID.')
->end()
->scalarNode('key_encryption_algorithm')
->isRequired()
->info('Key encryption algorithm used to encrypt the tokens.')
->end()
->scalarNode('content_encryption_algorithm')
->info('Content encryption algorithm used to encrypt the tokens.')
->isRequired()
->end()
->end()
->end()
->end()
;
}
}
3 changes: 1 addition & 2 deletions DependencyInjection/SpomkyLabsLexikJoseExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace SpomkyLabs\LexikJoseBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use function array_key_exists;
use Jose\Bundle\JoseFramework\Helper\ConfigurationHelper;
use SpomkyLabs\LexikJoseBundle\Encoder\LexikJoseEncoder;
Expand Down Expand Up @@ -91,7 +90,7 @@ public function prepend(ContainerBuilder $container): void

if (isset($bridgeConfig['key_set_remote'])) {
ConfigurationHelper::addKeyset($container, 'lexik_jose_bridge.signature', $bridgeConfig['key_set_remote']['type'], ['url' => $bridgeConfig['key_set_remote']['url'], 'is_public' => $isDebug]);
} else if (isset($bridgeConfig['key_set'])) {
} elseif (isset($bridgeConfig['key_set'])) {
ConfigurationHelper::addKeyset($container, 'lexik_jose_bridge.signature', 'jwkset', ['value' => $bridgeConfig['key_set'], 'is_public' => $isDebug]);
}

Expand Down
128 changes: 66 additions & 62 deletions Encoder/LexikJoseEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ final class LexikJoseEncoder implements JWTEncoderInterface
private $encryptionKeyIndex;

/**
* @var string|null
* @var null|string
*/
private $keyEncryptionAlgorithm;

/**
* @var string|null
* @var null|string
*/
private $contentEncryptionAlgorithm;

Expand All @@ -137,17 +137,18 @@ final class LexikJoseEncoder implements JWTEncoderInterface
*
* @param int|string $signatureKeyIndex
*/
public function __construct(JWSBuilder $jwsBuilder,
JWSVerifier $jwsLoader,
ClaimCheckerManager $claimCheckerManager,
HeaderCheckerManager $signatureHeaderCheckerManager,
JWKSet $signatureKeyset,
$signatureKeyIndex,
string $signatureAlgorithm,
string $issuer,
string $audience,
int $ttl,
array $mandatoryClaims = []
public function __construct(
JWSBuilder $jwsBuilder,
JWSVerifier $jwsLoader,
ClaimCheckerManager $claimCheckerManager,
HeaderCheckerManager $signatureHeaderCheckerManager,
JWKSet $signatureKeyset,
$signatureKeyIndex,
string $signatureAlgorithm,
string $issuer,
string $audience,
int $ttl,
array $mandatoryClaims = []
) {
$this->jwsBuilder = $jwsBuilder;
$this->jwsLoader = $jwsLoader;
Expand Down Expand Up @@ -194,26 +195,6 @@ public function encode(array $payload): string
}
}

private function sign(array $payload): string
{
$payload += $this->getAdditionalPayload();
$headers = $this->getSignatureHeader();
$signatureKey = $this->signatureKeyset->get($this->signatureKeyIndex);
if ($signatureKey->has('kid')) {
$headers['kid'] = $signatureKey->get('kid');
}

$jws = $this->jwsBuilder
->create()
->withPayload(JsonConverter::encode($payload))
->addSignature($signatureKey, $headers)
->build();

$serializer = new JWSCompactSerializer();

return $serializer->serialize($jws, 0);
}

public function encrypt(string $jws): string
{
$headers = $this->getEncryptionHeader();
Expand All @@ -228,13 +209,64 @@ public function encrypt(string $jws): string
->withPayload($jws)
->withSharedProtectedHeader($headers)
->addRecipient($encryptionKey)
->build();
->build()
;

$serializer = new JWECompactSerializer();

return $serializer->serialize($jwe, 0);
}

/**
* {@inheritdoc}
*/
public function decode($token): array
{
try {
if (null !== $this->jweBuilder) {
$token = $this->decrypt($token);
}

return $this->verify($token);
} catch (InvalidClaimException $e) {
switch ($e->getClaim()) {
case 'exp':
$reason = JWTDecodeFailureException::EXPIRED_TOKEN;

break;
default:
$reason = JWTDecodeFailureException::INVALID_TOKEN;
}

throw new JWTDecodeFailureException($reason, sprintf('Invalid JWT Token. The following claim was not verified: %s.', $e->getClaim()));
} catch (InvalidHeaderException $e) {
throw new JWTDecodeFailureException(JWTDecodeFailureException::INVALID_TOKEN, sprintf('Invalid JWT Token. The following header was not verified: %s.', $e->getHeader()));
} catch (Exception $e) {
throw new JWTDecodeFailureException(JWTDecodeFailureException::INVALID_TOKEN, sprintf('Invalid JWT Token: %s', $e->getMessage()), $e);
}
}

private function sign(array $payload): string
{
$payload += $this->getAdditionalPayload();
$headers = $this->getSignatureHeader();
$signatureKey = $this->signatureKeyset->get($this->signatureKeyIndex);
if ($signatureKey->has('kid')) {
$headers['kid'] = $signatureKey->get('kid');
}

$jws = $this->jwsBuilder
->create()
->withPayload(JsonConverter::encode($payload))
->addSignature($signatureKey, $headers)
->build()
;

$serializer = new JWSCompactSerializer();

return $serializer->serialize($jws, 0);
}

/**
* @throws JWTDecodeFailureException
*/
Expand Down Expand Up @@ -276,34 +308,6 @@ private function verify(string $token): array
return $payload;
}

/**
* {@inheritdoc}
*/
public function decode($token): array
{
try {
if (null !== $this->jweBuilder) {
$token = $this->decrypt($token);
}

return $this->verify($token);
} catch (InvalidClaimException $e) {
switch ($e->getClaim()) {
case 'exp':
$reason = JWTDecodeFailureException::EXPIRED_TOKEN;
break;
default:
$reason = JWTDecodeFailureException::INVALID_TOKEN;
}

throw new JWTDecodeFailureException($reason, sprintf('Invalid JWT Token. The following claim was not verified: %s.', $e->getClaim()));
} catch (InvalidHeaderException $e) {
throw new JWTDecodeFailureException(JWTDecodeFailureException::INVALID_TOKEN, sprintf('Invalid JWT Token. The following header was not verified: %s.', $e->getHeader()));
} catch (Exception $e) {
throw new JWTDecodeFailureException(JWTDecodeFailureException::INVALID_TOKEN, sprintf('Invalid JWT Token: %s', $e->getMessage()), $e);
}
}

private function getAdditionalPayload(): array
{
return [
Expand Down
3 changes: 2 additions & 1 deletion Resources/config/encryption_services.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
$container = $container->services()->defaults()
->private()
->autoconfigure()
->autowire();
->autowire()
;

$container->set('spomkylabs_lexik_jose_checker_key_encryption_algorithm')
->class(AlgHeaderChecker::class)
Expand Down
Loading

0 comments on commit 72c3d82

Please sign in to comment.