diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php
index e5bf3142259..c25d0240995 100644
--- a/htdocs/admin/emailcollector_card.php
+++ b/htdocs/admin/emailcollector_card.php
@@ -413,7 +413,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
} else {
$keyforprovider = '';
}
- $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
+ $keyforsupportedoauth2array = preg_replace('/-.*$/', '', strtoupper($keyforsupportedoauth2array));
$keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
if (!empty($supportedoauth2array)) {
diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php
index 08f98cebad5..8471f14da08 100644
--- a/htdocs/admin/oauthlogintokens.php
+++ b/htdocs/admin/oauthlogintokens.php
@@ -30,6 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/oauth.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
use OAuth\Common\Storage\DoliStorage;
+use OAuth\Common\Consumer\Credentials;
$supportedoauth2array = getSupportedOauth2Array();
@@ -114,6 +115,101 @@ if ($action == 'setvalue' && $user->admin) {
$action = '';
}
+// Test a refresh of a token using the refresh token
+if ($action == 'refreshtoken' && $user->admin) {
+ $keyforprovider = GETPOST('keyforprovider');
+ $OAUTH_SERVICENAME = GETPOST('service');
+
+ // Show value of token
+ $tokenobj = null;
+ // Load OAUth libraries
+ require_once DOL_DOCUMENT_ROOT.'/includes/OAuth/bootstrap.php';
+
+ $keyforsupportedoauth2array = $OAUTH_SERVICENAME;
+ if (preg_match('/^.*-/', $keyforsupportedoauth2array)) {
+ $keyforprovider = preg_replace('/^.*-/', '', $keyforsupportedoauth2array);
+ } else {
+ $keyforprovider = '';
+ }
+ $keyforsupportedoauth2array = preg_replace('/-.*$/', '', strtoupper($keyforsupportedoauth2array));
+ $keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
+
+ $keyforparamtenant = 'OAUTH_'.strtoupper(empty($supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']).($keyforprovider ? '-'.$keyforprovider : '').'_TENANT';
+
+ // Dolibarr storage
+ $storage = new DoliStorage($db, $conf, $keyforprovider, getDolGlobalString($keyforparamtenant));
+ try {
+ // $OAUTH_SERVICENAME is for example 'Google-keyforprovider'
+ print ''."\n";
+
+ dol_syslog("oauthlogintokens.php: Read token for service ".$OAUTH_SERVICENAME);
+ $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
+
+ $expire = ($tokenobj->getEndOfLife() !== -9002 && $tokenobj->getEndOfLife() !== -9001 && time() > ($tokenobj->getEndOfLife() - 30));
+ // We have to save the refresh token in a memory variable because Google give it only once
+ $refreshtoken = $tokenobj->getRefreshToken();
+ print '';
+
+ //print $tokenobj->getExtraParams()['id_token'].'
';
+ //print $tokenobj->getAccessToken().'
';
+ //print $tokenobj->getRefreshToken().'
';
+
+ //var_dump($expire);
+
+ // We do the refresh even if not expired, this is the goal of action.
+ $oauthname = explode('-', $OAUTH_SERVICENAME);
+ $keyforoauthservice = strtoupper($oauthname[0]).(empty($oauthname[1]) ? '' : '-'.$oauthname[1]);
+ $credentials = new Credentials(
+ getDolGlobalString('OAUTH_'.$keyforoauthservice.'_ID'),
+ getDolGlobalString('OAUTH_'.$keyforoauthservice.'_SECRET'),
+ getDolGlobalString('OAUTH_'.$keyforoauthservice.'_URLCALLBACK')
+ );
+
+ $serviceFactory = new \OAuth\ServiceFactory();
+ $httpClient = new \OAuth\Common\Http\Client\CurlClient();
+ // TODO Set options for proxy and timeout
+ // $params=array('CURLXXX'=>value, ...)
+ //$httpClient->setCurlParameters($params);
+ $serviceFactory->setHttpClient($httpClient);
+
+ $scopes = array();
+ if (preg_match('/^Microsoft/', $OAUTH_SERVICENAME)) {
+ //$extraparams = $tokenobj->getExtraParams();
+ $tmp = explode('-', $OAUTH_SERVICENAME);
+ $scopes = explode(',', getDolGlobalString('OAUTH_'.strtoupper($tmp[0]).(empty($tmp[1]) ? '' : '-'.$tmp[1]).'_SCOPE'));
+ }
+
+ // ex service is Google-Emails we need only the first part Google
+ $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, $scopes);
+
+ if ($apiService instanceof OAuth\OAuth2\Service\AbstractService || $apiService instanceof OAuth\OAuth1\Service\AbstractService) {
+ // ServiceInterface does not provide refreshAccessToekn, AbstractService does
+ dol_syslog("oauthlogintokens.php: call refreshAccessToken to get the new access token");
+ $tokenobj = $apiService->refreshAccessToken($tokenobj); // This call refresh and store the new token (but does not include the refresh token)
+
+ dol_syslog("oauthlogintokens.php: call setRefreshToken");
+ $tokenobj->setRefreshToken($refreshtoken); // Restore the refresh token
+
+ dol_syslog("oauthlogintokens.php: call storeAccessToken to save the new access token + the old refresh token");
+ $storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj); // This save the new token including the refresh token
+
+ if ($expire) {
+ setEventMessages($langs->trans("OldTokenWasExpiredItHasBeenRefresh"), null, 'mesgs');
+ } else {
+ setEventMessages($langs->trans("OldTokenWasNotExpiredButItHasBeenRefresh"), null, 'mesgs');
+ }
+ } else {
+ dol_print_error($db, 'apiService is not a correct OAUTH2 Abstract service');
+ }
+
+ dol_syslog("oauthlogintokens.php: Read token again for service ".$OAUTH_SERVICENAME);
+ $tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
+ } catch (Exception $e) {
+ // Return an error if token not found
+ print $e->getMessage();
+ }
+}
+
/*
* View
@@ -176,7 +272,7 @@ if ($mode == 'setup' && $user->admin) {
$keybeforeprovider = $keyforsupportedoauth2array;
$keyforprovider = '';
}
- $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
+ $keyforsupportedoauth2array = preg_replace('/-.*$/', '', strtoupper($keyforsupportedoauth2array));
$keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
$nameofservice = ucfirst(strtolower(empty($supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']) ? 'Unknown' : $supportedoauth2array[$keyforsupportedoauth2array]['callbackfile']));
@@ -191,6 +287,8 @@ if ($mode == 'setup' && $user->admin) {
}
$state = $shortscope; // TODO USe a better state
+ $urltorefresh = $_SERVER["PHP_SELF"].'?action=refreshtoken&token='.newToken();
+
// Define $urltorenew, $urltodelete, $urltocheckperms
if ($keyforsupportedoauth2array == 'OAUTH_GITHUB_NAME') {
// List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service).
@@ -220,6 +318,9 @@ if ($mode == 'setup' && $user->admin) {
if ($urltorenew) {
$urltorenew .= '&keyforprovider='.urlencode($keyforprovider);
}
+ if ($urltorefresh) {
+ $urltorefresh .= '&keyforprovider='.urlencode($keyforprovider).'&service='.urlencode($OAUTH_SERVICENAME);
+ }
if ($urltodelete) {
$urltodelete .= '&keyforprovider='.urlencode($keyforprovider);
}
@@ -234,6 +335,7 @@ if ($mode == 'setup' && $user->admin) {
// $OAUTH_SERVICENAME is for example 'Google-keyforprovider'
print ''."\n";
$tokenobj = $storage->retrieveAccessToken($OAUTH_SERVICENAME);
+ print '';
//print $storage->token.'
';
//print $tokenobj->getExtraParams()['id_token'].'
';
//print $tokenobj->getAccessToken().'
';
@@ -348,6 +450,11 @@ if ($mode == 'setup' && $user->admin) {
print $form->textwithpicto('', $langs->trans('RequestAccess'));
print '
';
}
+ // Request remote token
+ if ($urltorefresh && $refreshtoken) {
+ print ''.$langs->trans('RefreshToken').'';
+ }
+
// Check remote access
if ($urltocheckperms) {
print '
'.$langs->trans("ToCheckDeleteTokenOnProvider", $OAUTH_SERVICENAME).': '.$urltocheckperms.'';
diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php
index cfa1c65e93c..bab0e76a46f 100644
--- a/htdocs/emailcollector/class/emailcollector.class.php
+++ b/htdocs/emailcollector/class/emailcollector.class.php
@@ -1144,7 +1144,7 @@ class EmailCollector extends CommonObject
} else {
$keyforprovider = '';
}
- $keyforsupportedoauth2array = preg_replace('/-.*$/', '', $keyforsupportedoauth2array);
+ $keyforsupportedoauth2array = preg_replace('/-.*$/', '', strtoupper($keyforsupportedoauth2array));
$keyforsupportedoauth2array = 'OAUTH_'.$keyforsupportedoauth2array.'_NAME';
if (!empty($supportedoauth2array)) {
@@ -1185,11 +1185,22 @@ class EmailCollector extends CommonObject
$serviceFactory = new \OAuth\ServiceFactory();
$oauthname = explode('-', $OAUTH_SERVICENAME);
// ex service is Google-Emails we need only the first part Google
- $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, array());
+
+ $scopes = array();
+ if (preg_match('/^Microsoft/', $OAUTH_SERVICENAME)) {
+ //$extraparams = $tokenobj->getExtraParams();
+ $tmp = explode('-', $OAUTH_SERVICENAME);
+ $scopes = explode(',', getDolGlobalString('OAUTH_'.strtoupper($tmp[0]).(empty($tmp[1]) ? '' : '-'.$tmp[1]).'_SCOPE'));
+ }
+
+ $apiService = $serviceFactory->createService($oauthname[0], $credentials, $storage, $scopes);
+
'@phan-var-force OAuth\OAuth2\Service\AbstractService|OAuth\OAuth1\Service\AbstractService $apiService'; // createService is only ServiceInterface
- // We have to save the token because Google give it only once
+
$refreshtoken = $tokenobj->getRefreshToken();
$tokenobj = $apiService->refreshAccessToken($tokenobj);
+
+ // We have to save the token because answer give it only once
$tokenobj->setRefreshToken($refreshtoken);
$storage->storeAccessToken($OAUTH_SERVICENAME, $tokenobj);
}
diff --git a/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php b/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php
index b6f89118d83..bc28762c688 100644
--- a/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php
+++ b/htdocs/includes/OAuth/OAuth2/Service/AbstractService.php
@@ -218,12 +218,31 @@ abstract class AbstractService extends BaseAbstractService implements ServiceInt
'refresh_token' => $refreshToken,
);
+ // @CHANGE LDR
+ //global $conf; $conf->global->OAUTH_ADD_SCOPE_AND_TENANT_IN_REFRESH_MESSAGE = 1;
+ if (getDolGlobalString('OAUTH_ADD_SCOPE_AND_TENANT_IN_REFRESH_MESSAGE')) {
+ if (!empty($this->scopes)) {
+ $parameters['scope'] = implode($this->getScopesDelimiter(), $this->scopes);
+ }
+ if ($this->storage->getTenant()) {
+ $parameters['tenant'] = $this->storage->getTenant();
+ }
+ }
+ //var_dump($parameters);
+
$responseBody = $this->httpClient->retrieveResponse(
$this->getAccessTokenEndpoint(),
$parameters,
$this->getExtraOAuthHeaders()
);
- //print $responseBody;exit; // We must have a result "{"token_type":"Bearer","scope...
+
+
+ // @CHANGE LDR
+ $data = json_decode((string) $responseBody, true);
+ if (is_array($data) && !empty($data['error_description'])) {
+ print 'Oauth2 AbstractService error received: '.$data['error_description'];
+ }
+ //print $responseBody;exit; // We must have a result string "{"token_type":"Bearer","error_description":...,"scope...
$token = $this->parseAccessTokenResponse($responseBody);
$this->storage->storeAccessToken($this->service(), $token);