*/ 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 $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 $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()); } }