Failed Conditions
Push — master ( b5a0b4...819484 )
by Florent
08:00
created

ClientAssertionJwtSource::load()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
nc 8
nop 2
dl 0
loc 29
rs 9.0111
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\ServerBundle\Component\ClientAuthentication;
15
16
use Jose\Bundle\JoseFramework\Helper\ConfigurationHelper;
17
use Jose\Component\Core\JWK;
18
use OAuth2Framework\ServerBundle\Component\ClientAuthentication\Compiler\ClientAssertionEncryptedJwtCompilerPass;
19
use OAuth2Framework\ServerBundle\Component\ClientAuthentication\Compiler\ClientAssertionJkuSupportCompilerPass;
20
use OAuth2Framework\ServerBundle\Component\ClientAuthentication\Compiler\ClientAssertionTrustedIssuerSupportCompilerPass;
21
use OAuth2Framework\ServerBundle\Component\ClientAuthentication\Compiler\ClientJwtAssertionMetadataCompilerPass;
22
use OAuth2Framework\ServerBundle\Component\Component;
23
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
24
use Symfony\Component\Config\FileLocator;
25
use Symfony\Component\DependencyInjection\ContainerBuilder;
26
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
27
28
class ClientAssertionJwtSource implements Component
29
{
30
    public function name(): string
31
    {
32
        return 'client_assertion_jwt';
33
    }
34
35
    public function load(array $configs, ContainerBuilder $container)
36
    {
37
        if (!\class_exists(JWK::class)) {
38
            return;
39
        }
40
        $config = $configs['client_authentication']['client_assertion_jwt'];
41
        $container->setParameter('oauth2_server.client_authentication.client_assertion_jwt.enabled', $config['enabled']);
42
        if (!$config['enabled']) {
43
            return;
44
        }
45
46
        $keys = ['secret_lifetime', 'signature_algorithms', 'claim_checkers', 'header_checkers', 'jku_support'];
47
        foreach ($keys as $key) {
48
            $container->setParameter('oauth2_server.client_authentication.client_assertion_jwt.'.$key, $config[$key]);
49
        }
50
51
        $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../Resources/config/client_authentication'));
52
        $loader->load('client_assertion_jwt.php');
53
54
        $container->setParameter('oauth2_server.client_authentication.client_assertion_jwt.encryption.enabled', $config['encryption']['enabled']);
55
        if (!$config['encryption']['enabled']) {
56
            return;
57
        }
58
59
        $config = $configs['client_authentication']['client_assertion_jwt']['encryption'];
60
        $container->setParameter('oauth2_server.client_authentication.client_assertion_jwt.encryption.enabled', $config['enabled']);
61
        $keys = ['required', 'key_set', 'key_encryption_algorithms', 'content_encryption_algorithms'];
62
        foreach ($keys as $key) {
63
            $container->setParameter('oauth2_server.client_authentication.client_assertion_jwt.encryption.'.$key, $config[$key]);
64
        }
65
    }
66
67
    public function getNodeDefinition(ArrayNodeDefinition $node, ArrayNodeDefinition $rootNode)
68
    {
69
        if (!\class_exists(JWK::class)) {
70
            return;
71
        }
72
        $node->children()
73
            ->arrayNode($this->name())
74
            ->canBeEnabled()
75
            ->info('This method comprises the "client_secret_jwt" and the "private_key_jwt" authentication methods')
76
            ->validate()
77
            ->ifTrue(function ($config) {
78
                return $config['enabled'] && empty($config['signature_algorithms']);
79
            })
80
            ->thenInvalid('At least one signature algorithm must be set.')
81
            ->end()
82
            ->children()
83
            ->integerNode('secret_lifetime')
84
            ->info('Secret lifetime (in seconds; 0 = unlimited) applicable to the "client_secret_jwt" authentication method')
85
            ->defaultValue(60 * 60 * 24 * 14)
86
            ->min(0)
87
            ->end()
88
            ->arrayNode('signature_algorithms')
89
            ->info('Supported signature algorithms.')
90
            ->useAttributeAsKey('name')
91
            ->scalarPrototype()->end()
92
            ->treatNullLike([])
93
            ->end()
94
            ->arrayNode('claim_checkers')
95
            ->info('Claim checkers for incoming assertions.')
96
            ->useAttributeAsKey('name')
97
            ->scalarPrototype()->end()
98
            ->treatNullLike([])
99
            ->end()
100
            ->arrayNode('header_checkers')
101
            ->info('Header checkers for incoming assertions.')
102
            ->useAttributeAsKey('name')
103
            ->scalarPrototype()->end()
104
            ->treatNullLike([])
105
            ->end()
106
            ->booleanNode('jku_support')
107
            ->info('If true, the client configuration parameter "jwks_uri" will be allowed.')
108
            ->defaultTrue()
109
            ->end()
110
            ->arrayNode('encryption')
111
            ->canBeEnabled()
112
            ->validate()
113
            ->ifTrue(function ($config) {
114
                return true === $config['enabled'] && empty($config['key_encryption_algorithms']);
115
            })
116
            ->thenInvalid('At least one key encryption algorithm must be set.')
117
            ->end()
118
            ->validate()
119
            ->ifTrue(function ($config) {
120
                return true === $config['enabled'] && empty($config['content_encryption_algorithms']);
121
            })
122
            ->thenInvalid('At least one content encryption algorithm must be set.')
123
            ->end()
124
            ->children()
125
            ->booleanNode('required')
126
            ->info('When true, all incoming assertions must be encrypted.')
127
            ->defaultFalse()
128
            ->end()
129
            ->scalarNode('key_set')
130
            ->info('Private or shared keys used for assertion decryption.')
131
            ->isRequired()
132
            ->end()
133
            ->arrayNode('key_encryption_algorithms')
134
            ->info('Supported key encryption algorithms.')
135
            ->useAttributeAsKey('name')
136
            ->scalarPrototype()->end()
137
            ->treatNullLike([])
138
            ->end()
139
            ->arrayNode('content_encryption_algorithms')
140
            ->info('Supported content encryption algorithms.')
141
            ->useAttributeAsKey('name')
142
            ->scalarPrototype()->end()
143
            ->treatNullLike([])
144
            ->end()
145
            ->end()
146
            ->end()
147
            ->end()
148
            ->end()
149
            ->end();
150
    }
151
152
    public function prepend(ContainerBuilder $container, array $configs): array
153
    {
154
        if (!\class_exists(JWK::class)) {
155
            return [];
156
        }
157
        $config = $configs['client_authentication']['client_assertion_jwt'];
158
        if (!$config['enabled']) {
159
            return [];
160
        }
161
        ConfigurationHelper::addJWSVerifier($container, 'client_authentication.client_assertion_jwt', $config['signature_algorithms'], false, []);
162
        ConfigurationHelper::addHeaderChecker($container, 'client_authentication.client_assertion_jwt', $config['header_checkers'], false, []);
163
        ConfigurationHelper::addClaimChecker($container, 'client_authentication.client_assertion_jwt', $config['claim_checkers'], false, []);
164
        if ($config['encryption']['enabled']) {
165
            ConfigurationHelper::addJWELoader($container, 'client_authentication.client_assertion_jwt.encryption', ['jwe_compact'], $config['encryption']['key_encryption_algorithms'], $config['encryption']['content_encryption_algorithms'], ['DEF'], [] /*FIXME*/, false, []);
166
            ConfigurationHelper::addKeyset($container, 'client_authentication.client_assertion_jwt.encryption', 'jwkset', ['value' => $config['encryption']['key_set']], false, []);
167
        }
168
169
        return [];
170
    }
171
172
    public function build(ContainerBuilder $container)
173
    {
174
        if (!\class_exists(JWK::class)) {
175
            return;
176
        }
177
        $container->addCompilerPass(new ClientJwtAssertionMetadataCompilerPass());
178
        $container->addCompilerPass(new ClientAssertionTrustedIssuerSupportCompilerPass());
179
        $container->addCompilerPass(new ClientAssertionJkuSupportCompilerPass());
180
        $container->addCompilerPass(new ClientAssertionEncryptedJwtCompilerPass());
181
    }
182
}
183