diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php
index 99327e786ff..c06f9c7a49f 100644
--- a/htdocs/admin/oauthlogintokens.php
+++ b/htdocs/admin/oauthlogintokens.php
@@ -432,7 +432,7 @@ if ($mode == 'setup' && $user->admin) {
print '
';
if ($keyforprovider != 'Login') {
if (is_object($tokenobj)) {
- print $form->textwithpicto(yn(1), $langs->trans("HasAccessToken").' : '.dol_print_date($storage->date_modification, 'dayhour').' state='.dol_escape_htmltag($storage->state));
+ print $form->textwithpicto(yn(1), $langs->trans("HasAccessToken").' : '.dol_print_date($storage->date_modification, 'dayhour').' Scopes saved into field state='.dol_escape_htmltag($storage->state));
} else {
print ''.$langs->trans("NoAccessToken").'';
}
diff --git a/htdocs/core/modules/oauth/generic_oauthcallback.php b/htdocs/core/modules/oauth/generic_oauthcallback.php
index 9a89ce154d6..5258d3e69f2 100644
--- a/htdocs/core/modules/oauth/generic_oauthcallback.php
+++ b/htdocs/core/modules/oauth/generic_oauthcallback.php
@@ -114,9 +114,9 @@ if ($state) {
}
}
-// Add a test to check that the state parameter is provided into URL when we make the first call to ask the redirect or when we receive the callback
-// but not when callback was ok and we recall the page
-if ($action != 'delete' && !GETPOST('afteroauthloginreturn') && (empty($statewithscopeonly) || empty($requestedpermissionsarray)) && $state != 'none') {
+// Add a test to check that the state parameter is provided into URL when we make the first call to ask the redirect or when we receive the callback,
+// but NOT when callback was ok and we recall the page
+if ($action != 'delete' && !GETPOST('afteroauthloginreturn') && (empty($statewithscopeonly) || empty($requestedpermissionsarray)) && !preg_match('/^none/', $state)) {
if (GETPOST('error') || GETPOST('error_description')) {
setEventMessages($langs->trans("Error").' '.GETPOST('error_description'), null, 'errors');
} else {
@@ -208,7 +208,7 @@ if (!GETPOST('code') && !GETPOST('error')) {
if (empty($state) || $state == 'none') {
// Generate a random state value to prevent CSRF attack. Store it into session juste after to check it when we will receive the callback from provider.
- $state = bin2hex(random_bytes(16));
+ $state = 'none-'.bin2hex(random_bytes(16));
}
// If we enter this page without 'code' parameter, it means we click on the link from login page ($forlogin is set) or from setup page and we want to get the redirect
@@ -301,24 +301,57 @@ if (!GETPOST('code') && !GETPOST('error')) {
$db->begin();
- // This requests the token from the received OAuth code (call of the endpoint)
- // Result is stored into object managed by class DoliStorage into includes/OAuth/Common/Storage/DoliStorage.php and into database table llx_oauth_token
- $token = $apiService->requestAccessToken(GETPOST('code'), $state);
- '@phan-var-force OAuth\Common\Token\AbstractToken $token';
+ $token = null;
+ $last_insert_id = 0;
+ try {
+ // This requests the token from the received OAuth code (call of the endpoint)
+ // Result is stored into object managed by class DoliStorage into includes/OAuth/Common/Storage/DoliStorage.php and into database table llx_oauth_token
+ $token = $apiService->requestAccessToken(GETPOST('code'), $state);
+ '@phan-var-force OAuth\Common\Token\AbstractToken $token';
+
+ $storage = $apiService->getStorage();
+ if (property_exists($storage, 'last_insert_id')) {
+ $last_insert_id = $storage->last_insert_id;
+ }
+ } catch (Exception $e) {
+ dol_syslog("Failed to get token with requestAccessToken: ".$e->getMessage(), LOG_ERR);
+ setEventMessages("Failed to get token with requestAccessToken: ".$e->getMessage(), null, 'errors');
+ $errorincheck++;
+ }
+
+ // The refresh token is inside the object token if the prompt was forced only. Otherwise, it may be found into extraParams section.
+ //$refreshtoken = $token->getRefreshToken();
+ //var_dump($refreshtoken);
+ dol_syslog("requestAccessToken complete");
// The refresh token is inside the object token if the prompt was forced only.
//$refreshtoken = $token->getRefreshToken();
//var_dump($refreshtoken);
// Note: The extraparams has the 'id_token' than contains a lot of information about the user.
- $extraparams = $token->getExtraParams();
+ if ($token) {
+ $extraparams = $token->getExtraParams();
- $scope = empty($extraparams['scope']) ? '' : $extraparams['scope'];
- $tokenstring = $token->getAccessToken();
- // Update entry in llx_oauth_token to store the scope associated to the token into field "state" (field should be renamed).
- // It is not stored by default by DoliStorage.
- // TODO Update using $scope and $tokenstring
+ $scope = empty($extraparams['scope']) ? '' : $extraparams['scope'];
+ $tokenstring = $token->getAccessToken();
+ // Update entry in llx_oauth_token to store the scope associated to the token into field "state" (field should be renamed).
+ // It is not stored by default by DoliStorage.
+ // TODO Update using $scope and $tokenstring and $last_insert_id
+ $refreshtoken = empty($extraparams['refresh_token']) ? '' : $extraparams['refresh_token'];
+ if (empty($refreshtoken)) {
+ $refreshtoken = $token->getRefreshToken();
+ }
+ if ($last_insert_id) {
+ $sqlupdate = "UPDATE ".MAIN_DB_PREFIX."oauth_token";
+ $sqlupdate .= " SET state = '".(empty($scope) ? '' : $db->escape($scope))."', tokenstring = '".$db->escape($tokenstring)."', tokenstring_refresh = '".$db->escape($refreshtoken)."'";
+ $sqlupdate .= " WHERE rowid = ".((int) $last_insert_id);
+
+ $db->query($sqlupdate);
+
+ //var_dump($scope, $token, $refreshtoken, $last_insert_id, $sqlupdate);exit;
+ }
+ }
$username = '';
$useremail = '';
diff --git a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
index 61ccec7d284..38e041a6640 100644
--- a/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
+++ b/htdocs/includes/OAuth/Common/Storage/DoliStorage.php
@@ -66,6 +66,7 @@ class DoliStorage implements TokenStorageInterface
public $date_modification;
public $userid; // ID of user for user specific OAuth entries
+ public $last_insert_id; // The ID of last inserted record
/**
@@ -82,6 +83,7 @@ class DoliStorage implements TokenStorageInterface
$this->tokens = array();
$this->states = array();
$this->tenant = $tenant;
+ $this->last_insert_id = 0;
//$this->key = $key;
//$this->stateKey = $stateKey;
}
@@ -144,7 +146,9 @@ class DoliStorage implements TokenStorageInterface
$resql = $this->db->query($sql);
if (!$resql) {
dol_print_error($this->db);
- }
+ } else {
+ $this->last_insert_id = ((int) $obj['rowid']);
+ }
} else {
// save
$sql = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, token, entity, datec)";
@@ -154,7 +158,9 @@ class DoliStorage implements TokenStorageInterface
$resql = $this->db->query($sql);
if (!$resql) {
dol_print_error($this->db);
- }
+ } else {
+ $this->last_insert_id = $this->db->last_insert_id(MAIN_DB_PREFIX."oauth_token");
+ }
}
//print $sql;
|