|
@ -1,52 +1,55 @@ |
|
|
<?php |
|
|
<?php |
|
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1); |
|
|
|
|
|
|
|
|
namespace authkit2\Oidc; |
|
|
namespace authkit2\Oidc; |
|
|
|
|
|
|
|
|
use authkit2\Authkit2; |
|
|
use authkit2\Authkit2; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* OpenId Connect HTTP Client Library |
|
|
* OpenId Connect HTTP Client Library. |
|
|
*/ |
|
|
*/ |
|
|
class Client |
|
|
class Client |
|
|
{ |
|
|
{ |
|
|
/** |
|
|
/** |
|
|
* Authenticator used to authenticate requests we're making |
|
|
* Authenticator used to authenticate requests we're making. |
|
|
* @var Authentication\Authentication |
|
|
* @var Authentication\Authentication |
|
|
*/ |
|
|
*/ |
|
|
protected $auth; |
|
|
protected $auth; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Http client we've initialized with our authentication middleware in |
|
|
* Http client we've initialized with our authentication middleware in |
|
|
* place |
|
|
* place. |
|
|
* @var \GuzzleHttp\Client |
|
|
* @var \GuzzleHttp\Client |
|
|
*/ |
|
|
*/ |
|
|
protected $client; |
|
|
protected $client; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* OAuth client id |
|
|
* OAuth client id. |
|
|
* @var string |
|
|
* @var string |
|
|
*/ |
|
|
*/ |
|
|
protected $client_id; |
|
|
protected $client_id; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Base url of the OIDC realm |
|
|
* Base url of the OIDC realm. |
|
|
* @var string |
|
|
* @var string |
|
|
*/ |
|
|
*/ |
|
|
protected $oidc_url; |
|
|
protected $oidc_url; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* OIDC config fetched from the server or restored from cache |
|
|
* OIDC config fetched from the server or restored from cache. |
|
|
* @var ?array<string,mixed> |
|
|
* @var ?array<string,mixed> |
|
|
*/ |
|
|
*/ |
|
|
protected $oidc_config; |
|
|
protected $oidc_config; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Keys for validating signed JWT tokens |
|
|
* Keys for validating signed JWT tokens. |
|
|
* @var array<string,mixed> |
|
|
* @var array<string,mixed> |
|
|
*/ |
|
|
*/ |
|
|
protected $oidc_jwks; |
|
|
protected $oidc_jwks; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Create a new OIDC client using the passed in client credentials |
|
|
* Create a new OIDC client using the passed in client credentials. |
|
|
* |
|
|
* |
|
|
* @param string $url |
|
|
* @param string $url |
|
|
* @param string $client_id |
|
|
* @param string $client_id |
|
@ -62,7 +65,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Retrieve a HTTP client containing our authentication middleware |
|
|
* Retrieve a HTTP client containing our authentication middleware. |
|
|
* |
|
|
* |
|
|
* @return \GuzzleHttp\Client |
|
|
* @return \GuzzleHttp\Client |
|
|
*/ |
|
|
*/ |
|
@ -72,7 +75,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Retrieve the configured OpenId Connect realm url; null if never set |
|
|
* Retrieve the configured OpenId Connect realm url; null if never set. |
|
|
* |
|
|
* |
|
|
* @return ?string |
|
|
* @return ?string |
|
|
*/ |
|
|
*/ |
|
@ -82,7 +85,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Get the OpenId Connect configuration |
|
|
* Get the OpenId Connect configuration. |
|
|
* |
|
|
* |
|
|
* @return array<string,string|array|bool> |
|
|
* @return array<string,string|array|bool> |
|
|
*/ |
|
|
*/ |
|
@ -95,18 +98,17 @@ class Client |
|
|
/** |
|
|
/** |
|
|
* @return array<string,string|array|bool> |
|
|
* @return array<string,string|array|bool> |
|
|
*/ |
|
|
*/ |
|
|
function() use ($url) { |
|
|
static function() use ($url) { |
|
|
$response = (new \GuzzleHttp\Client())->get($url.'/.well-known/openid-configuration'); |
|
|
$response = (new \GuzzleHttp\Client())->get($url.'/.well-known/openid-configuration'); |
|
|
return json_decode($response->getBody(), true); |
|
|
return json_decode((string)$response->getBody(), true); |
|
|
} |
|
|
} |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
return $this->oidc_config; |
|
|
return $this->oidc_config; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Get the web key set for verifying JWTs |
|
|
* Get the web key set for verifying JWTs. |
|
|
* |
|
|
* |
|
|
* @return array<string,array> |
|
|
* @return array<string,array> |
|
|
*/ |
|
|
*/ |
|
@ -119,7 +121,7 @@ class Client |
|
|
/** |
|
|
/** |
|
|
* @return array<string,array> |
|
|
* @return array<string,array> |
|
|
*/ |
|
|
*/ |
|
|
function() use ($client) { |
|
|
static function() use ($client) { |
|
|
$response = $client->get($client->getConfiguration()['jwks_uri']); |
|
|
$response = $client->get($client->getConfiguration()['jwks_uri']); |
|
|
return json_decode(json_encode($response), true); |
|
|
return json_decode(json_encode($response), true); |
|
|
} |
|
|
} |
|
@ -129,7 +131,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Get the signing algorithms for signing JWTs |
|
|
* Get the signing algorithms for signing JWTs. |
|
|
* |
|
|
* |
|
|
* @return string[] |
|
|
* @return string[] |
|
|
*/ |
|
|
*/ |
|
@ -139,7 +141,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Fetch a specific OpenId Connect endpoint from the configuration |
|
|
* Fetch a specific OpenId Connect endpoint from the configuration. |
|
|
* |
|
|
* |
|
|
* @param string $endpoint_name |
|
|
* @param string $endpoint_name |
|
|
* @return string |
|
|
* @return string |
|
@ -150,7 +152,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Make a HTTP get request to a OIDC endpoint or other URL |
|
|
* Make a HTTP get request to a OIDC endpoint or other URL. |
|
|
* |
|
|
* |
|
|
* @param string $url |
|
|
* @param string $url |
|
|
* @param array<string,scalar> $params query string parameters |
|
|
* @param array<string,scalar> $params query string parameters |
|
@ -161,11 +163,11 @@ class Client |
|
|
$response = $this->getClient()->get($url, [ |
|
|
$response = $this->getClient()->get($url, [ |
|
|
'query' => $params |
|
|
'query' => $params |
|
|
]); |
|
|
]); |
|
|
return json_decode($response->getBody()); |
|
|
return json_decode((string)$response->getBody()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Make a HTTP post request to a OIDC endpoint or other URL |
|
|
* Make a HTTP post request to a OIDC endpoint or other URL. |
|
|
* |
|
|
* |
|
|
* If form parameters are provided the request is sent as |
|
|
* If form parameters are provided the request is sent as |
|
|
* application/x-www-form-urlencoded |
|
|
* application/x-www-form-urlencoded |
|
@ -179,11 +181,11 @@ class Client |
|
|
$response = $this->getClient()->post($url, [ |
|
|
$response = $this->getClient()->post($url, [ |
|
|
'form_params' => $params |
|
|
'form_params' => $params |
|
|
]); |
|
|
]); |
|
|
return json_decode($response->getBody()); |
|
|
return json_decode((string)$response->getBody()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Create a 'service account' token tied to this client's id |
|
|
* Create a 'service account' token tied to this client's id. |
|
|
* |
|
|
* |
|
|
* @return Token |
|
|
* @return Token |
|
|
*/ |
|
|
*/ |
|
@ -197,7 +199,7 @@ class Client |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Convert a returned authorization code from the three legged flow |
|
|
* Convert a returned authorization code from the three legged flow |
|
|
* into a token |
|
|
* into a token. |
|
|
* |
|
|
* |
|
|
* @param string $code |
|
|
* @param string $code |
|
|
* @param string $redirect_uri |
|
|
* @param string $redirect_uri |
|
@ -215,7 +217,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Create a new access token from a refresh token |
|
|
* Create a new access token from a refresh token. |
|
|
* |
|
|
* |
|
|
* @param string $refresh_token |
|
|
* @param string $refresh_token |
|
|
* @return Token |
|
|
* @return Token |
|
@ -231,7 +233,7 @@ class Client |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Generate the URL to redirect to in order to initiate the three-legged |
|
|
* Generate the URL to redirect to in order to initiate the three-legged |
|
|
* oauth flow |
|
|
* oauth flow. |
|
|
* |
|
|
* |
|
|
* @param string $redirect_uri url to redirect the user to after authentication |
|
|
* @param string $redirect_uri url to redirect the user to after authentication |
|
|
* @param string[] $scopes scopes to request from the openid provider |
|
|
* @param string[] $scopes scopes to request from the openid provider |
|
@ -251,7 +253,7 @@ class Client |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Generate the URL to redirect to in order to initiate a signout from the |
|
|
* Generate the URL to redirect to in order to initiate a signout from the |
|
|
* OIDC provider |
|
|
* OIDC provider. |
|
|
* |
|
|
* |
|
|
* @param string $redirect_uri url to redirect the user to after logout |
|
|
* @param string $redirect_uri url to redirect the user to after logout |
|
|
* @return string fully formed url |
|
|
* @return string fully formed url |
|
@ -264,7 +266,7 @@ class Client |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Refresh a token using a refresh token |
|
|
* Refresh a token using a refresh token. |
|
|
* |
|
|
* |
|
|
* @param Token $token expired token that includes a refresh token |
|
|
* @param Token $token expired token that includes a refresh token |
|
|
* @return Token newly generated token |
|
|
* @return Token newly generated token |
|
@ -273,21 +275,22 @@ class Client |
|
|
{ |
|
|
{ |
|
|
$refresh_token = $token->getRefreshToken(); |
|
|
$refresh_token = $token->getRefreshToken(); |
|
|
if (!isset($refresh_token)) |
|
|
if (!isset($refresh_token)) |
|
|
throw new \Exception("Cannot refresh token initialized without refresh token"); |
|
|
{ |
|
|
|
|
|
throw new \Exception('Cannot refresh token initialized without refresh token'); |
|
|
|
|
|
} |
|
|
return $this->createTokenFromRefreshToken($refresh_token); |
|
|
return $this->createTokenFromRefreshToken($refresh_token); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Fetch the available information on the user from the OIDC provider |
|
|
* Fetch the available information on the user from the OIDC provider. |
|
|
* |
|
|
* |
|
|
* @param Token $token token representing the user |
|
|
* @param Token $token token representing the user |
|
|
* @return array<string,mixed> |
|
|
* @return array<string,mixed> |
|
|
*/ |
|
|
*/ |
|
|
public function getTokenUserInfo(Token $token): array |
|
|
public function getTokenUserInfo(Token $token): array |
|
|
{ |
|
|
{ |
|
|
return json_decode($token->getClient()->get($this->getEndpointUrl('userinfo'))->getBody(), true); |
|
|
return json_decode((string)$token->getClient()->get($this->getEndpointUrl('userinfo'))->getBody(), true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// todo: introspect, etc |
|
|
// todo: introspect, etc |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|