Completed
Push — develop ( 17d645...b57b7f )
by Florent
02:19
created

SpomkyLabsJoseBundleExtension::createJWTCreator()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 15
Code Lines 10

Duplication

Lines 15
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 15
loc 15
rs 9.4285
cc 2
eloc 10
nc 1
nop 3
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;
13
14
use Symfony\Component\Config\Definition\Processor;
15
use Symfony\Component\Config\FileLocator;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
use Symfony\Component\DependencyInjection\Definition;
18
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
19
use Symfony\Component\DependencyInjection\Reference;
20
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
21
22
final class SpomkyLabsJoseBundleExtension extends Extension
23
{
24
    /**
25
     * @var \SpomkyLabs\JoseBundle\DependencyInjection\JWKSource\JWKSourceInterface[]
26
     */
27
    private $jwk_sources;
28
29
    /**
30
     * @var \SpomkyLabs\JoseBundle\DependencyInjection\JWKSetSource\JWKSetSourceInterface[]
31
     */
32
    private $jwk_set_sources;
33
34
    /**
35
     * @var string
36
     */
37
    private $alias;
38
39
    /**
40
     * @param string $alias
41
     */
42
    public function __construct($alias)
43
    {
44
        $this->alias = $alias;
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public function load(array $configs, ContainerBuilder $container)
51
    {
52
        $processor = new Processor();
53
54
        $config = $processor->processConfiguration(
55
            $this->getConfiguration($configs, $container),
56
            $configs
57
        );
58
59
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
60
        $services = $this->getXmlFileToLoad();
61
        foreach ($services as $basename) {
62
            $loader->load(sprintf('%s.xml', $basename));
63
        }
64
65
        $this->initConfiguration($container, $config);
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getConfiguration(array $configs, ContainerBuilder $container)
72
    {
73
        $jwk_sources = $this->createJWKSources();
74
        $jwk_set_sources = $this->createJWKSetSources();
75
76
        return new Configuration($this->getAlias(), $jwk_sources, $jwk_set_sources);
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function getAlias()
83
    {
84
        return $this->alias;
85
    }
86
87
    /**
88
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
89
     * @param array                                                   $config
90
     */
91
    private function initConfiguration(ContainerBuilder $container, array $config)
92
    {
93
        foreach ($config['keys'] as $name => $key) {
94
            $this->createJWK($name, $key, $container, $this->jwk_sources);
95
        }
96
97
        foreach ($config['key_sets'] as $name => $key_set) {
98
            $this->createJWKSet($name, $key_set, $container, $this->jwk_set_sources);
99
        }
100
101
        foreach ($config['encrypters'] as $name => $encrypter) {
102
            $this->createEncrypter($name, $encrypter, $container);
103
        }
104
105
        foreach ($config['decrypters'] as $name => $decrypter) {
106
            $this->createDecrypter($name, $decrypter, $container);
107
        }
108
109
        foreach ($config['signers'] as $name => $signer) {
110
            $this->createSigner($name, $signer, $container);
111
        }
112
113
        foreach ($config['verifiers'] as $name => $verifier) {
114
            $this->createVerifier($name, $verifier, $container);
115
        }
116
117
        foreach ($config['checkers'] as $name => $checker) {
118
            $this->createChecker($name, $checker, $container);
119
        }
120
121
        foreach ($config['jwt_loaders'] as $name => $loader) {
122
            $this->createJWTLoader($name, $loader, $container);
123
        }
124
125
        foreach ($config['jwt_creators'] as $name => $creator) {
126
            $this->createJWTCreator($name, $creator, $container);
127
        }
128
    }
129
130
    /**
131
     * @param string                                                                       $name
132
     * @param array                                                                        $config
133
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder                      $container
134
     * @param \SpomkyLabs\JoseBundle\DependencyInjection\JWKSetSource\JWKSetSourceInterface[] $jwk_set_sources
135
     */
136 View Code Duplication
    private function createJWKSet($name, array $config, ContainerBuilder $container, array $jwk_set_sources)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
137
    {
138
        foreach ($config as $key => $adapter) {
139
            if (array_key_exists($key, $jwk_set_sources)) {
140
                $service_id = sprintf('jose.key_set.%s', $name);
141
                $jwk_set_sources[$key]->create($container, $service_id, $adapter);
142
143
                return;
144
            }
145
        }
146
        throw new \LogicException(sprintf('The JWKSet definition "%s" is not configured.', $name));
147
    }
148
149
    /**
150
     * @param string                                                                    $name
151
     * @param array                                                                     $config
152
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder                   $container
153
     * @param \SpomkyLabs\JoseBundle\DependencyInjection\JWKSource\JWKSourceInterface[] $jwk_sources
154
     */
155 View Code Duplication
    private function createJWK($name, array $config, ContainerBuilder $container, array $jwk_sources)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
156
    {
157
        foreach ($config as $key => $adapter) {
158
            if (array_key_exists($key, $jwk_sources)) {
159
                $service_id = sprintf('jose.key.%s', $name);
160
                $jwk_sources[$key]->create($container, $service_id, $adapter);
161
162
                return;
163
            }
164
        }
165
        throw new \LogicException(sprintf('The JWK definition "%s" is not configured.', $name));
166
    }
167
168
    /**
169
     * @param string                                                  $name
170
     * @param array                                                   $config
171
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
172
     */
173
    private function createEncrypter($name, array $config, ContainerBuilder $container)
174
    {
175
        $service_id = sprintf('jose.encrypter.%s', $name);
176
        $definition = new Definition('Jose\Encrypter');
177
        $definition->setFactory([
178
            new Reference('jose.factory.service'),
179
            'createEncrypter',
180
        ]);
181
        $definition->setArguments([
182
            $config['key_encryption_algorithms'],
183
            $config['content_encryption_algorithms'],
184
            $config['compression_methods'],
185
            null === $config['logger'] ? null : new Reference($config['logger']),
186
        ]);
187
188
        $container->setDefinition($service_id, $definition);
189
        
190
        if (true === $config['create_decrypter']) {
191
            $this->createDecrypter($name, $config, $container);
192
        }
193
    }
194
195
    /**
196
     * @param string                                                  $name
197
     * @param array                                                   $config
198
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
199
     */
200
    private function createDecrypter($name, array $config, ContainerBuilder $container)
201
    {
202
        $service_id = sprintf('jose.decrypter.%s', $name);
203
        $definition = new Definition('Jose\Decrypter');
204
        $definition->setFactory([
205
            new Reference('jose.factory.service'),
206
            'createDecrypter',
207
        ]);
208
        $definition->setArguments([
209
            $config['key_encryption_algorithms'],
210
            $config['content_encryption_algorithms'],
211
            $config['compression_methods'],
212
            null === $config['logger'] ? null : new Reference($config['logger']),
213
        ]);
214
        
215
        $container->setDefinition($service_id, $definition);
216
    }
217
218
    /**
219
     * @param string                                                  $name
220
     * @param array                                                   $config
221
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
222
     */
223
    private function createSigner($name, array $config, ContainerBuilder $container)
224
    {
225
        $service_id = sprintf('jose.signer.%s', $name);
226
        $definition = new Definition('Jose\Signer');
227
        $definition->setFactory([
228
            new Reference('jose.factory.service'),
229
            'createSigner',
230
        ]);
231
        $definition->setArguments([
232
            $config['algorithms'],
233
            null === $config['logger'] ? null : new Reference($config['logger']),
234
        ]);
235
236
        $container->setDefinition($service_id, $definition);
237
        
238
        if (true === $config['create_verifier']) {
239
            $this->createVerifier($name, $config, $container);
240
        }
241
    }
242
243
    /**
244
     * @param string                                                  $name
245
     * @param array                                                   $config
246
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
247
     */
248 View Code Duplication
    private function createVerifier($name, array $config, ContainerBuilder $container)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
249
    {
250
        $service_id = sprintf('jose.verifier.%s', $name);
251
        $definition = new Definition('Jose\Verifier');
252
        $definition->setFactory([
253
            new Reference('jose.factory.service'),
254
            'createVerifier',
255
        ]);
256
        $definition->setArguments([
257
            $config['algorithms'],
258
            null === $config['logger'] ? null : new Reference($config['logger']),
259
        ]);
260
        
261
        $container->setDefinition($service_id, $definition);
262
    }
263
264
    /**
265
     * @param string                                                  $name
266
     * @param array                                                   $config
267
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
268
     */
269 View Code Duplication
    private function createChecker($name, array $config, ContainerBuilder $container)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
270
    {
271
        $service_id = sprintf('jose.checker.%s', $name);
272
        $definition = new Definition('Jose\Checker\CheckerManager');
273
        $definition->setFactory([
274
            new Reference('jose.factory.service'),
275
            'createChecker',
276
        ]);
277
        $definition->setArguments([
278
            $config['claims'],
279
            $config['headers'],
280
        ]);
281
282
        $container->setDefinition($service_id, $definition);
283
    }
284
285
    /**
286
     * @param string                                                  $name
287
     * @param array                                                   $config
288
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
289
     */
290
    private function createJWTLoader($name, array $config, ContainerBuilder $container)
291
    {
292
        $service_id = sprintf('jose.jwt_loader.%s', $name);
293
        $definition = new Definition('Jose\JWTLoader');
294
        $definition->setFactory([
295
            new Reference('jose.factory.service'),
296
            'createJWTLoader',
297
        ]);
298
        $definition->setArguments([
299
            new Reference($config['checker']),
300
            new Reference($config['verifier']),
301
            null === $config['decrypter'] ? null : new Reference($config['decrypter']),
302
            null === $config['logger'] ? null : new Reference($config['logger']),
303
        ]);
304
305
        $container->setDefinition($service_id, $definition);
306
    }
307
308
    /**
309
     * @param string                                                  $name
310
     * @param array                                                   $config
311
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
312
     */
313 View Code Duplication
    private function createJWTCreator($name, array $config, ContainerBuilder $container)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
314
    {
315
        $service_id = sprintf('jose.jwt_creator.%s', $name);
316
        $definition = new Definition('Jose\JWTCreator');
317
        $definition->setFactory([
318
            new Reference('jose.factory.service'),
319
            'createJWTCreator',
320
        ]);
321
        $definition->setArguments([
322
            new Reference($config['signer']),
323
            null === $config['encrypter'] ? null : new Reference($config['encrypter']),
324
        ]);
325
326
        $container->setDefinition($service_id, $definition);
327
    }
328
329
    /**
330
     * @return string[]
331
     */
332
    private function getXmlFileToLoad()
333
    {
334
        $services = [
335
            'services',
336
            'compression_methods',
337
            'checkers',
338
            'signature_algorithms',
339
            'encryption_algorithms',
340
            'checkers',
341
        ];
342
343
        return $services;
344
    }
345
346 View Code Duplication
    private function createJWKSources()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
347
    {
348
        if (null !== $this->jwk_sources) {
349
            return $this->jwk_sources;
350
        }
351
352
        // load bundled adapter factories
353
        $tempContainer = new ContainerBuilder();
354
        $loader = new XmlFileLoader($tempContainer, new FileLocator(__DIR__.'/../Resources/config'));
355
        $loader->load('jwk_sources.xml');
356
357
        $services = $tempContainer->findTaggedServiceIds('jose.jwk_source');
358
        $jwk_sources = [];
359
        foreach (array_keys($services) as $id) {
360
            $factory = $tempContainer->get($id);
361
            $jwk_sources[str_replace('-', '_', $factory->getKey())] = $factory;
362
        }
363
364
        return $this->jwk_sources = $jwk_sources;
365
    }
366
367 View Code Duplication
    private function createJWKSetSources()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
368
    {
369
        if (null !== $this->jwk_set_sources) {
370
            return $this->jwk_set_sources;
371
        }
372
373
        // load bundled adapter factories
374
        $tempContainer = new ContainerBuilder();
375
        $loader = new XmlFileLoader($tempContainer, new FileLocator(__DIR__.'/../Resources/config'));
376
        $loader->load('jwk_set_sources.xml');
377
378
        $services = $tempContainer->findTaggedServiceIds('jose.jwk_set_source');
379
        $jwk_set_sources = [];
380
        foreach (array_keys($services) as $id) {
381
            $factory = $tempContainer->get($id);
382
            $jwk_set_sources[str_replace('-', '_', $factory->getKeySet())] = $factory;
383
        }
384
385
        return $this->jwk_set_sources = $jwk_set_sources;
386
    }
387
}
388