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 ( d1fd57...d85002 )
by Dmitri
01:47
created

DamaxApiAuthExtension::configureJwtSigner()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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