Aleksandr Trofimov 2 hónapja
szülő
commit
a98ece63d5

+ 5 - 5
modules/boonex/cidaas_connect/classes/BxCidaasConModule.php

@@ -11,7 +11,6 @@
 
 require_once(BX_DIRECTORY_PATH_MODULES . 'boonex/cidaas_connect/vendor/autoload.php');
 
-use Cidaas\OAuth2\Client\Provider\Cidaas;
 use Cidaas\OAuth2\Client\Provider\GrantType;
 use GuzzleHttp\Exception\ClientException;
 
@@ -42,7 +41,7 @@ class BxCidaasConModule extends BxBaseModConnectModule
             $this->_redirect($this->_oConfig->sDefaultRedirectUrl);
         }
 
-        if (!$this->_oConfig->sBaseUrl || !$this->_oConfig->sClientID || !$this->_oConfig->sSecret) {
+        if (!$this->_oConfig->sBaseUrl || !$this->_oConfig->sClientID || (!$this->_oConfig->bPkce && !$this->_oConfig->sSecret)) {
             require_once(BX_DIRECTORY_PATH_INC . 'design.inc.php');
             bx_import('BxDolLanguages');
             $sCode = MsgBox(_t('_bx_cidaascon_profile_error_api_keys'));
@@ -201,14 +200,15 @@ class BxCidaasConModule extends BxBaseModConnectModule
     }
 
     /**
-     * @return Cidaas
+     * @return BxCidaasConProvider
      */
     protected function _getProvider()
     {
-        return new Cidaas(
+        bx_import('Provider', $this->_aModule);
+        return new BxCidaasConProvider(
             $this->_oConfig->sBaseUrl,
             $this->_oConfig->sClientID,
-            $this->_oConfig->sSecret,
+            $this->_oConfig->sSecret ? $this->_oConfig->sSecret : '',
             $this->_oConfig->sPageHandle,
             null,
             $this->_oConfig->bDebug

+ 104 - 0
modules/boonex/cidaas_connect/classes/BxCidaasConProvider.php

@@ -0,0 +1,104 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    CidaasConnect Cidaas Connect
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+use Cidaas\OAuth2\Client\Provider\Cidaas;
+use Cidaas\OAuth2\Client\Provider\GrantType;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Promise\PromiseInterface;
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * Cidaas SDK wrapper that allows PKCE without a client secret.
+ * The upstream constructor and token request always require client_secret.
+ */
+class BxCidaasConProvider extends Cidaas
+{
+    protected $sBaseUrl;
+    protected $sClientId;
+    protected $sClientSecret;
+    protected $sRedirectUri;
+    protected $bDebug;
+
+    public function __construct(string $baseUrl, string $clientId, string $clientSecret, string $redirectUri, ?HandlerStack $handler = null, bool $debug = false)
+    {
+        $this->sBaseUrl = rtrim($baseUrl, '/');
+        $this->sClientId = $clientId;
+        $this->sClientSecret = $clientSecret;
+        $this->sRedirectUri = $redirectUri;
+        $this->bDebug = $debug;
+
+        // Upstream validate() rejects an empty secret; pass a placeholder then clear it.
+        parent::__construct($baseUrl, $clientId, $clientSecret !== '' ? $clientSecret : '.', $redirectUri, $handler, $debug);
+
+        if ($clientSecret === '') {
+            $oProp = new ReflectionProperty(Cidaas::class, 'clientSecret');
+            $oProp->setValue($this, '');
+        }
+    }
+
+    public function getAccessToken(string $grantType, string $code = '', string $refreshToken = '', bool $pkceEnabled = false): PromiseInterface
+    {
+        if ($grantType === GrantType::AuthorizationCode) {
+            if (empty($code))
+                throw new InvalidArgumentException('code must not be empty in authorization_code flow');
+
+            $aParams = [
+                'client_id' => $this->sClientId,
+                'redirect_uri' => $this->sRedirectUri,
+                'grant_type' => 'authorization_code',
+                'code' => $code,
+            ];
+
+            if ($this->sClientSecret !== '')
+                $aParams['client_secret'] = $this->sClientSecret;
+
+            if ($pkceEnabled)
+                $aParams['code_verifier'] = $_SESSION['code-verifier'] ?? '';
+        }
+        else if ($grantType === GrantType::RefreshToken) {
+            if (empty($refreshToken))
+                throw new InvalidArgumentException('refreshToken must not be empty in refresh_token flow');
+
+            $aParams = [
+                'client_id' => $this->sClientId,
+                'grant_type' => 'refresh_token',
+                'refresh_token' => $refreshToken,
+            ];
+
+            if ($this->sClientSecret !== '')
+                $aParams['client_secret'] = $this->sClientSecret;
+        }
+        else if ($grantType === GrantType::ClientCredentials) {
+            if ($this->sClientSecret === '')
+                throw new InvalidArgumentException('client secret is required for client_credentials flow');
+
+            $aParams = [
+                'client_id' => $this->sClientId,
+                'client_secret' => $this->sClientSecret,
+                'grant_type' => 'client_credentials',
+            ];
+        }
+        else {
+            throw new InvalidArgumentException('invalid grant type');
+        }
+
+        $oCreateClient = new ReflectionMethod(Cidaas::class, 'createClient');
+        $oClient = $oCreateClient->invoke($this);
+
+        $oParseJson = new ReflectionMethod(Cidaas::class, 'parseJson');
+
+        return $oClient->requestAsync('POST', $this->sBaseUrl . '/token-srv/token', ['form_params' => $aParams])->then(function (ResponseInterface $oResponse) use ($oParseJson) {
+            return $oParseJson->invoke($this, $oResponse->getBody());
+        });
+    }
+}
+
+/** @} */

+ 4 - 3
modules/boonex/cidaas_connect/install/langs/en.xml

@@ -9,11 +9,12 @@
         <ul>
             <li>Redirect URL: <strong>{0}</strong></li>
             <li>Base URL: your Cidaas instance, e.g. https://yourtenant.cidaas.de</li>
-            <li>Client ID and Client Secret issued for that application</li>
+            <li>Client ID issued for that application</li>
+            <li>Client Secret — required unless PKCE is enabled for a public client</li>
         </ul>
-        <p>Enable PKCE in module settings if the Cidaas app is configured for the PKCE authorization code flow. For more info see <a target="_blank" href="https://docs.cidaas.com/">Cidaas documentation</a>.</p>
+        <p>Enable PKCE in module settings if the Cidaas app is configured for the PKCE authorization code flow. With PKCE, Client Secret can be left empty. For more info see <a target="_blank" href="https://docs.cidaas.com/">Cidaas documentation</a>.</p>
         ]]></string>
-	<string name="_bx_cidaascon_profile_error_api_keys"><![CDATA[Please configure the module in admin panel (can't define Base URL, Client ID & Secret)]]></string>
+	<string name="_bx_cidaascon_profile_error_api_keys"><![CDATA[Please configure the module in admin panel (Base URL and Client ID are required; Client Secret is required unless PKCE is enabled)]]></string>
 	<string name="_bx_cidaascon_auth_title"><![CDATA[Login with Cidaas]]></string>
 
     <string name="_bx_cidaascon_adm_stg_cpt_type"><![CDATA[Cidaas Connect]]></string>