295 lines
14 KiB
PHP

<?php
namespace Lexik\Bundle\JWTAuthenticationBundle\DependencyInjection;
use ApiPlatform\Symfony\Bundle\ApiPlatformBundle;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\HttpFoundation\Cookie;
/**
* LexikJWTAuthenticationBundle Configuration.
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder(): TreeBuilder
{
$treeBuilder = new TreeBuilder('lexik_jwt_authentication');
$treeBuilder
->getRootNode()
->addDefaultsIfNotSet()
->children()
->scalarNode('public_key')
->info('The key used to sign tokens (useless for HMAC). If not set, the key will be automatically computed from the secret key.')
->defaultNull()
->end()
->arrayNode('additional_public_keys')
->info('Multiple public keys to try to verify token signature. If none is given, it will use the key provided in "public_key".')
->scalarPrototype()->end()
->end()
->scalarNode('secret_key')
->info('The key used to sign tokens. It can be a raw secret (for HMAC), a raw RSA/ECDSA key or the path to a file itself being plaintext or PEM.')
->defaultNull()
->end()
->scalarNode('pass_phrase')
->info('The key passphrase (useless for HMAC)')
->defaultValue('')
->end()
->scalarNode('token_ttl')
->defaultValue(3600)
->end()
->booleanNode('allow_no_expiration')
->info('Allow tokens without "exp" claim (i.e. indefinitely valid, no lifetime) to be considered valid. Caution: usage of this should be rare.')
->defaultFalse()
->end()
->scalarNode('clock_skew')
->defaultValue(0)
->end()
->arrayNode('encoder')
->addDefaultsIfNotSet()
->children()
->scalarNode('service')
->defaultValue('lexik_jwt_authentication.encoder.lcobucci')
->end()
->scalarNode('signature_algorithm')
->defaultValue('RS256')
->cannotBeEmpty()
->end()
->end()
->end()
->scalarNode('user_id_claim')
->defaultValue('username')
->cannotBeEmpty()
->end()
->append($this->getTokenExtractorsNode())
->scalarNode('remove_token_from_body_when_cookies_used')
->defaultTrue()
->end()
->arrayNode('set_cookies')
->fixXmlConfig('set_cookie')
->normalizeKeys(false)
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('lifetime')
->defaultNull()
->info('The cookie lifetime. If null, the "token_ttl" option value will be used')
->end()
->enumNode('samesite')
->values([Cookie::SAMESITE_NONE, Cookie::SAMESITE_LAX, Cookie::SAMESITE_STRICT])
->defaultValue(Cookie::SAMESITE_LAX)
->end()
->scalarNode('path')->defaultValue('/')->cannotBeEmpty()->end()
->scalarNode('domain')->defaultNull()->end()
->scalarNode('secure')->defaultTrue()->end()
->scalarNode('httpOnly')->defaultTrue()->end()
->scalarNode('partitioned')->defaultFalse()->end()
->arrayNode('split')
->scalarPrototype()->end()
->end()
->end()
->end()
->end()
->arrayNode('api_platform')
->canBeEnabled()
->info('API Platform compatibility: add check_path in OpenAPI documentation.')
->children()
->scalarNode('check_path')
->defaultNull()
->info('The login check path to add in OpenAPI.')
->end()
->scalarNode('username_path')
->defaultNull()
->info('The path to the username in the JSON body.')
->end()
->scalarNode('password_path')
->defaultNull()
->info('The path to the password in the JSON body.')
->end()
->end()
->end()
->arrayNode('access_token_issuance')
->fixXmlConfig('access_token_issuance')
->canBeEnabled()
->children()
->arrayNode('signature')
->fixXmlConfig('signature')
->addDefaultsIfNotSet()
->children()
->scalarNode('algorithm')
->isRequired()
->info('The algorithm use to sign the access tokens.')
->end()
->scalarNode('key')
->isRequired()
->info('The signature key. It shall be JWK encoded.')
->end()
->end()
->end()
->arrayNode('encryption')
->fixXmlConfig('encryption')
->canBeEnabled()
->children()
->scalarNode('key_encryption_algorithm')
->isRequired()
->cannotBeEmpty()
->info('The key encryption algorithm is used to encrypt the token.')
->end()
->scalarNode('content_encryption_algorithm')
->isRequired()
->cannotBeEmpty()
->info('The key encryption algorithm is used to encrypt the token.')
->end()
->scalarNode('key')
->isRequired()
->info('The encryption key. It shall be JWK encoded.')
->end()
->end()
->end()
->end()
->end()
->arrayNode('access_token_verification')
->fixXmlConfig('access_token_verification')
->canBeEnabled()
->children()
->arrayNode('signature')
->fixXmlConfig('signature')
->addDefaultsIfNotSet()
->children()
->arrayNode('header_checkers')
->fixXmlConfig('header_checkers')
->scalarPrototype()->end()
->defaultValue([])
->info('The headers to be checked for validating the JWS.')
->end()
->arrayNode('claim_checkers')
->fixXmlConfig('claim_checkers')
->scalarPrototype()->end()
->defaultValue(['exp_with_clock_skew', 'iat_with_clock_skew', 'nbf_with_clock_skew'])
->info('The claims to be checked for validating the JWS.')
->end()
->arrayNode('mandatory_claims')
->fixXmlConfig('mandatory_claims')
->scalarPrototype()->end()
->defaultValue([])
->info('The list of claims that shall be present in the JWS.')
->end()
->arrayNode('allowed_algorithms')
->fixXmlConfig('allowed_algorithms')
->scalarPrototype()->end()
->requiresAtLeastOneElement()
->info('The algorithms allowed to be used for token verification.')
->end()
->scalarNode('keyset')
->isRequired()
->info('The signature keyset. It shall be JWKSet encoded.')
->end()
->end()
->end()
->arrayNode('encryption')
->fixXmlConfig('encryption')
->canBeEnabled()
->children()
->booleanNode('continue_on_decryption_failure')
->defaultFalse()
->info('If enable, non-encrypted tokens or tokens that failed during decryption or verification processes are accepted.')
->end()
->arrayNode('header_checkers')
->fixXmlConfig('header_checkers')
->scalarPrototype()->end()
->defaultValue(['iat_with_clock_skew', 'nbf_with_clock_skew', 'exp_with_clock_skew'])
->info('The headers to be checked for validating the JWE.')
->end()
->arrayNode('allowed_key_encryption_algorithms')
->fixXmlConfig('allowed_key_encryption_algorithms')
->scalarPrototype()->end()
->requiresAtLeastOneElement()
->info('The key encryption algorithm is used to encrypt the token.')
->end()
->arrayNode('allowed_content_encryption_algorithms')
->fixXmlConfig('allowed_content_encryption_algorithms')
->scalarPrototype()->end()
->requiresAtLeastOneElement()
->info('The key encryption algorithm is used to encrypt the token.')
->end()
->scalarNode('keyset')
->isRequired()
->info('The encryption keyset. It shall be JWKSet encoded.')
->end()
->end()
->end()
->end()
->end()
->arrayNode('blocklist_token')
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->scalarNode('cache')
->defaultValue('cache.app')
->info('Storage to track blocked tokens')
->end()
->end()
->end()
->end()
->end();
return $treeBuilder;
}
private function getTokenExtractorsNode(): ArrayNodeDefinition
{
$builder = new TreeBuilder('token_extractors');
$node = $builder->getRootNode();
$node
->addDefaultsIfNotSet()
->children()
->arrayNode('authorization_header')
->addDefaultsIfNotSet()
->canBeDisabled()
->children()
->scalarNode('prefix')
->defaultValue('Bearer')
->end()
->scalarNode('name')
->defaultValue('Authorization')
->end()
->end()
->end()
->arrayNode('cookie')
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->scalarNode('name')
->defaultValue('BEARER')
->end()
->end()
->end()
->arrayNode('query_parameter')
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->scalarNode('name')
->defaultValue('bearer')
->end()
->end()
->end()
->arrayNode('split_cookie')
->canBeEnabled()
->children()
->arrayNode('cookies')
->scalarPrototype()->end()
->end()
->end()
->end()
->end()
;
return $node;
}
}