diff --git a/composer.json b/composer.json
index 10845c3e3..d9989fe1c 100755
--- a/composer.json
+++ b/composer.json
@@ -39,6 +39,8 @@
"illuminate/database": "~5.4.0",
"intervention/image": "^2.3",
"league/csv": "^8.2",
+ "league/oauth2-client": "^2.6",
+ "league/oauth2-google": "^3.0",
"maximebf/debugbar": "^1.15",
"monolog/monolog": "^1.22",
"mpdf/mpdf": "^v8.0.7",
@@ -55,6 +57,7 @@
"symfony/polyfill-php70": "^1.8",
"symfony/translation": "^3.3",
"symfony/var-dumper": "^3.3",
+ "thenetworg/oauth2-azure": "^2.0",
"willdurand/geocoder": "^3.3"
},
"require-dev": {
diff --git a/core.php b/core.php
index fbfae808a..e01ac0556 100755
--- a/core.php
+++ b/core.php
@@ -55,7 +55,7 @@ $rootdir = ROOTDIR;
$baseurl = BASEURL;
// Sicurezza della sessioni
-ini_set('session.cookie_samesite', 'strict');
+//ini_set('session.cookie_samesite', 'strict');
ini_set('session.use_trans_sid', '0');
ini_set('session.use_only_cookies', '1');
diff --git a/modules/emails/src/Account.php b/modules/emails/src/Account.php
index b6f8f6a21..7b003c83b 100755
--- a/modules/emails/src/Account.php
+++ b/modules/emails/src/Account.php
@@ -34,6 +34,9 @@ class Account extends Model
protected $table = 'em_accounts';
+ /** @var OAuth2 */
+ protected $gestoreOAuth2;
+
public function testConnection()
{
// Impostazione di connected_at a NULL
@@ -54,6 +57,17 @@ class Account extends Model
return $result;
}
+ public function getGestoreOAuth2()
+ {
+ if (isset($this->gestoreOAuth2)) {
+ return $this->gestoreOAuth2;
+ }
+
+ $this->gestoreOAuth2 = new OAuth2($this);
+
+ return $this->gestoreOAuth2;
+ }
+
/* Relazioni Eloquent */
public function templates()
diff --git a/modules/emails/src/OAuth2.php b/modules/emails/src/OAuth2.php
new file mode 100644
index 000000000..6c70a81bf
--- /dev/null
+++ b/modules/emails/src/OAuth2.php
@@ -0,0 +1,190 @@
+ [
+ 'name' => 'Microsoft',
+ 'class' => Azure::class,
+ 'options' => [
+ 'scope' => [
+ 'offline_access',
+ 'https://graph.microsoft.com/SMTP.Send',
+ //'https://outlook.office.com/IMAP.AccessAsUser.All'
+ ],
+ ],
+ 'help' => 'https://docs.openstamanager.com/faq/configurazione-oauth2#microsoft',
+ ],
+ 'google' => [
+ 'name' => 'Google',
+ 'class' => Google::class,
+ 'options' => [
+ 'scope' => ['https://mail.google.com/'],
+ 'accessType' => 'offline',
+ ],
+ 'help' => 'https://docs.openstamanager.com/faq/configurazione-oauth2#google',
+ ],
+ ];
+ protected $provider;
+ protected $account;
+
+ public function __construct(Account $account)
+ {
+ $this->account = $account;
+
+ $this->init();
+ }
+
+ /**
+ * Inizializza il ->inprovider per l'autenticazione OAuth2.
+ */
+ public function init()
+ {
+ $redirect_uri = base_url().'/oauth2.php';
+
+ $class = $this->getProviderConfiguration()['class'];
+
+ // Authorization
+ $this->provider = new $class([
+ 'clientId' => $this->account->client_id,
+ 'clientSecret' => $this->account->client_secret,
+ 'redirectUri' => $redirect_uri,
+ ]);
+
+ // Configurazioni specifiche per il provider di Microsoft Azure
+ if ($this->provider instanceof Azure) {
+ $this->provider->defaultEndPointVersion = Azure::ENDPOINT_VERSION_2_0;
+ $this->provider->tenant = 'consumers';
+ }
+ }
+
+ public function getProvider()
+ {
+ return $this->provider;
+ }
+
+ public function getProviderConfiguration()
+ {
+ return self::$providers[$this->account->provider];
+ }
+
+ public function needsConfiguration()
+ {
+ $access_token = $this->getAccessToken();
+
+ return empty($access_token);
+ }
+
+ /**
+ * Gestisce le operazioni di configurazione per l'autenticazione OAuth2.
+ * Restituisce l'URL di redirect per le operazioni di aggiornamento dei dati, lancia un eccezione in caso di errori e restituisce null in caso di completamento della configurazione.
+ *
+ * Nota: l'autenticazione OAuth2 richiede una serie di richieste su una singola pagina
+ * - Richiesta di autenticazione al server remoto (code, state vuoti)
+ * - Conferma di autenticazione alla pagina di redirect (code, state impostati)
+ * - Richiesta del token di accesso dalla pagina di redirect al server remoto
+ *
+ * @param string|null $code
+ * @param string|null $state
+ *
+ * @throws IdentityProviderException
+ * @throws InvalidArgumentException
+ *
+ * @return string|null
+ */
+ public function configure($code, $state)
+ {
+ if (!$this->needsConfiguration()) {
+ return null;
+ }
+
+ $provider = $this->getProvider();
+ $options = $this->getProviderConfiguration()['options'];
+ if (empty($code)) {
+ // Fetch the authorization URL from the provider; this returns the
+ // urlAuthorize option and generates and applies any necessary parameters
+ // (e.g. state).
+ $authorizationUrl = $provider->getAuthorizationUrl($options);
+
+ // Get the state generated for you and store it to the session.
+ $this->account->oauth2_state = $provider->getState();
+ $this->account->save();
+
+ // Redirect the user to the authorization URL.
+ return $authorizationUrl;
+ } elseif (!empty($this->account->oauth2_state) && $this->account->oauth2_state !== $state) {
+ $this->account->oauth2_state = null;
+ $this->account->save();
+
+ throw new InvalidArgumentException();
+ } else {
+ $this->account->oauth2_state = null;
+ $this->account->save();
+
+ // Try to get an access token using the authorization code grant.
+ $accessToken = $provider->getAccessToken('authorization_code', [
+ 'code' => $code,
+ ]);
+ //dd($accessToken);
+
+ $this->setAccessToken($accessToken);
+ }
+
+ return null;
+ }
+
+ /**
+ * Imposta l'access token per l'autenticazione OAuth2.
+ *
+ * @param AccessToken|null
+ */
+ public function setAccessToken($value)
+ {
+ $this->account->access_token = serialize($value);
+ $this->account->save();
+ }
+
+ /**
+ * Restituisce l'access token per l'autenticazione OAuth2.
+ *
+ * @return AccessToken|null
+ */
+ public function getAccessToken()
+ {
+ $access_token = unserialize($this->account->access_token);
+
+ if (!empty($access_token) && $access_token->hasExpired()) {
+ // Tentativo di refresh del token di accessp
+ if (!empty($access_token->getRefreshToken())) {
+ $access_token = $this->getProvider()->getAccessToken('refresh_token', [
+ 'refresh_token' => $access_token->getRefreshToken(),
+ ]);
+ } else {
+ $access_token = null;
+ }
+
+ $this->setAccessToken($access_token);
+ }
+
+ return $access_token;
+ }
+
+ public function getRefreshToken()
+ {
+ $access_token = unserialize($this->account->access_token);
+
+ if (!empty($access_token)) {
+ return $access_token->getRefreshToken();
+ }
+
+ return null;
+ }
+}
diff --git a/modules/smtp/actions.php b/modules/smtp/actions.php
index 184f4cde4..1aa63b1a9 100755
--- a/modules/smtp/actions.php
+++ b/modules/smtp/actions.php
@@ -19,7 +19,7 @@
include_once __DIR__.'/../../core.php';
-switch (post('op')) {
+switch (filter('op')) {
case 'add':
$dbo->insert('em_accounts', [
'name' => post('name'),
@@ -39,6 +39,8 @@ switch (post('op')) {
$dbo->query('UPDATE em_accounts SET predefined = 0');
}
+ $abilita_oauth2 = post('abilita_oauth2');
+
$dbo->update('em_accounts', [
'name' => post('name'),
'note' => post('note'),
@@ -53,6 +55,9 @@ switch (post('op')) {
'timeout' => post('timeout'),
'ssl_no_verify' => post('ssl_no_verify'),
'predefined' => $predefined,
+ 'provider' => $abilita_oauth2 ? post('provider') : null,
+ 'client_id' => $abilita_oauth2 ? post('client_id') : null,
+ 'client_secret' => $abilita_oauth2 ? post('client_secret') : null,
], ['id' => $id_record]);
flash()->info(tr('Informazioni salvate correttamente!'));
@@ -96,5 +101,11 @@ switch (post('op')) {
flash()->info(tr('Account email eliminato!'));
+ break;
+
+ case 'oauth2':
+ $redirect = base_path().'/oauth2.php?id_account='.$account->id;
+ redirect($redirect);
+
break;
}
diff --git a/modules/smtp/edit.php b/modules/smtp/edit.php
index a1f970ccd..fb980e735 100755
--- a/modules/smtp/edit.php
+++ b/modules/smtp/edit.php
@@ -17,9 +17,11 @@
* along with this program. If not, see