Completed
Push — master ( 483eda...cb59ac )
by Дмитрий
03:04
created

AbstractProvider::discover()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 40
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 40
rs 8.5806
cc 4
eloc 22
nc 4
nop 1
1
<?php
2
/**
3
 * SocialConnect project
4
 * @author: Patsura Dmitry https://github.com/ovr <[email protected]>
5
 */
6
7
namespace SocialConnect\OpenID;
8
9
use SocialConnect\Auth\AbstractBaseProvider;
10
use SocialConnect\Auth\Provider\Exception\InvalidAccessToken;
11
use SocialConnect\Auth\Provider\Exception\InvalidResponse;
12
use SocialConnect\Common\Http\Client\Client;
13
14
abstract class AbstractProvider extends AbstractBaseProvider
15
{
16
    /**
17
     * @return string
18
     */
19
    abstract public function getOpenIdUrl();
20
21
    /**
22
     * @var int
23
     */
24
    protected $version;
25
26
    /**
27
     * @var string
28
     */
29
    protected $loginEntrypoint;
30
31
    /**
32
     * @param bool $immediate
33
     * @return string
34
     */
35
    protected function makeAuthUrlV2($immediate)
36
    {
37
        $params = array(
38
            'openid.ns' => 'http://specs.openid.net/auth/2.0',
39
            'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
40
            'openid.return_to' => $this->getRedirectUrl(),
41
            'openid.realm' => $this->getRedirectUrl()
42
        );
43
44
        $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
45
        $params['openid.identity'] = $params['openid.claimed_id'] = 'http://specs.openid.net/auth/2.0/identifier_select';
46
47
        return $this->loginEntrypoint . '?' . http_build_query($params, '', '&');
48
    }
49
50
    /**
51
     * @param string $url
52
     * @return string
53
     * @throws InvalidResponse
54
     */
55
    protected function discover($url)
56
    {
57
        $response = $this->service->getHttpClient()->request(
58
            $url,
59
            [],
60
            Client::GET,
61
            [
62
                'Content-Type' => 'application/json'
63
            ]
64
        );
65
66
        if (!$response->isSuccess()) {
67
            throw new InvalidResponse(
68
                'API response with error code',
69
                $response
70
            );
71
        }
72
73
        if (!$response->hasHeader('Content-Type')) {
74
            throw new InvalidResponse(
75
                'Unknown Content-Type',
76
                $response
77
            );
78
        }
79
80
        $contentType = $response->getHeader('Content-Type');
81
        if (strpos($contentType, 'application/xrds+xml;charset=utf-8') === false) {
82
            throw new InvalidResponse(
83
                'Unexpected Content-Type',
84
                $response
85
            );
86
        }
87
88
        $xml = new \SimpleXMLElement($response->getBody());
89
90
        $this->version = 2;
91
        $this->loginEntrypoint = $xml->XRD->Service->URI;
92
93
        return $this->getOpenIdUrl();
94
    }
95
96
    public function makeAuthUrl()
97
    {
98
        $this->discover($this->getOpenIdUrl());
99
100
        return $this->makeAuthUrlV2(false);
101
    }
102
103
    /**
104
     * @link http://openid.net/specs/openid-authentication-2_0.html#verification
105
     *
106
     * @param $requestParameters
107
     * @return AccessToken
108
     * @throws InvalidAccessToken
109
     */
110
    public function getAccessTokenByRequestParameters($requestParameters)
111
    {
112
        $params = array(
113
            'openid.assoc_handle' => $requestParameters['openid_assoc_handle'],
114
            'openid.signed' => $requestParameters['openid_signed'],
115
            'openid.sig' => $requestParameters['openid_sig'],
116
            'openid.ns' => $requestParameters['openid_ns'],
117
            'openid.op_endpoint' => $requestParameters['openid_op_endpoint'],
118
            'openid.claimed_id' => $requestParameters['openid_claimed_id'],
119
            'openid.identity' => $requestParameters['openid_identity'],
120
            'openid.return_to' => $this->getRedirectUrl(),
121
            'openid.response_nonce' => $requestParameters['openid_response_nonce'],
122
            'openid.mode' => 'check_authentication'
123
        );
124
125
        if (isset($requestParameters['openid_claimed_id'])) {
126
            $claimedId = $requestParameters['openid_claimed_id'];
127
        } else {
128
            $claimedId = $requestParameters['openid_identity'];
129
        }
130
131
        $this->discover($claimedId);
132
133
        $response = $this->service->getHttpClient()->request(
134
            $this->loginEntrypoint,
135
            $params,
136
            Client::POST
137
        );
138
139
        if (preg_match('/is_valid\s*:\s*true/i', $response->getBody())) {
140
            return new AccessToken($requestParameters['openid_identity']);
141
        }
142
143
        throw new InvalidAccessToken;
144
    }
145
}
146