Completed
Branch master (bda8d5)
by Дмитрий
02:19
created

AbstractProvider::getJWKSet()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 35
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 35
rs 9.3222
c 0
b 0
f 0
ccs 0
cts 20
cp 0
cc 5
nc 5
nop 0
crap 30
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\Provider\Exception\InvalidAccessToken;
11
use SocialConnect\Provider\Exception\InvalidResponse;
12
13
abstract class AbstractProvider extends \SocialConnect\OAuth2\AbstractProvider
14
{
15
    /**
16
     * @return array
17
     * @throws InvalidResponse
18
     */
19
    public function discover()
20
    {
21
        $response = $this->httpClient->request(
22
            $this->getOpenIdUrl()
23
        );
24
25
        if (!$response->isSuccess()) {
26
            throw new InvalidResponse(
27
                'API response with error code',
28
                $response
29
            );
30
        }
31
32
        $result = $response->json(true);
33
        if (!$result) {
34
            throw new InvalidResponse(
35
                'API response without valid JSON',
36
                $response
37
            );
38
        }
39
40
        return $result;
41
    }
42
43
    /**
44
     * @return array
45
     * @throws InvalidResponse
46
     */
47
    public function getJWKSet()
48
    {
49
        $spec = $this->discover();
50
51
        if (!isset($spec['jwks_uri'])) {
52
            throw new \RuntimeException('Unknown jwks_uri inside OpenIDConnect specification');
53
        }
54
55
        $response = $this->httpClient->request(
56
            $spec['jwks_uri']
57
        );
58
59
        if (!$response->isSuccess()) {
60
            throw new InvalidResponse(
61
                'API response with error code',
62
                $response
63
            );
64
        }
65
66
        $result = $response->json(true);
67
        if (!$result) {
68
            throw new InvalidResponse(
69
                'API response without valid JSON',
70
                $response
71
            );
72
        }
73
74
        if (!isset($result['keys'])) {
75
            throw new InvalidResponse(
76
                'API response without "keys" key inside JSON',
77
                $response
78
            );
79
        }
80
81
        return $result['keys'];
82
    }
83
84
    /**
85
     * @return string
86
     */
87
    abstract public function getOpenIdUrl();
88
89
    /**
90
     * {@inheritdoc}
91
     */
92
    public function getAuthUrlParameters(): array
93
    {
94
        $parameters = parent::getAuthUrlParameters();
95
96
        // special parameters only required for OpenIDConnect
97
        $parameters['client_id'] = $this->consumer->getKey();
98
        $parameters['redirect_uri'] = $this->getRedirectUrl();
99
        $parameters['response_type'] = 'code';
100
        // Optional field...
101
        //$parameters['response_mode'] = 'form_post';
102
        $parameters['scope'] = 'openid';
103
104
        return $parameters;
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function parseToken($body)
111
    {
112
        $result = json_decode($body, true);
113
        if ($result) {
114
            $token = new AccessToken($result);
115
            $token->setJwt(
116
                JWT::decode($result['id_token'], $this->getJWKSet())
117
            );
118
119
            return $token;
120
        }
121
122
        throw new InvalidAccessToken('Provider response with not valid JSON');
123
    }
124
}
125