PluginProbe
WP-Stateless – Google Cloud Storage / 3.0.3
WP-Stateless – Google Cloud Storage v3.0.3
4.4.3 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.3.0 2.3.1 2.3.2 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 All 62 releases
wp-stateless / lib / Google / vendor / google / auth / src / OAuth2.php

OAuth2.php in WP-Stateless – Google Cloud Storage 3.0.3, at lib/Google/vendor/google/auth/src/OAuth2.php

1,409 lines 35.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * Copyright 2015 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 namespace Google\Auth;
19
20 use Google\Auth\HttpHandler\HttpClientCache;
21 use Google\Auth\HttpHandler\HttpHandlerFactory;
22 use GuzzleHttp\Psr7;
23 use GuzzleHttp\Psr7\Request;
24 use InvalidArgumentException;
25 use Psr\Http\Message\RequestInterface;
26 use Psr\Http\Message\ResponseInterface;
27 use Psr\Http\Message\UriInterface;
28
29 /**
30 * OAuth2 supports authentication by OAuth2 2-legged flows.
31 *
32 * It primary supports
33 * - service account authorization
34 * - authorization where a user already has an access token
35 */
36 class OAuth2 implements FetchAuthTokenInterface
37 {
38 const DEFAULT_EXPIRY_SECONDS = 3600; // 1 hour
39 const DEFAULT_SKEW_SECONDS = 60; // 1 minute
40 const JWT_URN = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
41
42 /**
43 * TODO: determine known methods from the keys of JWT::methods.
44 */
45 public static $knownSigningAlgorithms = array(
46 'HS256',
47 'HS512',
48 'HS384',
49 'RS256',
50 );
51
52 /**
53 * The well known grant types.
54 *
55 * @var array
56 */
57 public static $knownGrantTypes = array(
58 'authorization_code',
59 'refresh_token',
60 'password',
61 'client_credentials',
62 );
63
64 /**
65 * - authorizationUri
66 * The authorization server's HTTP endpoint capable of
67 * authenticating the end-user and obtaining authorization.
68 *
69 * @var UriInterface
70 */
71 private $authorizationUri;
72
73 /**
74 * - tokenCredentialUri
75 * The authorization server's HTTP endpoint capable of issuing
76 * tokens and refreshing expired tokens.
77 *
78 * @var UriInterface
79 */
80 private $tokenCredentialUri;
81
82 /**
83 * The redirection URI used in the initial request.
84 *
85 * @var string
86 */
87 private $redirectUri;
88
89 /**
90 * A unique identifier issued to the client to identify itself to the
91 * authorization server.
92 *
93 * @var string
94 */
95 private $clientId;
96
97 /**
98 * A shared symmetric secret issued by the authorization server, which is
99 * used to authenticate the client.
100 *
101 * @var string
102 */
103 private $clientSecret;
104
105 /**
106 * The resource owner's username.
107 *
108 * @var string
109 */
110 private $username;
111
112 /**
113 * The resource owner's password.
114 *
115 * @var string
116 */
117 private $password;
118
119 /**
120 * The scope of the access request, expressed either as an Array or as a
121 * space-delimited string.
122 *
123 * @var array
124 */
125 private $scope;
126
127 /**
128 * An arbitrary string designed to allow the client to maintain state.
129 *
130 * @var string
131 */
132 private $state;
133
134 /**
135 * The authorization code issued to this client.
136 *
137 * Only used by the authorization code access grant type.
138 *
139 * @var string
140 */
141 private $code;
142
143 /**
144 * The issuer ID when using assertion profile.
145 *
146 * @var string
147 */
148 private $issuer;
149
150 /**
151 * The target audience for assertions.
152 *
153 * @var string
154 */
155 private $audience;
156
157 /**
158 * The target sub when issuing assertions.
159 *
160 * @var string
161 */
162 private $sub;
163
164 /**
165 * The number of seconds assertions are valid for.
166 *
167 * @var int
168 */
169 private $expiry;
170
171 /**
172 * The signing key when using assertion profile.
173 *
174 * @var string
175 */
176 private $signingKey;
177
178 /**
179 * The signing key id when using assertion profile. Param kid in jwt header
180 *
181 * @var string
182 */
183 private $signingKeyId;
184
185 /**
186 * The signing algorithm when using an assertion profile.
187 *
188 * @var string
189 */
190 private $signingAlgorithm;
191
192 /**
193 * The refresh token associated with the access token to be refreshed.
194 *
195 * @var string
196 */
197 private $refreshToken;
198
199 /**
200 * The current access token.
201 *
202 * @var string
203 */
204 private $accessToken;
205
206 /**
207 * The current ID token.
208 *
209 * @var string
210 */
211 private $idToken;
212
213 /**
214 * The lifetime in seconds of the current access token.
215 *
216 * @var int
217 */
218 private $expiresIn;
219
220 /**
221 * The expiration time of the access token as a number of seconds since the
222 * unix epoch.
223 *
224 * @var int
225 */
226 private $expiresAt;
227
228 /**
229 * The issue time of the access token as a number of seconds since the unix
230 * epoch.
231 *
232 * @var int
233 */
234 private $issuedAt;
235
236 /**
237 * The current grant type.
238 *
239 * @var string
240 */
241 private $grantType;
242
243 /**
244 * When using an extension grant type, this is the set of parameters used by
245 * that extension.
246 */
247 private $extensionParams;
248
249 /**
250 * When using the toJwt function, these claims will be added to the JWT
251 * payload.
252 */
253 private $additionalClaims;
254
255 /**
256 * Create a new OAuthCredentials.
257 *
258 * The configuration array accepts various options
259 *
260 * - authorizationUri
261 * The authorization server's HTTP endpoint capable of
262 * authenticating the end-user and obtaining authorization.
263 *
264 * - tokenCredentialUri
265 * The authorization server's HTTP endpoint capable of issuing
266 * tokens and refreshing expired tokens.
267 *
268 * - clientId
269 * A unique identifier issued to the client to identify itself to the
270 * authorization server.
271 *
272 * - clientSecret
273 * A shared symmetric secret issued by the authorization server,
274 * which is used to authenticate the client.
275 *
276 * - scope
277 * The scope of the access request, expressed either as an Array
278 * or as a space-delimited String.
279 *
280 * - state
281 * An arbitrary string designed to allow the client to maintain state.
282 *
283 * - redirectUri
284 * The redirection URI used in the initial request.
285 *
286 * - username
287 * The resource owner's username.
288 *
289 * - password
290 * The resource owner's password.
291 *
292 * - issuer
293 * Issuer ID when using assertion profile
294 *
295 * - audience
296 * Target audience for assertions
297 *
298 * - expiry
299 * Number of seconds assertions are valid for
300 *
301 * - signingKey
302 * Signing key when using assertion profile
303 *
304 * - signingKeyId
305 * Signing key id when using assertion profile
306 *
307 * - refreshToken
308 * The refresh token associated with the access token
309 * to be refreshed.
310 *
311 * - accessToken
312 * The current access token for this client.
313 *
314 * - idToken
315 * The current ID token for this client.
316 *
317 * - extensionParams
318 * When using an extension grant type, this is the set of parameters used
319 * by that extension.
320 *
321 * @param array $config Configuration array
322 */
323 public function __construct(array $config)
324 {
325 $opts = array_merge([
326 'expiry' => self::DEFAULT_EXPIRY_SECONDS,
327 'extensionParams' => [],
328 'authorizationUri' => null,
329 'redirectUri' => null,
330 'tokenCredentialUri' => null,
331 'state' => null,
332 'username' => null,
333 'password' => null,
334 'clientId' => null,
335 'clientSecret' => null,
336 'issuer' => null,
337 'sub' => null,
338 'audience' => null,
339 'signingKey' => null,
340 'signingKeyId' => null,
341 'signingAlgorithm' => null,
342 'scope' => null,
343 'additionalClaims' => [],
344 ], $config);
345
346 $this->setAuthorizationUri($opts['authorizationUri']);
347 $this->setRedirectUri($opts['redirectUri']);
348 $this->setTokenCredentialUri($opts['tokenCredentialUri']);
349 $this->setState($opts['state']);
350 $this->setUsername($opts['username']);
351 $this->setPassword($opts['password']);
352 $this->setClientId($opts['clientId']);
353 $this->setClientSecret($opts['clientSecret']);
354 $this->setIssuer($opts['issuer']);
355 $this->setSub($opts['sub']);
356 $this->setExpiry($opts['expiry']);
357 $this->setAudience($opts['audience']);
358 $this->setSigningKey($opts['signingKey']);
359 $this->setSigningKeyId($opts['signingKeyId']);
360 $this->setSigningAlgorithm($opts['signingAlgorithm']);
361 $this->setScope($opts['scope']);
362 $this->setExtensionParams($opts['extensionParams']);
363 $this->setAdditionalClaims($opts['additionalClaims']);
364 $this->updateToken($opts);
365 }
366
367 /**
368 * Verifies the idToken if present.
369 *
370 * - if none is present, return null
371 * - if present, but invalid, raises DomainException.
372 * - otherwise returns the payload in the idtoken as a PHP object.
373 *
374 * The behavior of this method varies depending on the version of
375 * `firebase/php-jwt` you are using. In versions lower than 3.0.0, if
376 * `$publicKey` is null, the key is decoded without being verified. In
377 * newer versions, if a public key is not given, this method will throw an
378 * `\InvalidArgumentException`.
379 *
380 * @param string $publicKey The public key to use to authenticate the token
381 * @param array $allowed_algs List of supported verification algorithms
382 * @throws \DomainException if the token is missing an audience.
383 * @throws \DomainException if the audience does not match the one set in
384 * the OAuth2 class instance.
385 * @throws \UnexpectedValueException If the token is invalid
386 * @throws SignatureInvalidException If the signature is invalid.
387 * @throws BeforeValidException If the token is not yet valid.
388 * @throws ExpiredException If the token has expired.
389 * @return null|object
390 */
391 public function verifyIdToken($publicKey = null, $allowed_algs = array())
392 {
393 $idToken = $this->getIdToken();
394 if (is_null($idToken)) {
395 return null;
396 }
397
398 $resp = $this->jwtDecode($idToken, $publicKey, $allowed_algs);
399 if (!property_exists($resp, 'aud')) {
400 throw new \DomainException('No audience found the id token');
401 }
402 if ($resp->aud != $this->getAudience()) {
403 throw new \DomainException('Wrong audience present in the id token');
404 }
405
406 return $resp;
407 }
408
409 /**
410 * Obtains the encoded jwt from the instance data.
411 *
412 * @param array $config array optional configuration parameters
413 * @return string
414 */
415 public function toJwt(array $config = [])
416 {
417 if (is_null($this->getSigningKey())) {
418 throw new \DomainException('No signing key available');
419 }
420 if (is_null($this->getSigningAlgorithm())) {
421 throw new \DomainException('No signing algorithm specified');
422 }
423 $now = time();
424
425 $opts = array_merge([
426 'skew' => self::DEFAULT_SKEW_SECONDS,
427 ], $config);
428
429 $assertion = [
430 'iss' => $this->getIssuer(),
431 'aud' => $this->getAudience(),
432 'exp' => ($now + $this->getExpiry()),
433 'iat' => ($now - $opts['skew']),
434 ];
435 foreach ($assertion as $k => $v) {
436 if (is_null($v)) {
437 throw new \DomainException($k . ' should not be null');
438 }
439 }
440 if (!(is_null($this->getScope()))) {
441 $assertion['scope'] = $this->getScope();
442 }
443 if (!(is_null($this->getSub()))) {
444 $assertion['sub'] = $this->getSub();
445 }
446 $assertion += $this->getAdditionalClaims();
447
448 return $this->jwtEncode(
449 $assertion,
450 $this->getSigningKey(),
451 $this->getSigningAlgorithm(),
452 $this->getSigningKeyId()
453 );
454 }
455
456 /**
457 * Generates a request for token credentials.
458 *
459 * @return RequestInterface the authorization Url.
460 */
461 public function generateCredentialsRequest()
462 {
463 $uri = $this->getTokenCredentialUri();
464 if (is_null($uri)) {
465 throw new \DomainException('No token credential URI was set.');
466 }
467
468 $grantType = $this->getGrantType();
469 $params = array('grant_type' => $grantType);
470 switch ($grantType) {
471 case 'authorization_code':
472 $params['code'] = $this->getCode();
473 $params['redirect_uri'] = $this->getRedirectUri();
474 $this->addClientCredentials($params);
475 break;
476 case 'password':
477 $params['username'] = $this->getUsername();
478 $params['password'] = $this->getPassword();
479 $this->addClientCredentials($params);
480 break;
481 case 'refresh_token':
482 $params['refresh_token'] = $this->getRefreshToken();
483 $this->addClientCredentials($params);
484 break;
485 case self::JWT_URN:
486 $params['assertion'] = $this->toJwt();
487 break;
488 default:
489 if (!is_null($this->getRedirectUri())) {
490 # Grant type was supposed to be 'authorization_code', as there
491 # is a redirect URI.
492 throw new \DomainException('Missing authorization code');
493 }
494 unset($params['grant_type']);
495 if (!is_null($grantType)) {
496 $params['grant_type'] = $grantType;
497 }
498 $params = array_merge($params, $this->getExtensionParams());
499 }
500
501 $headers = [
502 'Cache-Control' => 'no-store',
503 'Content-Type' => 'application/x-www-form-urlencoded',
504 ];
505
506 return new Request(
507 'POST',
508 $uri,
509 $headers,
510 Psr7\build_query($params)
511 );
512 }
513
514 /**
515 * Fetches the auth tokens based on the current state.
516 *
517 * @param callable $httpHandler callback which delivers psr7 request
518 * @return array the response
519 */
520 public function fetchAuthToken(callable $httpHandler = null)
521 {
522 if (is_null($httpHandler)) {
523 $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
524 }
525
526 $response = $httpHandler($this->generateCredentialsRequest());
527 $credentials = $this->parseTokenResponse($response);
528 $this->updateToken($credentials);
529
530 return $credentials;
531 }
532
533 /**
534 * Obtains a key that can used to cache the results of #fetchAuthToken.
535 *
536 * The key is derived from the scopes.
537 *
538 * @return string a key that may be used to cache the auth token.
539 */
540 public function getCacheKey()
541 {
542 if (is_array($this->scope)) {
543 return implode(':', $this->scope);
544 }
545
546 if ($this->audience) {
547 return $this->audience;
548 }
549
550 // If scope has not set, return null to indicate no caching.
551 return null;
552 }
553
554 /**
555 * Parses the fetched tokens.
556 *
557 * @param ResponseInterface $resp the response.
558 * @return array the tokens parsed from the response body.
559 * @throws \Exception
560 */
561 public function parseTokenResponse(ResponseInterface $resp)
562 {
563 $body = (string)$resp->getBody();
564 if ($resp->hasHeader('Content-Type') &&
565 $resp->getHeaderLine('Content-Type') == 'application/x-www-form-urlencoded'
566 ) {
567 $res = array();
568 parse_str($body, $res);
569
570 return $res;
571 }
572
573 // Assume it's JSON; if it's not throw an exception
574 if (null === $res = json_decode($body, true)) {
575 throw new \Exception('Invalid JSON response');
576 }
577
578 return $res;
579 }
580
581 /**
582 * Updates an OAuth 2.0 client.
583 *
584 * Example:
585 * ```
586 * $oauth->updateToken([
587 * 'refresh_token' => 'n4E9O119d',
588 * 'access_token' => 'FJQbwq9',
589 * 'expires_in' => 3600
590 * ]);
591 * ```
592 *
593 * @param array $config
594 * The configuration parameters related to the token.
595 *
596 * - refresh_token
597 * The refresh token associated with the access token
598 * to be refreshed.
599 *
600 * - access_token
601 * The current access token for this client.
602 *
603 * - id_token
604 * The current ID token for this client.
605 *
606 * - expires_in
607 * The time in seconds until access token expiration.
608 *
609 * - expires_at
610 * The time as an integer number of seconds since the Epoch
611 *
612 * - issued_at
613 * The timestamp that the token was issued at.
614 */
615 public function updateToken(array $config)
616 {
617 $opts = array_merge([
618 'extensionParams' => [],
619 'access_token' => null,
620 'id_token' => null,
621 'expires_in' => null,
622 'expires_at' => null,
623 'issued_at' => null,
624 ], $config);
625
626 $this->setExpiresAt($opts['expires_at']);
627 $this->setExpiresIn($opts['expires_in']);
628 // By default, the token is issued at `Time.now` when `expiresIn` is set,
629 // but this can be used to supply a more precise time.
630 if (!is_null($opts['issued_at'])) {
631 $this->setIssuedAt($opts['issued_at']);
632 }
633
634 $this->setAccessToken($opts['access_token']);
635 $this->setIdToken($opts['id_token']);
636 // The refresh token should only be updated if a value is explicitly
637 // passed in, as some access token responses do not include a refresh
638 // token.
639 if (array_key_exists('refresh_token', $opts)) {
640 $this->setRefreshToken($opts['refresh_token']);
641 }
642 }
643
644 /**
645 * Builds the authorization Uri that the user should be redirected to.
646 *
647 * @param array $config configuration options that customize the return url
648 * @return UriInterface the authorization Url.
649 * @throws InvalidArgumentException
650 */
651 public function buildFullAuthorizationUri(array $config = [])
652 {
653 if (is_null($this->getAuthorizationUri())) {
654 throw new InvalidArgumentException(
655 'requires an authorizationUri to have been set'
656 );
657 }
658
659 $params = array_merge([
660 'response_type' => 'code',
661 'access_type' => 'offline',
662 'client_id' => $this->clientId,
663 'redirect_uri' => $this->redirectUri,
664 'state' => $this->state,
665 'scope' => $this->getScope(),
666 ], $config);
667
668 // Validate the auth_params
669 if (is_null($params['client_id'])) {
670 throw new InvalidArgumentException(
671 'missing the required client identifier'
672 );
673 }
674 if (is_null($params['redirect_uri'])) {
675 throw new InvalidArgumentException('missing the required redirect URI');
676 }
677 if (!empty($params['prompt']) && !empty($params['approval_prompt'])) {
678 throw new InvalidArgumentException(
679 'prompt and approval_prompt are mutually exclusive'
680 );
681 }
682
683 // Construct the uri object; return it if it is valid.
684 $result = clone $this->authorizationUri;
685 $existingParams = Psr7\parse_query($result->getQuery());
686
687 $result = $result->withQuery(
688 Psr7\build_query(array_merge($existingParams, $params))
689 );
690
691 if ($result->getScheme() != 'https') {
692 throw new InvalidArgumentException(
693 'Authorization endpoint must be protected by TLS'
694 );
695 }
696
697 return $result;
698 }
699
700 /**
701 * Sets the authorization server's HTTP endpoint capable of authenticating
702 * the end-user and obtaining authorization.
703 *
704 * @param string $uri
705 */
706 public function setAuthorizationUri($uri)
707 {
708 $this->authorizationUri = $this->coerceUri($uri);
709 }
710
711 /**
712 * Gets the authorization server's HTTP endpoint capable of authenticating
713 * the end-user and obtaining authorization.
714 *
715 * @return UriInterface
716 */
717 public function getAuthorizationUri()
718 {
719 return $this->authorizationUri;
720 }
721
722 /**
723 * Gets the authorization server's HTTP endpoint capable of issuing tokens
724 * and refreshing expired tokens.
725 *
726 * @return string
727 */
728 public function getTokenCredentialUri()
729 {
730 return $this->tokenCredentialUri;
731 }
732
733 /**
734 * Sets the authorization server's HTTP endpoint capable of issuing tokens
735 * and refreshing expired tokens.
736 *
737 * @param string $uri
738 */
739 public function setTokenCredentialUri($uri)
740 {
741 $this->tokenCredentialUri = $this->coerceUri($uri);
742 }
743
744 /**
745 * Gets the redirection URI used in the initial request.
746 *
747 * @return string
748 */
749 public function getRedirectUri()
750 {
751 return $this->redirectUri;
752 }
753
754 /**
755 * Sets the redirection URI used in the initial request.
756 *
757 * @param string $uri
758 */
759 public function setRedirectUri($uri)
760 {
761 if (is_null($uri)) {
762 $this->redirectUri = null;
763
764 return;
765 }
766 // redirect URI must be absolute
767 if (!$this->isAbsoluteUri($uri)) {
768 // "postmessage" is a reserved URI string in Google-land
769 // @see https://developers.google.com/identity/sign-in/web/server-side-flow
770 if ('postmessage' !== (string)$uri) {
771 throw new InvalidArgumentException(
772 'Redirect URI must be absolute'
773 );
774 }
775 }
776 $this->redirectUri = (string)$uri;
777 }
778
779 /**
780 * Gets the scope of the access requests as a space-delimited String.
781 *
782 * @return string
783 */
784 public function getScope()
785 {
786 if (is_null($this->scope)) {
787 return $this->scope;
788 }
789
790 return implode(' ', $this->scope);
791 }
792
793 /**
794 * Sets the scope of the access request, expressed either as an Array or as
795 * a space-delimited String.
796 *
797 * @param string|array $scope
798 * @throws InvalidArgumentException
799 */
800 public function setScope($scope)
801 {
802 if (is_null($scope)) {
803 $this->scope = null;
804 } elseif (is_string($scope)) {
805 $this->scope = explode(' ', $scope);
806 } elseif (is_array($scope)) {
807 foreach ($scope as $s) {
808 $pos = strpos($s, ' ');
809 if ($pos !== false) {
810 throw new InvalidArgumentException(
811 'array scope values should not contain spaces'
812 );
813 }
814 }
815 $this->scope = $scope;
816 } else {
817 throw new InvalidArgumentException(
818 'scopes should be a string or array of strings'
819 );
820 }
821 }
822
823 /**
824 * Gets the current grant type.
825 *
826 * @return string
827 */
828 public function getGrantType()
829 {
830 if (!is_null($this->grantType)) {
831 return $this->grantType;
832 }
833
834 // Returns the inferred grant type, based on the current object instance
835 // state.
836 if (!is_null($this->code)) {
837 return 'authorization_code';
838 }
839
840 if (!is_null($this->refreshToken)) {
841 return 'refresh_token';
842 }
843
844 if (!is_null($this->username) && !is_null($this->password)) {
845 return 'password';
846 }
847
848 if (!is_null($this->issuer) && !is_null($this->signingKey)) {
849 return self::JWT_URN;
850 }
851
852 return null;
853 }
854
855 /**
856 * Sets the current grant type.
857 *
858 * @param $grantType
859 * @throws InvalidArgumentException
860 */
861 public function setGrantType($grantType)
862 {
863 if (in_array($grantType, self::$knownGrantTypes)) {
864 $this->grantType = $grantType;
865 } else {
866 // validate URI
867 if (!$this->isAbsoluteUri($grantType)) {
868 throw new InvalidArgumentException(
869 'invalid grant type'
870 );
871 }
872 $this->grantType = (string)$grantType;
873 }
874 }
875
876 /**
877 * Gets an arbitrary string designed to allow the client to maintain state.
878 *
879 * @return string
880 */
881 public function getState()
882 {
883 return $this->state;
884 }
885
886 /**
887 * Sets an arbitrary string designed to allow the client to maintain state.
888 *
889 * @param string $state
890 */
891 public function setState($state)
892 {
893 $this->state = $state;
894 }
895
896 /**
897 * Gets the authorization code issued to this client.
898 */
899 public function getCode()
900 {
901 return $this->code;
902 }
903
904 /**
905 * Sets the authorization code issued to this client.
906 *
907 * @param string $code
908 */
909 public function setCode($code)
910 {
911 $this->code = $code;
912 }
913
914 /**
915 * Gets the resource owner's username.
916 */
917 public function getUsername()
918 {
919 return $this->username;
920 }
921
922 /**
923 * Sets the resource owner's username.
924 *
925 * @param string $username
926 */
927 public function setUsername($username)
928 {
929 $this->username = $username;
930 }
931
932 /**
933 * Gets the resource owner's password.
934 */
935 public function getPassword()
936 {
937 return $this->password;
938 }
939
940 /**
941 * Sets the resource owner's password.
942 *
943 * @param $password
944 */
945 public function setPassword($password)
946 {
947 $this->password = $password;
948 }
949
950 /**
951 * Sets a unique identifier issued to the client to identify itself to the
952 * authorization server.
953 */
954 public function getClientId()
955 {
956 return $this->clientId;
957 }
958
959 /**
960 * Sets a unique identifier issued to the client to identify itself to the
961 * authorization server.
962 *
963 * @param $clientId
964 */
965 public function setClientId($clientId)
966 {
967 $this->clientId = $clientId;
968 }
969
970 /**
971 * Gets a shared symmetric secret issued by the authorization server, which
972 * is used to authenticate the client.
973 */
974 public function getClientSecret()
975 {
976 return $this->clientSecret;
977 }
978
979 /**
980 * Sets a shared symmetric secret issued by the authorization server, which
981 * is used to authenticate the client.
982 *
983 * @param $clientSecret
984 */
985 public function setClientSecret($clientSecret)
986 {
987 $this->clientSecret = $clientSecret;
988 }
989
990 /**
991 * Gets the Issuer ID when using assertion profile.
992 */
993 public function getIssuer()
994 {
995 return $this->issuer;
996 }
997
998 /**
999 * Sets the Issuer ID when using assertion profile.
1000 *
1001 * @param string $issuer
1002 */
1003 public function setIssuer($issuer)
1004 {
1005 $this->issuer = $issuer;
1006 }
1007
1008 /**
1009 * Gets the target sub when issuing assertions.
1010 */
1011 public function getSub()
1012 {
1013 return $this->sub;
1014 }
1015
1016 /**
1017 * Sets the target sub when issuing assertions.
1018 *
1019 * @param string $sub
1020 */
1021 public function setSub($sub)
1022 {
1023 $this->sub = $sub;
1024 }
1025
1026 /**
1027 * Gets the target audience when issuing assertions.
1028 */
1029 public function getAudience()
1030 {
1031 return $this->audience;
1032 }
1033
1034 /**
1035 * Sets the target audience when issuing assertions.
1036 *
1037 * @param string $audience
1038 */
1039 public function setAudience($audience)
1040 {
1041 $this->audience = $audience;
1042 }
1043
1044 /**
1045 * Gets the signing key when using an assertion profile.
1046 */
1047 public function getSigningKey()
1048 {
1049 return $this->signingKey;
1050 }
1051
1052 /**
1053 * Sets the signing key when using an assertion profile.
1054 *
1055 * @param string $signingKey
1056 */
1057 public function setSigningKey($signingKey)
1058 {
1059 $this->signingKey = $signingKey;
1060 }
1061
1062 /**
1063 * Gets the signing key id when using an assertion profile.
1064 *
1065 * @return string
1066 */
1067 public function getSigningKeyId()
1068 {
1069 return $this->signingKeyId;
1070 }
1071
1072 /**
1073 * Sets the signing key id when using an assertion profile.
1074 *
1075 * @param string $signingKeyId
1076 */
1077 public function setSigningKeyId($signingKeyId)
1078 {
1079 $this->signingKeyId = $signingKeyId;
1080 }
1081
1082 /**
1083 * Gets the signing algorithm when using an assertion profile.
1084 *
1085 * @return string
1086 */
1087 public function getSigningAlgorithm()
1088 {
1089 return $this->signingAlgorithm;
1090 }
1091
1092 /**
1093 * Sets the signing algorithm when using an assertion profile.
1094 *
1095 * @param string $signingAlgorithm
1096 */
1097 public function setSigningAlgorithm($signingAlgorithm)
1098 {
1099 if (is_null($signingAlgorithm)) {
1100 $this->signingAlgorithm = null;
1101 } elseif (!in_array($signingAlgorithm, self::$knownSigningAlgorithms)) {
1102 throw new InvalidArgumentException('unknown signing algorithm');
1103 } else {
1104 $this->signingAlgorithm = $signingAlgorithm;
1105 }
1106 }
1107
1108 /**
1109 * Gets the set of parameters used by extension when using an extension
1110 * grant type.
1111 */
1112 public function getExtensionParams()
1113 {
1114 return $this->extensionParams;
1115 }
1116
1117 /**
1118 * Sets the set of parameters used by extension when using an extension
1119 * grant type.
1120 *
1121 * @param $extensionParams
1122 */
1123 public function setExtensionParams($extensionParams)
1124 {
1125 $this->extensionParams = $extensionParams;
1126 }
1127
1128 /**
1129 * Gets the number of seconds assertions are valid for.
1130 */
1131 public function getExpiry()
1132 {
1133 return $this->expiry;
1134 }
1135
1136 /**
1137 * Sets the number of seconds assertions are valid for.
1138 *
1139 * @param int $expiry
1140 */
1141 public function setExpiry($expiry)
1142 {
1143 $this->expiry = $expiry;
1144 }
1145
1146 /**
1147 * Gets the lifetime of the access token in seconds.
1148 */
1149 public function getExpiresIn()
1150 {
1151 return $this->expiresIn;
1152 }
1153
1154 /**
1155 * Sets the lifetime of the access token in seconds.
1156 *
1157 * @param int $expiresIn
1158 */
1159 public function setExpiresIn($expiresIn)
1160 {
1161 if (is_null($expiresIn)) {
1162 $this->expiresIn = null;
1163 $this->issuedAt = null;
1164 } else {
1165 $this->issuedAt = time();
1166 $this->expiresIn = (int)$expiresIn;
1167 }
1168 }
1169
1170 /**
1171 * Gets the time the current access token expires at.
1172 *
1173 * @return int
1174 */
1175 public function getExpiresAt()
1176 {
1177 if (!is_null($this->expiresAt)) {
1178 return $this->expiresAt;
1179 }
1180
1181 if (!is_null($this->issuedAt) && !is_null($this->expiresIn)) {
1182 return $this->issuedAt + $this->expiresIn;
1183 }
1184
1185 return null;
1186 }
1187
1188 /**
1189 * Returns true if the acccess token has expired.
1190 *
1191 * @return bool
1192 */
1193 public function isExpired()
1194 {
1195 $expiration = $this->getExpiresAt();
1196 $now = time();
1197
1198 return !is_null($expiration) && $now >= $expiration;
1199 }
1200
1201 /**
1202 * Sets the time the current access token expires at.
1203 *
1204 * @param int $expiresAt
1205 */
1206 public function setExpiresAt($expiresAt)
1207 {
1208 $this->expiresAt = $expiresAt;
1209 }
1210
1211 /**
1212 * Gets the time the current access token was issued at.
1213 */
1214 public function getIssuedAt()
1215 {
1216 return $this->issuedAt;
1217 }
1218
1219 /**
1220 * Sets the time the current access token was issued at.
1221 *
1222 * @param int $issuedAt
1223 */
1224 public function setIssuedAt($issuedAt)
1225 {
1226 $this->issuedAt = $issuedAt;
1227 }
1228
1229 /**
1230 * Gets the current access token.
1231 */
1232 public function getAccessToken()
1233 {
1234 return $this->accessToken;
1235 }
1236
1237 /**
1238 * Sets the current access token.
1239 *
1240 * @param string $accessToken
1241 */
1242 public function setAccessToken($accessToken)
1243 {
1244 $this->accessToken = $accessToken;
1245 }
1246
1247 /**
1248 * Gets the current ID token.
1249 */
1250 public function getIdToken()
1251 {
1252 return $this->idToken;
1253 }
1254
1255 /**
1256 * Sets the current ID token.
1257 *
1258 * @param $idToken
1259 */
1260 public function setIdToken($idToken)
1261 {
1262 $this->idToken = $idToken;
1263 }
1264
1265 /**
1266 * Gets the refresh token associated with the current access token.
1267 */
1268 public function getRefreshToken()
1269 {
1270 return $this->refreshToken;
1271 }
1272
1273 /**
1274 * Sets the refresh token associated with the current access token.
1275 *
1276 * @param $refreshToken
1277 */
1278 public function setRefreshToken($refreshToken)
1279 {
1280 $this->refreshToken = $refreshToken;
1281 }
1282
1283 /**
1284 * Sets additional claims to be included in the JWT token
1285 *
1286 * @param array $additionalClaims
1287 */
1288 public function setAdditionalClaims(array $additionalClaims)
1289 {
1290 $this->additionalClaims = $additionalClaims;
1291 }
1292
1293 /**
1294 * Gets the additional claims to be included in the JWT token.
1295 *
1296 * @return array
1297 */
1298 public function getAdditionalClaims()
1299 {
1300 return $this->additionalClaims;
1301 }
1302
1303 /**
1304 * The expiration of the last received token.
1305 *
1306 * @return array
1307 */
1308 public function getLastReceivedToken()
1309 {
1310 if ($token = $this->getAccessToken()) {
1311 return [
1312 'access_token' => $token,
1313 'expires_at' => $this->getExpiresAt(),
1314 ];
1315 }
1316
1317 return null;
1318 }
1319
1320 /**
1321 * Get the client ID.
1322 *
1323 * Alias of {@see Google\Auth\OAuth2::getClientId()}.
1324 *
1325 * @param callable $httpHandler
1326 * @return string
1327 * @access private
1328 */
1329 public function getClientName(callable $httpHandler = null)
1330 {
1331 return $this->getClientId();
1332 }
1333
1334 /**
1335 * @todo handle uri as array
1336 *
1337 * @param string $uri
1338 * @return null|UriInterface
1339 */
1340 private function coerceUri($uri)
1341 {
1342 if (is_null($uri)) {
1343 return;
1344 }
1345
1346 return Psr7\uri_for($uri);
1347 }
1348
1349 /**
1350 * @param string $idToken
1351 * @param string|array|null $publicKey
1352 * @param array $allowedAlgs
1353 * @return object
1354 */
1355 private function jwtDecode($idToken, $publicKey, $allowedAlgs)
1356 {
1357 if (class_exists('Firebase\JWT\JWT')) {
1358 return \Firebase\JWT\JWT::decode($idToken, $publicKey, $allowedAlgs);
1359 }
1360
1361 return \JWT::decode($idToken, $publicKey, $allowedAlgs);
1362 }
1363
1364 private function jwtEncode($assertion, $signingKey, $signingAlgorithm, $signingKeyId = null)
1365 {
1366 if (class_exists('Firebase\JWT\JWT')) {
1367 return \Firebase\JWT\JWT::encode(
1368 $assertion,
1369 $signingKey,
1370 $signingAlgorithm,
1371 $signingKeyId
1372 );
1373 }
1374
1375 return \JWT::encode($assertion, $signingKey, $signingAlgorithm, $signingKeyId);
1376 }
1377
1378 /**
1379 * Determines if the URI is absolute based on its scheme and host or path
1380 * (RFC 3986).
1381 *
1382 * @param string $uri
1383 * @return bool
1384 */
1385 private function isAbsoluteUri($uri)
1386 {
1387 $uri = $this->coerceUri($uri);
1388
1389 return $uri->getScheme() && ($uri->getHost() || $uri->getPath());
1390 }
1391
1392 /**
1393 * @param array $params
1394 * @return array
1395 */
1396 private function addClientCredentials(&$params)
1397 {
1398 $clientId = $this->getClientId();
1399 $clientSecret = $this->getClientSecret();
1400
1401 if ($clientId && $clientSecret) {
1402 $params['client_id'] = $clientId;
1403 $params['client_secret'] = $clientSecret;
1404 }
1405
1406 return $params;
1407 }
1408 }
1409