Completed
Push — 3.x ( 497b30...ca6623 )
by Дмитрий
03:36 queued 53s
created

AbstractProvider::discover()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 2
b 0
f 0
nc 1
nop 0
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 2
rs 10
1
<?php
2
/**
3
 * SocialConnect project
4
 * @author: Patsura Dmitry https://github.com/ovr <[email protected]>
5
 */
6
declare(strict_types=1);
7
8
namespace SocialConnect\OpenIDConnect;
9
10
use SocialConnect\JWX\DecodeOptions;
11
use SocialConnect\JWX\JWKSet;
12
use SocialConnect\JWX\JWT;
13
use SocialConnect\Provider\Exception\InvalidAccessToken;
14
use SocialConnect\Provider\Exception\InvalidResponse;
15
16
abstract class AbstractProvider extends \SocialConnect\OAuth2\AbstractProvider
17
{
18
    /**
19
     * @return array
20
     * @throws InvalidResponse
21
     * @throws \Psr\Http\Client\ClientExceptionInterface
22
     */
23
    public function discover(): array
24
    {
25
        return $this->hydrateResponse(
26
            $this->executeRequest(
27
                $this->httpStack->createRequest('GET', $this->getOpenIdUrl())
28
            )
29
        );
30
    }
31
32
    /**
33
     * @return JWKSet
34
     * @throws InvalidResponse
35
     * @throws \Psr\Http\Client\ClientExceptionInterface
36
     */
37
    public function getJWKSet(): JWKSet
38
    {
39
        $spec = $this->discover();
40
41
        if (!isset($spec['jwks_uri'])) {
42
            throw new \RuntimeException('Unknown jwks_uri inside OpenIDConnect specification');
43
        }
44
45
        $response = $this->executeRequest(
46
            $this->httpStack->createRequest('GET', $spec['jwks_uri'])
47
        );
48
49
        $result = $this->hydrateResponse($response);
50
51
        if (!isset($result['keys'])) {
52
            throw new InvalidResponse(
53
                'API response without "keys" key inside JSON',
54
                $response
55
            );
56
        }
57
58
        return new JWKSet($result);
59
    }
60
61
    /**
62
     * @return string
63
     */
64
    abstract public function getOpenIdUrl();
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function getAuthUrlParameters(): array
70
    {
71
        $parameters = parent::getAuthUrlParameters();
72
73
        // special parameters only required for OpenIDConnect
74
        $parameters['client_id'] = $this->consumer->getKey();
75
        $parameters['redirect_uri'] = $this->getRedirectUrl();
76
        $parameters['response_type'] = 'code';
77
        // Optional field...
78
        //$parameters['response_mode'] = 'form_post';
79
        $parameters['scope'] = 'openid';
80
81
        return $parameters;
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87 4
    public function parseToken(string $body)
88
    {
89 4
        if (empty($body)) {
90 2
            throw new InvalidAccessToken('Provider response with empty body');
91
        }
92
93 2
        $result = json_decode($body, true);
94 2
        if ($result) {
95
            $token = new AccessToken($result);
96
            $token->setJwt(
97
                JWT::decode($result['id_token'], $this->getJWKSet(), new DecodeOptions())
98
            );
99
100
            return $token;
101
        }
102
103 2
        throw new InvalidAccessToken('Provider response with not valid JSON');
104
    }
105
106
    /**
107
     * {@inheritDoc}
108
     */
109
    public function createAccessToken(array $information)
110
    {
111
        $token = new AccessToken($information);
112
        $token->setJwt(
113
            JWT::decode($information['id_token'], $this->getJWKSet(), new DecodeOptions())
114
        );
115
116
        return $token;
117
    }
118
}
119