Completed
Push — master ( bda8d5...d74c6d )
by Дмитрий
03:32 queued 01:52
created

AbstractProvider::discover()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 20
c 2
b 0
f 0
nc 4
nop 1
dl 0
loc 36
ccs 0
cts 22
cp 0
crap 20
rs 9.6
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\OpenID;
9
10
use SocialConnect\Provider\AbstractBaseProvider;
11
use SocialConnect\Provider\Exception\InvalidAccessToken;
12
use SocialConnect\Provider\Exception\InvalidResponse;
13
use SocialConnect\Common\Http\Client\Client;
14
15
abstract class AbstractProvider extends AbstractBaseProvider
16
{
17
    /**
18
     * @return string
19
     */
20
    abstract public function getOpenIdUrl();
21
22
    /**
23
     * @var int
24
     */
25
    protected $version;
26
27
    /**
28
     * @var string
29
     */
30
    protected $loginEntrypoint;
31
32
    /**
33
     * @param bool $immediate
34
     * @return string
35
     */
36
    protected function makeAuthUrlV2($immediate)
37
    {
38
        $params = [
39
            'openid.ns' => 'http://specs.openid.net/auth/2.0',
40
            'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
41
            'openid.return_to' => $this->getRedirectUrl(),
42
            'openid.realm' => $this->getRedirectUrl()
43
        ];
44
45
        $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
46
        $params['openid.identity'] = $params['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select';
47
48
        return $this->loginEntrypoint . '?' . http_build_query($params, '', '&');
49
    }
50
51
    /**
52
     * @param string $url
53
     * @return string
54
     * @throws InvalidResponse
55
     */
56
    protected function discover($url)
57
    {
58
        $response = $this->httpClient->request(
59
            $url,
60
            [],
61
            Client::GET
62
        );
63
64
        if (!$response->isSuccess()) {
65
            throw new InvalidResponse(
66
                'API response with error code',
67
                $response
68
            );
69
        }
70
71
        if (!$response->hasHeader('Content-Type')) {
72
            throw new InvalidResponse(
73
                'Unknown Content-Type',
74
                $response
75
            );
76
        }
77
78
        $contentType = $response->getHeader('Content-Type');
79
        if (strpos($contentType, 'application/xrds+xml;charset=utf-8') === false) {
80
            throw new InvalidResponse(
81
                'Unexpected Content-Type',
82
                $response
83
            );
84
        }
85
86
        $xml = new \SimpleXMLElement($response->getBody());
87
88
        $this->version = 2;
89
        $this->loginEntrypoint = $xml->XRD->Service->URI;
90
91
        return $this->getOpenIdUrl();
92
    }
93
94
    /**
95
     * {@inheritdoc}
96
     */
97
    public function makeAuthUrl(): string
98
    {
99
        $this->discover($this->getOpenIdUrl());
100
101
        return $this->makeAuthUrlV2(false);
102
    }
103
104
    /**
105
     * @param string $identity
106
     * @return int
107
     */
108
    protected function parseUserIdFromIdentity($identity)
0 ignored issues
show
Unused Code introduced by
The parameter $identity is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

108
    protected function parseUserIdFromIdentity(/** @scrutinizer ignore-unused */ $identity)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
109
    {
110
        return null;
111
    }
112
113
    /**
114
     * @link http://openid.net/specs/openid-authentication-2_0.html#verification
115
     *
116
     * @param $requestParameters
117
     * @return AccessToken
118
     * @throws InvalidAccessToken
119
     */
120
    public function getAccessTokenByRequestParameters(array $requestParameters)
121
    {
122
        $params = [
123
            'openid.assoc_handle' => $requestParameters['openid_assoc_handle'],
124
            'openid.signed' => $requestParameters['openid_signed'],
125
            'openid.sig' => $requestParameters['openid_sig'],
126
            'openid.ns' => $requestParameters['openid_ns'],
127
            'openid.op_endpoint' => $requestParameters['openid_op_endpoint'],
128
            'openid.claimed_id' => $requestParameters['openid_claimed_id'],
129
            'openid.identity' => $requestParameters['openid_identity'],
130
            'openid.return_to' => $this->getRedirectUrl(),
131
            'openid.response_nonce' => $requestParameters['openid_response_nonce'],
132
            'openid.mode' => 'check_authentication'
133
        ];
134
135
        if (isset($requestParameters['openid_claimed_id'])) {
136
            $claimedId = $requestParameters['openid_claimed_id'];
137
        } else {
138
            $claimedId = $requestParameters['openid_identity'];
139
        }
140
141
        $this->discover($claimedId);
142
143
        $response = $this->httpClient->request(
144
            $this->loginEntrypoint,
145
            $params,
146
            Client::POST
147
        );
148
149
        if (preg_match('/is_valid\s*:\s*true/i', $response->getBody())) {
150
            return new AccessToken(
151
                $requestParameters['openid_identity'],
152
                $this->parseUserIdFromIdentity(
153
                    $requestParameters['openid_identity']
154
                )
155
            );
156
        }
157
158
        throw new InvalidAccessToken;
159
    }
160
}
161