You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
4.4 KiB
187 lines
4.4 KiB
<?php
|
|
|
|
namespace authkit2\Oidc;
|
|
use authkit2\Authkit2;
|
|
|
|
/**
|
|
* OpenId Connect HTTP Client Library
|
|
*/
|
|
class Client
|
|
{
|
|
/**
|
|
* Authenticator used to authenticate requests we're making
|
|
* @var Authentication\Authentication
|
|
*/
|
|
protected $auth;
|
|
|
|
/**
|
|
* Http client we've initialized with our authentication middleware in
|
|
* place
|
|
* @var \GuzzleHttp\Client
|
|
*/
|
|
protected $client;
|
|
|
|
/**
|
|
* Base url of the OIDC realm
|
|
* @var string
|
|
*/
|
|
static $oidc_url;
|
|
|
|
/**
|
|
* OIDC config fetched from the server or restored from cache
|
|
* @var array<string,mixed>
|
|
*/
|
|
static $oidc_config;
|
|
|
|
/**
|
|
* Create a new OIDC client using the passed authentication provider
|
|
*
|
|
* @param Authentication\Authentication $auth
|
|
*/
|
|
public function __construct(Authentication\Authentication $auth)
|
|
{
|
|
$this->auth = $auth;
|
|
}
|
|
|
|
/**
|
|
* Retrieve a HTTP client containing our authentication middleware
|
|
*
|
|
* Constructed on first use
|
|
*
|
|
* @return \GuzzleHttp\Client
|
|
*/
|
|
public function getClient(): \GuzzleHttp\Client
|
|
{
|
|
if (!isset($this->client))
|
|
{
|
|
$stack = new \GuzzleHttp\HandlerStack();
|
|
$stack->setHandler(new \GuzzleHttp\Handler\CurlHandler());
|
|
$stack->push($this->auth->getMiddleware());
|
|
$this->client = new \GuzzleHttp\Client(['handler' => $stack]);
|
|
}
|
|
return $this->client;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the configured OpenId Connect realm url; null if never set
|
|
*
|
|
* @return ?string
|
|
*/
|
|
public static function getUrl(): ?string
|
|
{
|
|
return static::$oidc_url;
|
|
}
|
|
|
|
/**
|
|
* Configure the library with a OpenId Connect realm url
|
|
*
|
|
* @param string $url
|
|
* @return void
|
|
*/
|
|
public static function setUrl(string $url): void
|
|
{
|
|
static::$oidc_url = $url;
|
|
}
|
|
|
|
/**
|
|
* Set the OpenId Connect configuration
|
|
*
|
|
* This is provided to allow external caching rather than having us refetch
|
|
* the configuration on every invocation of the project.
|
|
*
|
|
* @param array $config config as retrieved from getOidcConfig()
|
|
* @return void
|
|
*/
|
|
public static function setOidcConfig(array $config): void
|
|
{
|
|
static::$oidc_config = $config;
|
|
}
|
|
|
|
/**
|
|
* Get the OpenId Connect configuration
|
|
*
|
|
* If not restored/set via setOidcConfig, this will be fetched from the OIDC
|
|
* realm on first use
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getOidcConfig(): array
|
|
{
|
|
if (!isset(static::$oidc_config))
|
|
{
|
|
static::$oidc_config = Authkit2::cache('oidc.config', function() {
|
|
$response = (new \GuzzleHttp\Client())->get(static::$oidc_url.'/.well-known/openid-configuration');
|
|
return json_decode($response->getBody(), true);
|
|
});
|
|
|
|
}
|
|
return static::$oidc_config;
|
|
}
|
|
|
|
/**
|
|
* Fetch a specific OpenId Connect endpoint from the configuration
|
|
*
|
|
* @param string $endpoint_name
|
|
* @return string
|
|
*/
|
|
public function getEndpointUrl(string $endpoint_name): string
|
|
{
|
|
return static::getOidcConfig()[$endpoint_name.'_endpoint'];
|
|
}
|
|
|
|
/**
|
|
* Determine the final URL to make a request to given an arbitrarily-defined
|
|
* 'endpoint'.
|
|
*
|
|
* If the passed in value is a valid URI, it will be used directly. Otherwise,
|
|
* we will attempt to find a configured endpoint with a name matching the
|
|
* passed in value in the OIDC config.
|
|
*
|
|
* @param string $endpoint url or endpoint name
|
|
* @return string url to call
|
|
*/
|
|
protected function parseEndpoint(string $endpoint): string
|
|
{
|
|
if (filter_var($endpoint, \FILTER_VALIDATE_URL))
|
|
{
|
|
return $endpoint;
|
|
}
|
|
else
|
|
{
|
|
return $this->getEndpointUrl($endpoint);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make a HTTP get request to a OIDC endpoint or other URL
|
|
*
|
|
* @param string $endpoint url or endpoint name
|
|
* @param array<string,scalar> $params query string parameters
|
|
* @return object json decoded response
|
|
*/
|
|
public function get(string $endpoint, array $params = []): object
|
|
{
|
|
$response = $this->getClient()->get($this->parseEndpoint($endpoint), [
|
|
'query' => $params
|
|
]);
|
|
return json_decode($response->getBody());
|
|
}
|
|
|
|
/**
|
|
* Make a HTTP post request to a OIDC endpoint or other URL
|
|
*
|
|
* If form parameters are provided the request is sent as
|
|
* application/x-www-form-urlencoded
|
|
*
|
|
* @param string $endpoint url or endpoint name
|
|
* @param array<string,scalar> $params form fields
|
|
* @return object json decoded response
|
|
*/
|
|
public function post(string $endpoint, array $params = []): object
|
|
{
|
|
$response = $this->getClient()->post($this->parseEndpoint($endpoint), [
|
|
'form_params' => $params
|
|
]);
|
|
return json_decode($response->getBody());
|
|
}
|
|
}
|
|
|