Completed
Push — master ( 9945e0...74c6f6 )
by Patrick
09:00 queued 07:59
created

Apple::getResourceOwnerDetailsUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace League\OAuth2\Client\Provider;
4
5
use Exception;
6
use InvalidArgumentException;
7
use Lcobucci\JWT\Builder;
8
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
9
use Lcobucci\JWT\Signer\Key;
10
use League\OAuth2\Client\Grant\AbstractGrant;
11
use League\OAuth2\Client\Provider\Exception\AppleAccessDeniedException;
12
use League\OAuth2\Client\Token\AccessToken;
13
use League\OAuth2\Client\Token\AccessTokenInterface;
14
use League\OAuth2\Client\Token\AppleAccessToken;
15
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
16
use Psr\Http\Message\ResponseInterface;
17
18
class Apple extends AbstractProvider
19
{
20
    use BearerAuthorizationTrait;
21
22
    /**
23
     * Default scopes
24
     *
25
     * @var array
26
     */
27
    public $defaultScopes = ['name', 'email'];
28
29
    /**
30
     * @var string the team id
31
     */
32
    protected $teamId;
33
34
    /**
35
     * @var string the key file id
36
     */
37
    protected $keyFileId;
38
39
    /**
40
     * @var string the key file path
41
     */
42
    protected $keyFilePath;
43
44
    /**
45
     * Constructs Apple's OAuth 2.0 service provider.
46
     *
47
     * @param array $options
48
     * @param array $collaborators
49
     */
50 13
    public function __construct(array $options = [], array $collaborators = [])
51
    {
52 13
        if (empty($options['teamId'])) {
53 1
            throw new InvalidArgumentException('Required option not passed: "teamId"');
54
        }
55
56 13
        if (empty($options['keyFileId'])) {
57 1
            throw new InvalidArgumentException('Required option not passed: "keyFileId"');
58
        }
59
60 13
        if (empty($options['keyFilePath'])) {
61 1
            throw new InvalidArgumentException('Required option not passed: "keyFilePath"');
62
        }
63
64 13
        parent::__construct($options, $collaborators);
65 13
    }
66
67
    /**
68
     * Creates an access token from a response.
69
     *
70
     * The grant that was used to fetch the response can be used to provide
71
     * additional context.
72
     *
73
     * @param  array         $response
74
     * @param  AbstractGrant $grant
75
     * @return AccessTokenInterface
76
     */
77 1
    protected function createAccessToken(array $response, AbstractGrant $grant)
78
    {
79 1
        return new AppleAccessToken($response);
80
    }
81
82
    /**
83
     * Get the string used to separate scopes.
84
     *
85
     * @return string
86
     */
87 3
    protected function getScopeSeparator()
88
    {
89 3
        return ' ';
90
    }
91
92
    /**
93
     * Change response mode when scope requires it
94
     *
95
     * @param array $options
96
     *
97
     * @return array
98
     */
99 3
    protected function getAuthorizationParameters(array $options)
100
    {
101 3
        $options = parent::getAuthorizationParameters($options);
102 3
        if (strpos($options['scope'], 'name') !== false || strpos($options['scope'], 'email') !== false) {
103 2
            $options['response_mode'] = 'form_post';
104
        }
105 3
        return $options;
106
    }
107
108
    /**
109
     * @param AccessToken $token
110
     *
111
     * @return mixed
112
     */
113 1
    protected function fetchResourceOwnerDetails(AccessToken $token)
114
    {
115 1
        return json_decode(array_key_exists('user', $_GET) ? $_GET['user']
116 1
            : (array_key_exists('user', $_POST) ? $_POST['user'] : '[]'), true);
117
    }
118
119
    /**
120
     * Get authorization url to begin OAuth flow
121
     *
122
     * @return string
123
     */
124 3
    public function getBaseAuthorizationUrl()
125
    {
126 3
        return 'https://appleid.apple.com/auth/authorize';
127
    }
128
129
    /**
130
     * Get access token url to retrieve token
131
     *
132
     * @return string
133
     */
134 2
    public function getBaseAccessTokenUrl(array $params)
135
    {
136 2
        return 'https://appleid.apple.com/auth/token';
137
    }
138
139
    /**
140
     * Get provider url to fetch user details
141
     *
142
     * @param AccessToken $token
143
     *
144
     * @return string
145
     * @throws Exception
146
     */
147 1
    public function getResourceOwnerDetailsUrl(AccessToken $token)
148
    {
149 1
        throw new Exception('No Apple ID REST API available yet!');
150
    }
151
152
    /**
153
     * Get the default scopes used by this provider.
154
     *
155
     * This should not be a complete list of all scopes, but the minimum
156
     * required for the provider user interface!
157
     *
158
     * @return array
159
     */
160 2
    protected function getDefaultScopes()
161
    {
162 2
        return $this->defaultScopes;
163
    }
164
165
    /**
166
     * Check a provider response for errors.
167
     *
168
     * @param  ResponseInterface $response
169
     * @param  array             $data     Parsed response data
170
     * @return void
171
     * @throws AppleAccessDeniedException
172
     */
173 2
    protected function checkResponse(ResponseInterface $response, $data)
174
    {
175 2
        if ($response->getStatusCode() >= 400) {
176 1
            throw new AppleAccessDeniedException(
177 1
                $data['error'] ?: $response->getReasonPhrase(),
178 1
                $data['code'] ?: $response->getStatusCode(),
179 1
                $response
0 ignored issues
show
Documentation introduced by
$response is of type object<Psr\Http\Message\ResponseInterface>, but the function expects a array|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
180
            );
181
        }
182 1
    }
183
184
    /**
185
     * Generate a user object from a successful user details request.
186
     *
187
     * @param array $response
188
     * @param AccessToken $token
189
     * @return AppleResourceOwner
190
     */
191 1
    protected function createResourceOwner(array $response, AccessToken $token)
192
    {
193 1
        return new AppleResourceOwner(
194 1
            array_merge(
195 1
                $response,
196
                [
197 1
                    'email' => isset($token->getValues()['email'])
198 1
                        ? $token->getValues()['email'] : (isset($response['email']) ? $response['email'] : null),
199 1
                    'isPrivateEmail' => $token instanceof AppleAccessToken ? $token->isPrivateEmail() : null
200
                ]
201
            ),
202 1
            $token->getResourceOwnerId()
203
        );
204
    }
205
206
    /**
207
     * {@inheritDoc}
208
     */
209 1
    public function getAccessToken($grant, array $options = [])
210
    {
211 1
        $signer = new Sha256();
212 1
        $time = time();
213
214 1
        $token = (new Builder())
215 1
            ->issuedBy($this->teamId)
216 1
            ->permittedFor('https://appleid.apple.com')
217 1
            ->issuedAt($time)
218 1
            ->expiresAt($time + 600)
219 1
            ->relatedTo($this->clientId)
220 1
            ->withClaim('sub', $this->clientId)
221 1
            ->withHeader('alg', 'ES256')
222 1
            ->withHeader('kid', $this->keyFileId)
223 1
            ->getToken($signer, $this->getLocalKey());
224
225
        $options += [
226 1
            'client_secret' => (string) $token
227
        ];
228
229 1
        return parent::getAccessToken($grant, $options);
230
    }
231
232
    /**
233
     * @return Key
234
     */
235 1
    public function getLocalKey()
236
    {
237 1
        return new Key('file://' . $this->keyFilePath);
238
    }
239
}
240