GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 162e16...c8f601 )
by Dmitri
01:44
created

DamaxApiAuthExtension::prepend()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Damax\Bundle\ApiAuthBundle\DependencyInjection;
6
7
use Damax\Bundle\ApiAuthBundle\Command\Storage\AddKeyCommand;
8
use Damax\Bundle\ApiAuthBundle\Command\Storage\LookupKeyCommand;
9
use Damax\Bundle\ApiAuthBundle\Command\Storage\RemoveKeyCommand;
10
use Damax\Bundle\ApiAuthBundle\Controller\TokenController;
11
use Damax\Bundle\ApiAuthBundle\Extractor\ChainExtractor;
12
use Damax\Bundle\ApiAuthBundle\Jwt\Claims;
13
use Damax\Bundle\ApiAuthBundle\Jwt\Claims\ClaimsCollector;
14
use Damax\Bundle\ApiAuthBundle\Jwt\Claims\OrganizationClaims;
15
use Damax\Bundle\ApiAuthBundle\Jwt\Claims\SecurityClaims;
16
use Damax\Bundle\ApiAuthBundle\Jwt\Claims\TimestampClaims;
17
use Damax\Bundle\ApiAuthBundle\Jwt\Lcobucci\Builder;
18
use Damax\Bundle\ApiAuthBundle\Jwt\Lcobucci\Parser;
19
use Damax\Bundle\ApiAuthBundle\Jwt\TokenBuilder;
20
use Damax\Bundle\ApiAuthBundle\Key\Factory;
21
use Damax\Bundle\ApiAuthBundle\Key\Generator\Generator;
22
use Damax\Bundle\ApiAuthBundle\Key\Generator\RandomGenerator;
23
use Damax\Bundle\ApiAuthBundle\Key\Storage\ChainStorage;
24
use Damax\Bundle\ApiAuthBundle\Key\Storage\DoctrineStorage;
25
use Damax\Bundle\ApiAuthBundle\Key\Storage\DummyStorage;
26
use Damax\Bundle\ApiAuthBundle\Key\Storage\InMemoryStorage;
27
use Damax\Bundle\ApiAuthBundle\Key\Storage\Reader;
28
use Damax\Bundle\ApiAuthBundle\Key\Storage\RedisStorage;
29
use Damax\Bundle\ApiAuthBundle\Key\Storage\Writer;
30
use Damax\Bundle\ApiAuthBundle\Security\ApiKey\Authenticator as ApiKeyAuthenticator;
31
use Damax\Bundle\ApiAuthBundle\Security\ApiKey\StorageUserProvider;
32
use Damax\Bundle\ApiAuthBundle\Security\JsonResponseFactory;
33
use Damax\Bundle\ApiAuthBundle\Security\Jwt\AuthenticationHandler;
34
use Damax\Bundle\ApiAuthBundle\Security\Jwt\Authenticator as JwtAuthenticator;
35
use Damax\Bundle\ApiAuthBundle\Security\ResponseFactory;
36
use Lcobucci\Clock\SystemClock;
37
use Lcobucci\JWT\Configuration as JwtConfiguration;
38
use Lcobucci\JWT\Signer\Key;
39
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
40
use Symfony\Component\DependencyInjection\ContainerBuilder;
41
use Symfony\Component\DependencyInjection\Definition;
42
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
43
use Symfony\Component\DependencyInjection\Reference;
44
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;
45
46
final class DamaxApiAuthExtension extends ConfigurableExtension implements PrependExtensionInterface
47
{
48
    public function prepend(ContainerBuilder $container): void
49
    {
50
        $bundles = $container->getParameter('kernel.bundles');
51
52
        if (isset($bundles['NelmioApiDocBundle'])) {
53
            $container->prependExtensionConfig('nelmio_api_doc', [
54
                'documentation' => ['definitions' => require_once __DIR__ . '/../Resources/api-doc-definitions.php'],
55
            ]);
56
        }
57
    }
58
59
    protected function loadInternal(array $config, ContainerBuilder $container)
60
    {
61
        $container->register(JsonResponseFactory::class);
62
        $container->setAlias(ResponseFactory::class, $config['response_factory_service_id']);
63
64
        if ($config['api_key']['enabled']) {
65
            $this->configureApiKey($config['api_key'], $container);
66
        }
67
68
        if ($config['jwt']['enabled']) {
69
            $this->configureJwt($config['jwt'], $container);
70
        }
71
    }
72
73
    private function configureApiKey(array $config, ContainerBuilder $container): self
74
    {
75
        $extractors = $this->configureExtractors($config['extractors']);
76
77
        // User provider.
78
        $container->autowire('damax.api_auth.api_key.user_provider', StorageUserProvider::class);
79
80
        // Authenticator.
81
        $container
82
            ->register('damax.api_auth.api_key.authenticator', ApiKeyAuthenticator::class)
83
            ->addArgument($extractors)
84
            ->addArgument(new Reference(ResponseFactory::class))
85
        ;
86
87
        $container
88
            ->register(Generator::class, RandomGenerator::class)
89
            ->addArgument($config['generator']['key_size'])
90
        ;
91
92
        // Key factory.
93
        $container->autowire(Factory::class);
94
95
        return $this->configureKeyStorage($config['storage'], $container);
96
    }
97
98
    private function configureJwt(array $config, ContainerBuilder $container): self
99
    {
100
        $signer = $this->configureJwtSigner($config['signer']);
101
102
        $clock = new Definition(SystemClock::class);
103
104
        $configuration = (new Definition(JwtConfiguration::class))
105
            ->setFactory(JwtConfiguration::class . '::forSymmetricSigner')
106
            ->addArgument($signer)
107
            ->addArgument(new Definition(Key::class, [
108
                $config['signer']['signing_key'],
109
                $config['signer']['passphrase'],
110
            ]))
111
        ;
112
113
        if (Configuration::SIGNER_ASYMMETRIC === $config['signer']['type']) {
114
            $configuration
115
                ->setFactory(JwtConfiguration::class . '::forAsymmetricSigner')
116
                ->addArgument(new Definition(Key::class, [
117
                    $config['signer']['verification_key'],
118
                ]))
119
            ;
120
        }
121
122
        $parser = (new Definition(Parser::class))
123
            ->addArgument($configuration)
124
            ->addArgument($clock)
125
            ->addArgument($config['parser']['issuers'] ?? null)
126
            ->addArgument($config['parser']['audience'] ?? null)
127
        ;
128
129
        $claims = $this->configureJwtClaims($config['builder'], $clock, $container);
130
131
        $container
132
            ->register(TokenBuilder::class, Builder::class)
133
            ->addArgument($configuration)
134
            ->addArgument($claims)
135
        ;
136
137
        $extractors = $this->configureExtractors($config['extractors']);
138
139
        // Authenticator.
140
        $container
141
            ->register('damax.api_auth.jwt.authenticator', JwtAuthenticator::class)
142
            ->addArgument($extractors)
143
            ->addArgument(new Reference(ResponseFactory::class))
144
            ->addArgument($parser)
145
            ->addArgument($config['identity_claim'] ?? null)
146
        ;
147
148
        // Handler.
149
        $container->autowire('damax.api_auth.jwt.handler', AuthenticationHandler::class);
150
151
        // Controller
152
        $container
153
            ->autowire(TokenController::class)
154
            ->addTag('controller.service_arguments')
155
        ;
156
157
        return $this;
158
    }
159
160
    private function configureJwtClaims(array $config, Definition $clock, ContainerBuilder $container): Definition
161
    {
162
        // Default claims.
163
        $container
164
            ->register(TimestampClaims::class)
165
            ->addArgument($clock)
166
            ->addArgument($config['ttl'])
167
            ->addTag('damax.api_auth.jwt_claims')
168
        ;
169
        $container
170
            ->register(OrganizationClaims::class)
171
            ->addArgument($config['issuer'] ?? null)
172
            ->addArgument($config['audience'] ?? null)
173
            ->addTag('damax.api_auth.jwt_claims')
174
        ;
175
        $container
176
            ->register(SecurityClaims::class)
177
            ->addTag('damax.api_auth.jwt_claims')
178
        ;
179
180
        $container->setAlias(Claims::class, ClaimsCollector::class);
181
182
        return $container
183
            ->register(ClaimsCollector::class)
184
            ->addArgument(new TaggedIteratorArgument('damax.api_auth.jwt_claims'))
185
        ;
186
    }
187
188
    private function configureJwtSigner(array $config): Definition
189
    {
190
        $dirs = ['HS' => 'Hmac', 'RS' => 'Rsa', 'ES' => 'Ecdsa'];
191
        $algo = $config['algorithm'];
192
193
        return new Definition('Lcobucci\\JWT\\Signer\\' . $dirs[substr($algo, 0, 2)] . '\\Sha' . substr($algo, 2));
194
    }
195
196
    private function configureExtractors(array $config): Definition
197
    {
198
        $extractors = [];
199
200
        foreach ($config as $item) {
201
            $className = sprintf('Damax\\Bundle\\ApiAuthBundle\\Extractor\\%sExtractor', ucfirst($item['type']));
202
203
            $extractors[] = (new Definition($className))
204
                ->setArgument(0, $item['name'])
205
                ->setArgument(1, $item['prefix'] ?? null)
206
            ;
207
        }
208
209
        return new Definition(ChainExtractor::class, [$extractors]);
210
    }
211
212
    private function configureKeyStorage(array $config, ContainerBuilder $container): self
213
    {
214
        $drivers = [];
215
216
        // Default writable storage.
217
        $container->register(Writer::class, DummyStorage::class);
218
219
        foreach ($config as $item) {
220
            $drivers[] = $driver = new Definition();
221
222
            if (Configuration::STORAGE_REDIS === $item['type']) {
223
                $driver
224
                    ->setClass(RedisStorage::class)
225
                    ->addArgument(new Reference($item['redis_client_id']))
226
                    ->addArgument($item['key_prefix'] ?? '')
227
                ;
228
            } elseif (Configuration::STORAGE_DOCTRINE === $item['type']) {
229
                $driver
230
                    ->setClass(DoctrineStorage::class)
231
                    ->addArgument(new Reference($item['doctrine_connection_id']))
232
                    ->addArgument($item['table_name'])
233
                    ->addArgument($item['fields'] ?? [])
234
                ;
235
            } else {
236
                $driver
237
                    ->setClass(InMemoryStorage::class)
238
                    ->addArgument($item['tokens'])
239
                ;
240
            }
241
242
            if ($item['writable']) {
243
                $container->setDefinition(Writer::class, $driver);
244
            }
245
        }
246
247
        $container
248
            ->register(Reader::class, ChainStorage::class)
249
            ->addArgument($drivers)
250
        ;
251
252
        $container
253
            ->autowire(AddKeyCommand::class)
254
            ->addTag('console.command')
255
        ;
256
        $container
257
            ->autowire(LookupKeyCommand::class)
258
            ->addTag('console.command')
259
        ;
260
        $container
261
            ->autowire(RemoveKeyCommand::class)
262
            ->addTag('console.command')
263
        ;
264
265
        return $this;
266
    }
267
}
268