[Web] add league/oauth2-client

This commit is contained in:
FreddleSpl0it
2023-05-16 13:21:17 +02:00
parent 07edec4ea5
commit 34e7b3f613
10 changed files with 143 additions and 30 deletions

View File

@@ -6,7 +6,7 @@ This package provides a base for integrating with [OAuth 2.0](http://oauth.net/2
[![Source Code](https://img.shields.io/badge/source-thephpleague/oauth2--client-blue.svg?style=flat-square)](https://github.com/thephpleague/oauth2-client)
[![Latest Version](https://img.shields.io/github/release/thephpleague/oauth2-client.svg?style=flat-square)](https://github.com/thephpleague/oauth2-client/releases)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://github.com/thephpleague/oauth2-client/blob/master/LICENSE)
[![Build Status](https://img.shields.io/github/workflow/status/thephpleague/oauth2-client/CI?label=CI&logo=github&style=flat-square)](https://github.com/thephpleague/oauth2-client/actions?query=workflow%3ACI)
[![Build Status](https://img.shields.io/github/actions/workflow/status/thephpleague/oauth2-client/continuous-integration.yml?label=CI&logo=github&style=flat-square)](https://github.com/thephpleague/oauth2-client/actions?query=workflow%3ACI)
[![Codecov Code Coverage](https://img.shields.io/codecov/c/gh/thephpleague/oauth2-client?label=codecov&logo=codecov&style=flat-square)](https://codecov.io/gh/thephpleague/oauth2-client)
[![Total Downloads](https://img.shields.io/packagist/dt/league/oauth2-client.svg?style=flat-square)](https://packagist.org/packages/league/oauth2-client)

View File

@@ -17,6 +17,7 @@ namespace League\OAuth2\Client\Provider;
use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\ClientInterface as HttpClientInterface;
use GuzzleHttp\Exception\BadResponseException;
use InvalidArgumentException;
use League\OAuth2\Client\Grant\AbstractGrant;
use League\OAuth2\Client\Grant\GrantFactory;
use League\OAuth2\Client\OptionProvider\OptionProviderInterface;
@@ -44,7 +45,7 @@ abstract class AbstractProvider
use QueryBuilderTrait;
/**
* @var string Key used in a token response to identify the resource owner.
* @var string|null Key used in a token response to identify the resource owner.
*/
const ACCESS_TOKEN_RESOURCE_OWNER_ID = null;
@@ -58,6 +59,19 @@ abstract class AbstractProvider
*/
const METHOD_POST = 'POST';
/**
* @var string PKCE method used to fetch authorization token.
* The PKCE code challenge will be hashed with sha256 (recommended).
*/
const PKCE_METHOD_S256 = 'S256';
/**
* @var string PKCE method used to fetch authorization token.
* The PKCE code challenge will be sent as plain text, this is NOT recommended.
* Only use `plain` if no other option is possible.
*/
const PKCE_METHOD_PLAIN = 'plain';
/**
* @var string
*/
@@ -78,6 +92,11 @@ abstract class AbstractProvider
*/
protected $state;
/**
* @var string|null
*/
protected $pkceCode = null;
/**
* @var GrantFactory
*/
@@ -264,6 +283,32 @@ abstract class AbstractProvider
return $this->state;
}
/**
* Set the value of the pkceCode parameter.
*
* When using PKCE this should be set before requesting an access token.
*
* @param string $pkceCode
* @return self
*/
public function setPkceCode($pkceCode)
{
$this->pkceCode = $pkceCode;
return $this;
}
/**
* Returns the current value of the pkceCode parameter.
*
* This can be accessed by the redirect handler during authorization.
*
* @return string|null
*/
public function getPkceCode()
{
return $this->pkceCode;
}
/**
* Returns the base URL for authorizing a client.
*
@@ -305,6 +350,27 @@ abstract class AbstractProvider
return bin2hex(random_bytes($length / 2));
}
/**
* Returns a new random string to use as PKCE code_verifier and
* hashed as code_challenge parameters in an authorization flow.
* Must be between 43 and 128 characters long.
*
* @param int $length Length of the random string to be generated.
* @return string
*/
protected function getRandomPkceCode($length = 64)
{
return substr(
strtr(
base64_encode(random_bytes($length)),
'+/',
'-_'
),
0,
$length
);
}
/**
* Returns the default scopes used by this provider.
*
@@ -326,6 +392,14 @@ abstract class AbstractProvider
return ',';
}
/**
* @return string|null
*/
protected function getPkceMethod()
{
return null;
}
/**
* Returns authorization parameters based on provided options.
*
@@ -355,6 +429,26 @@ abstract class AbstractProvider
// Store the state as it may need to be accessed later on.
$this->state = $options['state'];
$pkceMethod = $this->getPkceMethod();
if (!empty($pkceMethod)) {
$this->pkceCode = $this->getRandomPkceCode();
if ($pkceMethod === static::PKCE_METHOD_S256) {
$options['code_challenge'] = trim(
strtr(
base64_encode(hash('sha256', $this->pkceCode, true)),
'+/',
'-_'
),
'='
);
} elseif ($pkceMethod === static::PKCE_METHOD_PLAIN) {
$options['code_challenge'] = $this->pkceCode;
} else {
throw new InvalidArgumentException('Unknown PKCE method "' . $pkceMethod . '".');
}
$options['code_challenge_method'] = $pkceMethod;
}
// Business code layer might set a different redirect_uri parameter
// depending on the context, leave it as-is
if (!isset($options['redirect_uri'])) {
@@ -517,8 +611,8 @@ abstract class AbstractProvider
/**
* Requests an access token using a specified grant and option set.
*
* @param mixed $grant
* @param array $options
* @param mixed $grant
* @param array<string, mixed> $options
* @throws IdentityProviderException
* @return AccessTokenInterface
*/
@@ -532,6 +626,10 @@ abstract class AbstractProvider
'redirect_uri' => $this->redirectUri,
];
if (!empty($this->pkceCode)) {
$params['code_verifier'] = $this->pkceCode;
}
$params = $grant->prepareRequestParameters($params, $options);
$request = $this->getAccessTokenRequest($params);
$response = $this->getParsedResponse($request);
@@ -564,7 +662,7 @@ abstract class AbstractProvider
*
* @param string $method
* @param string $url
* @param AccessTokenInterface|string $token
* @param AccessTokenInterface|string|null $token
* @param array $options Any of "headers", "body", and "protocolVersion".
* @return RequestInterface
*/

View File

@@ -27,7 +27,7 @@ class IdentityProviderException extends \Exception
/**
* @param string $message
* @param int $code
* @param array|string $response The response body
* @param mixed $response The response body
*/
public function __construct($message, $code, $response)
{
@@ -39,7 +39,7 @@ class IdentityProviderException extends \Exception
/**
* Returns the exception's response body.
*
* @return array|string
* @return mixed
*/
public function getResponseBody()
{

View File

@@ -78,6 +78,11 @@ class GenericProvider extends AbstractProvider
*/
private $responseResourceOwnerId = 'id';
/**
* @var string|null
*/
private $pkceMethod = null;
/**
* @param array $options
* @param array $collaborators
@@ -114,6 +119,7 @@ class GenericProvider extends AbstractProvider
'responseCode',
'responseResourceOwnerId',
'scopes',
'pkceMethod',
]);
}
@@ -205,6 +211,14 @@ class GenericProvider extends AbstractProvider
return $this->scopeSeparator ?: parent::getScopeSeparator();
}
/**
* @inheritdoc
*/
protected function getPkceMethod()
{
return $this->pkceMethod ?: parent::getPkceMethod();
}
/**
* @inheritdoc
*/