DiscoveryProvider   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Test Coverage

Coverage 81.48%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
dl 0
loc 67
ccs 22
cts 27
cp 0.8148
rs 10
c 1
b 0
f 0
wmc 13

3 Methods

Rating   Name   Duplication   Size   Complexity  
A fetchOpenIdConfiguration() 0 16 3
A __construct() 0 8 4
A discovery() 0 24 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TMV\OpenIdClient\Issuer\Metadata\Provider;
6
7
use function array_key_exists;
8
use Http\Discovery\Psr17FactoryDiscovery;
9
use Http\Discovery\Psr18ClientDiscovery;
10
use Psr\Http\Client\ClientExceptionInterface;
11
use Psr\Http\Client\ClientInterface;
12
use Psr\Http\Message\RequestFactoryInterface;
13
use Psr\Http\Message\UriFactoryInterface;
14
use function rtrim;
15
use function strpos;
16
use TMV\OpenIdClient\Exception\RuntimeException;
17
use function TMV\OpenIdClient\parse_metadata_response;
18
19
final class DiscoveryProvider implements DiscoveryProviderInterface
20
{
21
    private const OIDC_DISCOVERY = '/.well-known/openid-configuration';
22
23
    private const OAUTH2_DISCOVERY = '/.well-known/oauth-authorization-server';
24
25
    /** @var ClientInterface */
26
    private $client;
27
28
    /** @var RequestFactoryInterface */
29
    private $requestFactory;
30
31
    /** @var UriFactoryInterface */
32
    private $uriFactory;
33
34 3
    public function __construct(
35
        ?ClientInterface $client = null,
36
        ?RequestFactoryInterface $requestFactory = null,
37
        ?UriFactoryInterface $uriFactory = null
38
    ) {
39 3
        $this->client = $client ?: Psr18ClientDiscovery::find();
40 3
        $this->requestFactory = $requestFactory ?: Psr17FactoryDiscovery::findRequestFactory();
41 3
        $this->uriFactory = $uriFactory ?: Psr17FactoryDiscovery::findUrlFactory();
42 3
    }
43
44 2
    public function discovery(string $url): array
45
    {
46 2
        $uri = $this->uriFactory->createUri($url);
47 2
        $uriPath = $uri->getPath() ?: '/';
48
49 2
        if (false !== strpos($uriPath, '/.well-known/')) {
50 1
            return $this->fetchOpenIdConfiguration((string) $uri);
51
        }
52
53
        $uris = [
54 1
            $uri->withPath(rtrim($uriPath, '/') . self::OIDC_DISCOVERY),
55 1
            $uri->withPath('/' === $uriPath
56 1
                ? self::OAUTH2_DISCOVERY
57 1
                : self::OAUTH2_DISCOVERY . $uriPath),
58
        ];
59
60 1
        foreach ($uris as $wellKnownUri) {
61
            try {
62 1
                return $this->fetchOpenIdConfiguration((string) $wellKnownUri);
63
            } catch (RuntimeException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
64
            }
65
        }
66
67
        throw new RuntimeException('Unable to fetch provider metadata');
68
    }
69
70 2
    private function fetchOpenIdConfiguration(string $uri): array
71
    {
72 2
        $request = $this->requestFactory->createRequest('GET', $uri)
73 2
            ->withHeader('accept', 'application/json');
74
75
        try {
76 2
            $data = parse_metadata_response($this->client->sendRequest($request));
77
        } catch (ClientExceptionInterface $e) {
78
            throw new RuntimeException('Unable to fetch provider metadata', 0, $e);
79
        }
80
81 2
        if (! array_key_exists('issuer', $data)) {
82
            throw new RuntimeException('Invalid metadata content, no "issuer" key found');
83
        }
84
85 2
        return $data;
86
    }
87
}
88