BxCidaasConProvider.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup CidaasConnect Cidaas Connect
  7. * @ingroup UnaModules
  8. *
  9. * @{
  10. */
  11. use Cidaas\OAuth2\Client\Provider\Cidaas;
  12. use Cidaas\OAuth2\Client\Provider\GrantType;
  13. use GuzzleHttp\HandlerStack;
  14. use GuzzleHttp\Promise\PromiseInterface;
  15. use Psr\Http\Message\ResponseInterface;
  16. /**
  17. * Cidaas SDK wrapper that allows PKCE without a client secret.
  18. * The upstream constructor and token request always require client_secret.
  19. */
  20. class BxCidaasConProvider extends Cidaas
  21. {
  22. protected $sBaseUrl;
  23. protected $sClientId;
  24. protected $sClientSecret;
  25. protected $sRedirectUri;
  26. protected $bDebug;
  27. public function __construct(string $baseUrl, string $clientId, string $clientSecret, string $redirectUri, ?HandlerStack $handler = null, bool $debug = false)
  28. {
  29. $this->sBaseUrl = rtrim($baseUrl, '/');
  30. $this->sClientId = $clientId;
  31. $this->sClientSecret = $clientSecret;
  32. $this->sRedirectUri = $redirectUri;
  33. $this->bDebug = $debug;
  34. // Upstream validate() rejects an empty secret; pass a placeholder then clear it.
  35. parent::__construct($baseUrl, $clientId, $clientSecret !== '' ? $clientSecret : '.', $redirectUri, $handler, $debug);
  36. if ($clientSecret === '') {
  37. $oProp = new ReflectionProperty(Cidaas::class, 'clientSecret');
  38. $oProp->setValue($this, '');
  39. }
  40. }
  41. public function getAccessToken(string $grantType, string $code = '', string $refreshToken = '', bool $pkceEnabled = false): PromiseInterface
  42. {
  43. if ($grantType === GrantType::AuthorizationCode) {
  44. if (empty($code))
  45. throw new InvalidArgumentException('code must not be empty in authorization_code flow');
  46. $aParams = [
  47. 'client_id' => $this->sClientId,
  48. 'redirect_uri' => $this->sRedirectUri,
  49. 'grant_type' => 'authorization_code',
  50. 'code' => $code,
  51. ];
  52. if ($this->sClientSecret !== '')
  53. $aParams['client_secret'] = $this->sClientSecret;
  54. if ($pkceEnabled)
  55. $aParams['code_verifier'] = $_SESSION['code-verifier'] ?? '';
  56. }
  57. else if ($grantType === GrantType::RefreshToken) {
  58. if (empty($refreshToken))
  59. throw new InvalidArgumentException('refreshToken must not be empty in refresh_token flow');
  60. $aParams = [
  61. 'client_id' => $this->sClientId,
  62. 'grant_type' => 'refresh_token',
  63. 'refresh_token' => $refreshToken,
  64. ];
  65. if ($this->sClientSecret !== '')
  66. $aParams['client_secret'] = $this->sClientSecret;
  67. }
  68. else if ($grantType === GrantType::ClientCredentials) {
  69. if ($this->sClientSecret === '')
  70. throw new InvalidArgumentException('client secret is required for client_credentials flow');
  71. $aParams = [
  72. 'client_id' => $this->sClientId,
  73. 'client_secret' => $this->sClientSecret,
  74. 'grant_type' => 'client_credentials',
  75. ];
  76. }
  77. else {
  78. throw new InvalidArgumentException('invalid grant type');
  79. }
  80. $oCreateClient = new ReflectionMethod(Cidaas::class, 'createClient');
  81. $oClient = $oCreateClient->invoke($this);
  82. $oParseJson = new ReflectionMethod(Cidaas::class, 'parseJson');
  83. return $oClient->requestAsync('POST', $this->sBaseUrl . '/token-srv/token', ['form_params' => $aParams])->then(function (ResponseInterface $oResponse) use ($oParseJson) {
  84. return $oParseJson->invoke($this, $oResponse->getBody());
  85. });
  86. }
  87. }
  88. /** @} */