diff --git a/htdocs/admin/oauthlogintokens.php b/htdocs/admin/oauthlogintokens.php
index 680a5f1f02f..820ce847030 100644
--- a/htdocs/admin/oauthlogintokens.php
+++ b/htdocs/admin/oauthlogintokens.php
@@ -122,7 +122,7 @@ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domai
$form = new Form($db);
-llxHeader('', $langs->trans("PrintingSetup"));
+llxHeader('', $langs->trans("TokenManager"));
$linkback = ''.$langs->trans("BackToModuleList").'';
print load_fiche_titre($langs->trans('ConfigOAuth'), $linkback, 'title_setup');
@@ -163,13 +163,24 @@ if ($mode == 'setup' && $user->admin) {
$urltocheckperms = 'https://github.com/settings/applications/';
} elseif ($keyforsupportedoauth2array == 'OAUTH_GOOGLE_NAME') {
// List of keys that will be converted into scopes (from constants 'SCOPE_state_in_uppercase' in file of service).
- // We pass this param list in to 'state' because we need it before and after the redirect.
- $shortscope = 'userinfo_email,userinfo_profile,cloud_print';
- if (!empty($conf->global->OAUTH_GSUITE)) {
+ // List of scopes for Google are here: https://developers.google.com/identity/protocols/oauth2/scopes
+ // We pass this key list into the param 'state' because we need it before and after the redirect.
+ $shortscope = 'userinfo_email,userinfo_profile';
+ $shortscope .= ',openid,email,profile'; // For openid connect
+ if (!empty($conf->printing->enabled)) {
+ $shortscope .= ',cloud_print';
+ }
+ if (!empty($conf->global->OAUTH_GOOGLE_GSUITE)) {
$shortscope .= ',admin_directory_user';
}
- //$scope.=',gmail_full';
- $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
+ if (!empty($conf->global->OAUTH_GOOGLE_GMAIL)) {
+ $shortscope.=',gmail_full';
+ }
+
+ $oauthstateanticsrf = bin2hex(random_bytes(128/8));
+ $_SESSION['oauthstateanticsrf'] = $shortscope.'-'.$oauthstateanticsrf;
+
+ $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
$urltodelete = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?action=delete&token='.newToken().'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
$urltocheckperms = 'https://security.google.com/settings/security/permissions';
} elseif ($keyforsupportedoauth2array == 'OAUTH_STRIPE_TEST_NAME') {
diff --git a/htdocs/core/modules/modPrinting.class.php b/htdocs/core/modules/modPrinting.class.php
index 4c104b30ecf..c9e99b3d933 100644
--- a/htdocs/core/modules/modPrinting.class.php
+++ b/htdocs/core/modules/modPrinting.class.php
@@ -34,7 +34,6 @@ include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
*/
class modPrinting extends DolibarrModules
{
-
/**
* Constructor
*
diff --git a/htdocs/core/modules/oauth/google_oauthcallback.php b/htdocs/core/modules/oauth/google_oauthcallback.php
index 4f9fded878f..520da0881e9 100644
--- a/htdocs/core/modules/oauth/google_oauthcallback.php
+++ b/htdocs/core/modules/oauth/google_oauthcallback.php
@@ -16,6 +16,9 @@
* along with this program. If not, see .
*/
+// This page should make the process to login and get token as described here:
+// https://developers.google.com/identity/protocols/oauth2/openid-connect#server-flow
+
/**
* \file htdocs/core/modules/oauth/google_oauthcallback.php
* \ingroup oauth
@@ -70,9 +73,13 @@ $credentials = new Credentials(
$currentUri->getAbsoluteUri()
);
+$state = GETPOST('state');
+
$requestedpermissionsarray = array();
-if (GETPOST('state')) {
- $requestedpermissionsarray = explode(',', GETPOST('state')); // Example: 'userinfo_email,userinfo_profile,cloud_print'. 'state' parameter is standard to store a hash value and can be used to retrieve some parameters back
+if ($state) {
+ // 'state' parameter is standard to store a hash value and can be used to retrieve some parameters back
+ $statewithscopeonly = preg_replace('/\-.*$/', '', $state);
+ $requestedpermissionsarray = explode(',', $statewithscopeonly); // Example: 'userinfo_email,userinfo_profile,openid,email,profile,cloud_print'.
}
if ($action != 'delete' && empty($requestedpermissionsarray)) {
print 'Error, parameter state is not defined';
@@ -80,6 +87,8 @@ if ($action != 'delete' && empty($requestedpermissionsarray)) {
}
//var_dump($requestedpermissionsarray);exit;
+
+
// Instantiate the Api service using the credentials, http client and storage mechanism for the token
// $requestedpermissionsarray contains list of scopes.
// Conversion into URL is done by Reflection on constant with name SCOPE_scope_in_uppercase
@@ -91,6 +100,8 @@ $apiService->setAccessType('offline');
$apiService->setApprouvalPrompt('force');
+//$apiService->setLoginHint(email); // If we know the email of Google account, we can set it to have it correctly selected on login prompt on multiaccount
+
$langs->load("oauth");
@@ -108,17 +119,12 @@ if ($action == 'delete') {
exit();
}
-if (!empty($_GET['code'])) { // We are coming from oauth provider page
+if (GETPOST('code')) { // We are coming from oauth provider page.
dol_syslog("We are coming from the oauth provider page");
- //llxHeader('',$langs->trans("OAuthSetup"));
- //$linkback=''.$langs->trans("BackToModuleList").'';
- //print load_fiche_titre($langs->trans("OAuthSetup"),$linkback,'title_setup');
+ // TODO
+ // We should validate that the $sate is same than the one into $_SESSION['oauthstateanticsrf'], return error if not.
- //print dol_get_fiche_head();
- // retrieve the CSRF state parameter
- $state = isset($_GET['state']) ? $_GET['state'] : null;
- //print '
';
// This was a callback request from service, get the token
try {
@@ -126,9 +132,13 @@ if (!empty($_GET['code'])) { // We are coming from oauth provider page
//var_dump($state);
//var_dump($apiService); // OAuth\OAuth2\Service\Google
- $token = $apiService->requestAccessToken($_GET['code'], $state);
+ // This request the token
+ // Result is stored into object managed by class DoliStorage into includes/OAuth/Common/Storage/DoliStorage.php, so into table llx_oauth_token
+ $token = $apiService->requestAccessToken(GETPOST('code'), $state);
- setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs'); // Stored into object managed by class DoliStorage so into table oauth_token
+ // Note: The token contains a lot of information about the user.
+
+ setEventMessages($langs->trans('NewTokenStored'), null, 'mesgs');
$backtourl = $_SESSION["backtourlsavedbeforeoauthjump"];
unset($_SESSION["backtourlsavedbeforeoauthjump"]);
@@ -138,8 +148,9 @@ if (!empty($_GET['code'])) { // We are coming from oauth provider page
} catch (Exception $e) {
print $e->getMessage();
}
-} else // If entry on page with no parameter, we arrive here
-{
+} else {
+ // If we enter this page without 'code' parameter, we arrive here. this is the case when we want to get the redirect
+ // to the OAuth provider login page
$_SESSION["backtourlsavedbeforeoauthjump"] = $backtourl;
// This may create record into oauth_state before the header redirect.
@@ -160,6 +171,6 @@ if (!empty($_GET['code'])) { // We are coming from oauth provider page
* View
*/
-// No view at all, just actions
+// No view at all, just actions, so we never reach this line, except on error.
$db->close();
diff --git a/htdocs/core/tpl/login.tpl.php b/htdocs/core/tpl/login.tpl.php
index 338d2bd1a19..2645a76a8ab 100644
--- a/htdocs/core/tpl/login.tpl.php
+++ b/htdocs/core/tpl/login.tpl.php
@@ -33,6 +33,8 @@ if (empty($conf) || !is_object($conf)) {
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
+
+
header('Cache-Control: Public, must-revalidate');
header("Content-type: text/html; charset=".$conf->file->character_set_client);
@@ -316,6 +318,37 @@ if (isset($conf->file->main_authentication) && preg_match('/openid/', $conf->fil
echo '';
}
+if (isset($conf->file->main_authentication) && preg_match('/google/', $conf->file->main_authentication)) {
+ $langs->load("users");
+
+ global $dolibarr_main_url_root;
+
+ // Define $urlwithroot
+ $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
+ $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
+ //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
+
+ echo '
';
+ echo '';
+
+ $shortscope = 'userinfo_email,userinfo_profile';
+ $shortscope .= ',openid,email,profile'; // For openid connect
+
+ $oauthstateanticsrf = bin2hex(random_bytes(128/8));
+ $_SESSION['oauthstateanticsrf'] = $shortscope.'-'.$oauthstateanticsrf;
+ $urltorenew = $urlwithroot.'/core/modules/oauth/google_oauthcallback.php?shortscope='.$shortscope.'&state='.$shortscope.$oauthstateanticsrf.'&backtourl='.urlencode(DOL_URL_ROOT.'/admin/oauthlogintokens.php');
+
+ $url = $urltorenew;
+
+ //if (!empty($url)) {
+ print img_picto('', 'google', 'class="pictofixedwidth"').'
'.$langs->trans("LoginWith", "Google").'';
+ /*} else {
+ $langs->load("errors");
+ print '
'.$langs->trans("ErrorOpenIDSetupNotComplete", 'MAIN_AUTHENTICATION_OPENID_URL').'';
+ }*/
+
+ echo '
';
+}
?>
diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang
index 91dd5ba4509..a43e97c1a02 100644
--- a/htdocs/langs/en_US/other.lang
+++ b/htdocs/langs/en_US/other.lang
@@ -272,7 +272,8 @@ ProjectCreatedByEmailCollector=Project created by email collector from email MSG
TicketCreatedByEmailCollector=Ticket created by email collector from email MSGID %s
OpeningHoursFormatDesc=Use a - to separate opening and closing hours.
Use a space to enter different ranges.
Example: 8-12 14-18
SuffixSessionName=Suffix for session name
-
+LoginWith=Login with %s
+
##### Export #####
ExportsArea=Exports area
AvailableFormats=Available formats