1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * This file is part of the cilogon/oauth2-orcid library. |
||||
5 | * |
||||
6 | * For the full copyright and license information, please view the LICENSE |
||||
7 | * file that was distributed with this source code. |
||||
8 | * |
||||
9 | * @author Terry Fleury <[email protected]> |
||||
10 | * @copyright 2021 University of Illinois |
||||
11 | * @license https://opensource.org/licenses/NCSA NCSA |
||||
12 | * @link https://github.com/cilogon/oauth2-orcid GitHub |
||||
13 | */ |
||||
14 | |||||
15 | namespace CILogon\OAuth2\Client\Provider; |
||||
16 | |||||
17 | use League\OAuth2\Client\Provider\AbstractProvider; |
||||
18 | use League\OAuth2\Client\Provider\Exception\IdentityProviderException; |
||||
19 | use League\OAuth2\Client\Token\AccessToken; |
||||
20 | use League\OAuth2\Client\Tool\BearerAuthorizationTrait; |
||||
21 | use Psr\Http\Message\ResponseInterface; |
||||
22 | use Lcobucci\JWT\Parser; |
||||
23 | |||||
24 | class ORCID extends AbstractProvider |
||||
25 | { |
||||
26 | use BearerAuthorizationTrait; |
||||
27 | |||||
28 | /** |
||||
29 | * @var string Key used in the access token response to identify the resource owner. |
||||
30 | */ |
||||
31 | public const ACCESS_TOKEN_RESOURCE_OWNER_ID = 'orcid'; |
||||
32 | |||||
33 | /** |
||||
34 | * @var string |
||||
35 | */ |
||||
36 | public $sandbox = false; |
||||
37 | |||||
38 | /** |
||||
39 | * @var string |
||||
40 | */ |
||||
41 | public $member = false; |
||||
42 | |||||
43 | /** |
||||
44 | * Returns the base URL for authorizing a client. |
||||
45 | * |
||||
46 | * @return string |
||||
47 | */ |
||||
48 | public function getBaseAuthorizationUrl() |
||||
49 | { |
||||
50 | return 'https://' . |
||||
51 | (($this->sandbox) ? 'sandbox.' : '') . |
||||
52 | 'orcid.org/oauth/authorize'; |
||||
53 | } |
||||
54 | |||||
55 | /** |
||||
56 | * Returns the base URL for requesting an access token. |
||||
57 | * |
||||
58 | * @param array $params |
||||
59 | * @return string |
||||
60 | */ |
||||
61 | public function getBaseAccessTokenUrl(array $params) |
||||
62 | { |
||||
63 | return 'https://' . |
||||
64 | (($this->sandbox) ? 'sandbox.' : '') . |
||||
65 | 'orcid.org/oauth/token'; |
||||
66 | } |
||||
67 | |||||
68 | /** |
||||
69 | * Returns the URL for requesting the resource owner's details. |
||||
70 | * |
||||
71 | * @param AccessToken $token |
||||
72 | * |
||||
73 | * @return string |
||||
74 | */ |
||||
75 | public function getResourceOwnerDetailsUrl(AccessToken $token) |
||||
76 | { |
||||
77 | return 'https://' . |
||||
78 | (($this->member) ? 'api.' : 'pub.') . |
||||
79 | (($this->sandbox) ? 'sandbox.' : '') . |
||||
80 | 'orcid.org/v2.0/' . |
||||
81 | $token->getResourceOwnerId() . |
||||
82 | '/record'; |
||||
83 | } |
||||
84 | |||||
85 | /** |
||||
86 | * Returns the default scopes used by this provider. |
||||
87 | * |
||||
88 | * This should only be the scopes that are required to request the details |
||||
89 | * of the resource owner, rather than all the available scopes. |
||||
90 | * |
||||
91 | * @return array |
||||
92 | */ |
||||
93 | protected function getDefaultScopes() |
||||
94 | { |
||||
95 | return [ '/authenticate' ]; |
||||
96 | } |
||||
97 | |||||
98 | /** |
||||
99 | * Returns the string that should be used to separate scopes when building |
||||
100 | * the URL for requesting an access token. |
||||
101 | * |
||||
102 | * @return string Scope separator, defaults to ',' |
||||
103 | */ |
||||
104 | protected function getScopeSeparator() |
||||
105 | { |
||||
106 | return ' '; |
||||
107 | } |
||||
108 | |||||
109 | /** |
||||
110 | * Returns the default headers used by this provider. |
||||
111 | * |
||||
112 | * Typically this is used to set 'Accept' or 'Content-Type' headers. |
||||
113 | * |
||||
114 | * @return array |
||||
115 | */ |
||||
116 | protected function getDefaultHeaders() |
||||
117 | { |
||||
118 | return [ 'Accept' => 'application/json' ]; |
||||
119 | } |
||||
120 | |||||
121 | |||||
122 | /** |
||||
123 | * Check a provider response for errors. |
||||
124 | * |
||||
125 | * @throws IdentityProviderException |
||||
126 | * @param ResponseInterface $response |
||||
127 | * @param string $data Parsed response data |
||||
128 | * @return void |
||||
129 | */ |
||||
130 | protected function checkResponse(ResponseInterface $response, $data) |
||||
131 | { |
||||
132 | $error = false; |
||||
133 | $errcode = 0; |
||||
134 | $errmsg = ''; |
||||
135 | |||||
136 | if (!empty($data['error'])) { |
||||
137 | $error = true; |
||||
138 | $errmsg = $data['error']; |
||||
139 | if (!empty($data['error_description'])) { |
||||
140 | $errmsg .= ': ' . $data['error_description']; |
||||
141 | } |
||||
142 | } elseif (!empty($data['error-code'])) { |
||||
143 | $error = true; |
||||
144 | $errcode = (int)$data['error-code']; |
||||
145 | if (!empty($data['developer-message'])) { |
||||
146 | $errmsg = $data['developer-message']; |
||||
147 | } |
||||
148 | } elseif ($response->getStatusCode() >= 400) { |
||||
149 | $error = true; |
||||
150 | $errcode = $response->getStatusCode(); |
||||
151 | $errmsg = $response->getReasonPhrase(); |
||||
152 | } |
||||
153 | |||||
154 | if ($error) { |
||||
155 | throw new IdentityProviderException($errmsg, $errcode, $data); |
||||
156 | } |
||||
157 | } |
||||
158 | |||||
159 | /** |
||||
160 | * Generate a user object from a successful user details request. |
||||
161 | * |
||||
162 | * @param object $response |
||||
163 | * @param AccessToken $token |
||||
164 | * @return ORCIDResourceOwner |
||||
165 | */ |
||||
166 | protected function createResourceOwner(array $response, AccessToken $token) |
||||
167 | { |
||||
168 | // Attempt to extract 'amr' (AuthnMethodRef) from the id_token |
||||
169 | // and add it to the response. Note that 'amr' is available only |
||||
170 | // when using the Member API. |
||||
171 | $values = $token->getValues(); |
||||
172 | if (array_key_exists('id_token', $values)) { |
||||
173 | $jwt = $values['id_token']; |
||||
174 | try { |
||||
175 | $read = (new Parser())->parse((string) $jwt); |
||||
176 | if ($read->hasClaim('amr')) { |
||||
0 ignored issues
–
show
|
|||||
177 | $amr = $read->getClaim('amr'); |
||||
0 ignored issues
–
show
The function
Lcobucci\JWT\Token::getClaim() has been deprecated: This method has been removed from the interface in v4.0
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
178 | if (strlen($amr) > 0) { |
||||
179 | $response['amr'] = $amr; |
||||
180 | } |
||||
181 | } |
||||
182 | } catch (\Exception $e) { |
||||
183 | // Do not set 'amr' in case of errors. |
||||
184 | } |
||||
185 | } |
||||
186 | |||||
187 | return new ORCIDResourceOwner($response); |
||||
188 | } |
||||
189 | |||||
190 | /** |
||||
191 | * Returns a prepared request for requesting an access token. |
||||
192 | * |
||||
193 | * @param array $params Query string parameters |
||||
194 | * @return \GuzzleHttp\Psr7\Request |
||||
195 | */ |
||||
196 | protected function getAccessTokenRequest(array $params, $accesstoken = null) |
||||
197 | { |
||||
198 | $method = $this->getAccessTokenMethod(); |
||||
199 | $url = $this->getAccessTokenUrl($params); |
||||
200 | $options = $this->optionProvider->getAccessTokenOptions($method, $params); |
||||
201 | if (is_null($accesstoken)) { |
||||
202 | return $this->getRequest($method, $url, $options); |
||||
203 | } else { |
||||
204 | return $this->getAuthenticatedRequest($method, $url, $accesstoken, $options); |
||||
205 | } |
||||
206 | } |
||||
207 | /** |
||||
208 | * Requests an access token using a specified grant and option set. |
||||
209 | * |
||||
210 | * @param mixed $grant |
||||
211 | * @param array $options |
||||
212 | * @return AccessToken |
||||
213 | */ |
||||
214 | public function getAccessToken($grant, array $options = [], $accesstoken = null) |
||||
215 | { |
||||
216 | $grant = $this->verifyGrant($grant); |
||||
217 | $params = [ |
||||
218 | 'client_id' => $this->clientId, |
||||
219 | 'client_secret' => $this->clientSecret, |
||||
220 | 'redirect_uri' => $this->redirectUri, |
||||
221 | ]; |
||||
222 | $params = $grant->prepareRequestParameters($params, $options); |
||||
223 | $request = $this->getAccessTokenRequest($params, $accesstoken); |
||||
224 | $response = $this->getParsedResponse($request); |
||||
225 | $prepared = $this->prepareAccessTokenResponse($response); |
||||
226 | $token = $this->createAccessToken($prepared, $grant); |
||||
227 | return $token; |
||||
228 | } |
||||
229 | } |
||||
230 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.