EasyJWTLoaderSource::getNodeDefinition()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 48
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 48
rs 9.125
c 0
b 0
f 0
cc 1
eloc 46
nc 1
nop 1
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace SpomkyLabs\JoseBundle\DependencyInjection\Source;
13
14
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\DependencyInjection\ContainerBuilder;
16
17
final class EasyJWTLoaderSource implements SourceInterface
18
{
19
    /**
20
     * {@inheritdoc}
21
     */
22
    public function getName()
23
    {
24
        return 'easy_jwt_loader';
25
    }
26
27
    /**
28
     * {@inheritdoc}
29
     */
30
    public function createService($name, array $config, ContainerBuilder $container)
31
    {
32
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function getNodeDefinition(ArrayNodeDefinition $node)
38
    {
39
        $node
40
            ->children()
41
                ->arrayNode('easy_jwt_loader')
42
                    ->useAttributeAsKey('name')
43
                    ->prototype('array')
44
                        ->children()
45
                            ->booleanNode('is_public')
46
                                ->info('If true, the service will be public, else private.')
47
                                ->defaultTrue()
48
                            ->end()
49
                            ->arrayNode('signature_algorithms')
50
                                ->useAttributeAsKey('name')
51
                                ->isRequired()
52
                                ->cannotBeEmpty()
53
                                ->prototype('scalar')->end()
54
                            ->end()
55
                            ->arrayNode('key_encryption_algorithms')
56
                                ->useAttributeAsKey('name')
57
                                ->defaultValue([])
58
                                ->prototype('scalar')->end()
59
                            ->end()
60
                            ->arrayNode('content_encryption_algorithms')
61
                                ->useAttributeAsKey('name')
62
                                ->defaultValue([])
63
                                ->prototype('scalar')->end()
64
                            ->end()
65
                            ->arrayNode('compression_methods')
66
                                ->useAttributeAsKey('name')
67
                                ->defaultValue(['DEF'])
68
                                ->prototype('scalar')->end()
69
                            ->end()
70
                            ->arrayNode('claim_checkers')
71
                                ->useAttributeAsKey('name')
72
                                ->defaultValue([])
73
                                ->prototype('scalar')->end()
74
                            ->end()
75
                            ->arrayNode('header_checkers')
76
                                ->useAttributeAsKey('name')
77
                                ->defaultValue([])
78
                                ->prototype('scalar')->end()
79
                            ->end()
80
                        ->end()
81
                    ->end()
82
                ->end()
83
            ->end();
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    public function prepend(ContainerBuilder $container, array $config)
90
    {
91
        if (false === array_key_exists($this->getName(), $config)) {
92
            return;
93
        }
94
95
        foreach ($config[$this->getName()] as $id => $section) {
96
            $config = $this->createServiceConfiguration($config, $id, $section);
97
        }
98
99
        return $config;
100
    }
101
102
    /**
103
     * @param array  $config
104
     * @param string $id
105
     * @param array  $section
106
     *
107
     * @return array
108
     */
109
    private function createServiceConfiguration(array $config, $id, array $section)
110
    {
111
        $config = $this->createVerifierServiceConfiguration($config, $id, $section);
112
        $config = $this->createDecrypterServiceConfiguration($config, $id, $section);
113
        $config = $this->createJWTLoaderServiceConfiguration($config, $id, $section);
114
        $config = $this->createCheckerServiceConfiguration($config, $id, $section);
115
116
        return $config;
117
    }
118
119
    /**
120
     * @param array  $config
121
     * @param string $id
122
     * @param array  $section
123
     *
124
     * @return array
125
     */
126
    private function createVerifierServiceConfiguration(array $config, $id, array $section)
127
    {
128
        $config['verifiers'] = array_merge(
129
            array_key_exists('verifiers', $config) ? $config['verifiers'] : [],
130
            [$id => [
131
                'is_public'  => $section['is_public'],
132
                'algorithms' => $section['signature_algorithms'],
133
            ]]
134
        );
135
136
        return $config;
137
    }
138
139
    /**
140
     * @param array  $config
141
     * @param string $id
142
     * @param array  $section
143
     *
144
     * @return array
145
     */
146
    private function createDecrypterServiceConfiguration(array $config, $id, array $section)
147
    {
148
        if (false === $this->isEncryptionSupportEnabled($section)) {
149
            return $config;
150
        }
151
        $config['decrypters'] = array_merge(
152
            array_key_exists('decrypters', $config) ? $config['decrypters'] : [],
153
            [$id => [
154
                'is_public'                     => $section['is_public'],
155
                'key_encryption_algorithms'     => $section['key_encryption_algorithms'],
156
                'content_encryption_algorithms' => $section['content_encryption_algorithms'],
157
                'compression_methods'           => $section['compression_methods'],
158
            ]]
159
        );
160
161
        return $config;
162
    }
163
164
    /**
165
     * @param array  $config
166
     * @param string $id
167
     * @param array  $section
168
     *
169
     * @return array
170
     */
171
    private function createCheckerServiceConfiguration(array $config, $id, array $section)
172
    {
173
        $config['checkers'] = array_merge(
174
            array_key_exists('checkers', $config) ? $config['checkers'] : [],
175
            [$id => [
176
                'is_public' => $section['is_public'],
177
                'claims'    => $section['claim_checkers'],
178
                'headers'   => $section['header_checkers'],
179
            ]]
180
        );
181
182
        return $config;
183
    }
184
185
    /**
186
     * @param array  $config
187
     * @param string $id
188
     * @param array  $section
189
     *
190
     * @return array
191
     */
192
    private function createJWTLoaderServiceConfiguration(array $config, $id, array $section)
193
    {
194
        $service = [
195
            'is_public' => $section['is_public'],
196
            'verifier'  => sprintf('jose.verifier.%s', $id),
197
            'checker'   => sprintf('jose.checker.%s', $id),
198
        ];
199
        if (true === $this->isEncryptionSupportEnabled($section)) {
200
            $service['decrypter'] = sprintf('jose.decrypter.%s', $id);
201
        }
202
        $config['jwt_loaders'] = array_merge(
203
            array_key_exists('jwt_loaders', $config) ? $config['jwt_loaders'] : [],
204
            [$id => $service]
205
        );
206
207
        return $config;
208
    }
209
210
    /**
211
     * @param array $section
212
     *
213
     * @return bool
214
     */
215
    private function isEncryptionSupportEnabled(array $section)
216
    {
217
        if (true === empty($section['key_encryption_algorithms']) && true === empty($section['content_encryption_algorithms'])) {
218
            return false;
219
        }
220
221
        if (true === empty($section['key_encryption_algorithms']) || true === empty($section['content_encryption_algorithms'])) {
222
            throw new \LogicException('Both key encryption algorithms and content encryption algorithms must be set to enable the encryption support.');
223
        }
224
225
        return true;
226
    }
227
}
228