Gestione login tramite Microsoft

This commit is contained in:
MatteoPistorello 2024-01-26 17:00:02 +01:00
parent 9c1d3a0ed7
commit 9e2b76ffdf
12 changed files with 318 additions and 9 deletions

View File

@ -161,6 +161,9 @@ echo '
if (isset($username)) {
echo ' value="'.$username.'"';
}
$microsoft = $dbo->selectOne('zz_oauth2', '*', ['nome' => 'Microsoft', 'enabled' => 1, 'is_login' => 1]);
echo ' required>
<span class="form-control-feedback"><i class="fa fa-user"></i> </span>
</div>
@ -171,7 +174,17 @@ echo ' required>
<button type="submit" class="btn btn-danger btn-block btn-flat">'.tr('Accedi').'</button>
<br>
<p><a href="'.base_path().'/reset.php">'.tr('Password dimenticata?').'</a></p>
<p><a href="'.base_path().'/reset.php">'.tr('Password dimenticata?').'</a></p>';
if ($microsoft) {
echo '
<div class="social-auth-links text-center">
<p>- oppure -</p>
<a href="'.base_path().'/oauth2_login.php?id='.$microsoft['id'].'" class="btn btn-block btn-social btn-primary btn-flat"><i class="fa fa-windows"></i>'.tr('Accedi con Microsoft').'</a>
</div>';
}
echo '
</div>
</div>
</form>
<!-- /.box -->

View File

@ -11,6 +11,16 @@ class Google extends OriginalProvider implements ProviderInterface
'accessType' => 'offline',
];
public function __construct(array $options = [], array $collaborators = [])
{
// Configurazioni specifiche per il provider di Microsoft Azure
$config = array_merge($options, [
'redirectUri' => base_url().'/oauth2.php',
]);
parent::__construct($config, $collaborators);
}
public function getOptions()
{
return self::$options;

View File

@ -21,6 +21,7 @@ class Microsoft extends Azure implements ProviderInterface
'https://outlook.office.com/SMTP.Send',
// 'https://outlook.office.com/IMAP.AccessAsUser.All'
],
'accessType' => 'offline'
];
public function __construct(array $options = [], array $collaborators = [])
@ -29,6 +30,7 @@ class Microsoft extends Azure implements ProviderInterface
$config = array_merge($options, [
'defaultEndPointVersion' => parent::ENDPOINT_VERSION_2_0,
'tenant' => $options['tenant_id'],
'redirectUri' => base_url().'/oauth2.php',
]);
parent::__construct($config, $collaborators);

View File

@ -0,0 +1,54 @@
<?php
namespace Modules\Emails\OAuth2;
use TheNetworg\OAuth2\Client\Provider\Azure;
class MicrosoftLogin extends Azure implements ProviderInterface
{
/**
* Impostazioni native per la connessione.
*
*
* @var \string[][]
*/
protected static $options = [
'scope' => [
'https://graph.microsoft.com/User.Read',
],
];
public function __construct(array $options = [], array $collaborators = [])
{
// Configurazioni specifiche per il provider di Microsoft Azure
$config = array_merge($options, [
'defaultEndPointVersion' => parent::ENDPOINT_VERSION_2_0,
'tenant' => $options['tenant_id'],
'redirectUri' => base_url().'/oauth2_login.php',
]);
parent::__construct($config, $collaborators);
}
public function getOptions()
{
return self::$options;
}
public static function getConfigInputs()
{
return [
'tenant_id' => [
'label' => 'Tenant ID',
'type' => 'text',
],
];
}
public function getUser($access_token)
{
$me = $this->get('https://graph.microsoft.com/v1.0/me', $access_token);
return $me['mail'];
}
}

34
modules/oauth/actions.php Normal file
View File

@ -0,0 +1,34 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
include_once __DIR__.'/../../core.php';
switch (filter('op')) {
case 'update':
$dbo->update('zz_oauth2', [
'client_id' => post('client_id'),
'client_secret' => post('client_secret'),
'config' => post('config'),
'enabled' => post('enabled'),
], ['id' => $id_record]);
flash()->info(tr('Salvataggio completato!'));
break;
}

67
modules/oauth/edit.php Normal file
View File

@ -0,0 +1,67 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
include_once __DIR__.'/../../core.php';
?><form action="" method="post" id="edit-form">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="op" value="update">
<!-- DATI -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><?php echo tr('OAuth2'); ?></h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "<?php echo tr('Nome'); ?>", "name": "nome", "value": "$nome$", "disabled": "1" ]}
</div>
<div class="col-md-6">
{[ "type": "checkbox", "label": "<?php echo tr('Abilita'); ?>", "name": "enabled", "value": "$enabled$" ]}
</div>
</div>
<div class="row">
<div class="col-md-4">
{[ "type": "text", "label": "<?php echo tr('Client ID'); ?>", "name": "client_id", "value": "$client_id$" ]}
</div>
<div class="col-md-4">
{[ "type": "text", "label": "<?php echo tr('Client Secret'); ?>", "name": "client_secret", "value": "$client_secret$" ]}
</div>
<?php
$config = $record['class']::getConfigInputs();
foreach ($config as $name => $field) {
$field['name'] = 'config['.$name.']';
$field['value'] = $oauth2->config[$name];
echo '
<div class="col-md-4">
'.input($field).'
</div>';
}
?>
</div>
</div>
</div>
</form>

29
modules/oauth/init.php Normal file
View File

@ -0,0 +1,29 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\OAuth2;
include_once __DIR__.'/../../core.php';
if (isset($id_record)) {
$record = $dbo->fetchOne('SELECT * FROM `zz_oauth2` WHERE id='.prepare($id_record));
$oauth2 = OAuth2::find($id_record);
$a=0;
}

View File

@ -47,11 +47,13 @@ if (empty($account)) {
}
// Redirect all'URL di autorizzazione del servizio esterno
$redirect = $account->configure($code, $state);
$response = $account->configure($code, $state);
// Redirect automatico al record
if (empty($redirect)) {
if (empty($response['authorization_url'])) {
$redirect = $account->after_configuration;
} else {
$redirect = $response['authorization_url'];
}
if (empty($_GET['error'])) {

76
oauth2_login.php Normal file
View File

@ -0,0 +1,76 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\OAuth2;
$skip_permissions = true;
include_once __DIR__.'/core.php';
// Authorization information
$state = $_GET['state'];
$code = $_GET['code'];
// Account individuato via state
if (!empty($state)) {
$account = OAuth2::where('state', '=', $state)
->first();
} else {
$account = OAuth2::find(get('id'));
// Impostazione access token a null per reimpostare la configurazione
$account->access_token = null;
$account->refresh_token = null;
$account->save();
}
if (empty($account)) {
echo tr('Errore durante il completamento della configurazione: account non trovato');
return;
}
// Redirect all'URL di autorizzazione del servizio esterno
$response = $account->configure($code, $state);
// Redirect automatico al record
if (empty($response['authorization_url'])) {
$redirect = $account->after_configuration;
} else {
$redirect = $response['authorization_url'];
}
if (empty($_GET['error'])) {
if ($response['access_token']) {
$username = $account->getProvider()->getUser($response['access_token']);
if (!auth()->attempt($username, null, true)) {
flash()->error(tr('Autenticazione fallita!'));
}
redirect(base_path());
} else {
redirect($redirect);
}
exit;
} else {
echo strip_tags($_GET['error']).'<br>'.strip_tags($_GET['error_description']).'
<br><br>
<a href="'.$redirect.'">'.tr('Riprova').'</a>';
}

View File

@ -101,10 +101,11 @@ class Auth extends Util\Singleton
*
* @param string $username
* @param string $password
* @param bool $force Forza il login solo tramite username (serve per l'autenticazione con Oauth2)
*
* @return bool
*/
public function attempt($username, $password)
public function attempt($username, $password, $force = false)
{
session_regenerate_id();
@ -134,7 +135,14 @@ class Auth extends Util\Singleton
$module = $gruppo['id_module_start'];
$module = $this->getFirstModule($module);
if (
if ($force) {
// Accesso completato
$log['id_utente'] = $this->user->id;
$status = 'success';
// Salvataggio nella sessione
$this->saveToSession();
} elseif (
$this->isAuthenticated()
&& $this->password_check($password, $user['password'], $user['id'])
&& !empty($module)

View File

@ -47,9 +47,7 @@ class OAuth2 extends Model
$config = $this->config ?? [];
$config = array_merge($config, [
'clientId' => $this->client_id,
'clientSecret' => $this->client_secret,
'redirectUri' => base_url().'/oauth2.php',
'accessType' => 'offline',
'clientSecret' => $this->client_secret
]);
$class = $this->class;
@ -106,7 +104,7 @@ class OAuth2 extends Model
$this->save();
// Redirect the user to the authorization URL.
return $authorization_url;
return ['authorization_url' => $authorization_url];
} elseif (!empty($this->state) && $this->state !== $state) {
$this->state = null;
$this->save();
@ -123,6 +121,8 @@ class OAuth2 extends Model
$refresh_token = $access_token->getRefreshToken();
$this->updateTokens($access_token, $refresh_token);
return ['access_token' => $access_token];
}
return null;

View File

@ -11,3 +11,17 @@ INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `slow`,
INSERT INTO `zz_views` (`id`, `id_module`, `name`, `query`, `order`, `search`, `slow`, `format`, `html_format`, `search_inside`, `order_by`, `visible`, `summable`, `default`) VALUES (NULL, (SELECT `id` FROM `zz_modules` WHERE `name` = 'Utenti e permessi'), 'Tema', '`zz_groups`.`theme`', '4', '1', '0', '0', '0', '', '', '1', '0', '0');
-- Creazione modulo Login
INSERT INTO `zz_modules` (`id`, `name`, `title`, `directory`, `options`, `options2`, `icon`, `version`, `compatibility`, `order`, `parent`, `default`, `enabled`, `use_notes`, `use_checklists`) VALUES (NULL, 'Accesso con OAuth', 'Accesso con OAuth', 'oauth', 'SELECT |select| FROM zz_oauth2 WHERE 1=1 AND is_login=1 HAVING 2=2', '', 'fa fa-angle-right', '1.0', '2.4.54', '100', (SELECT `t`.`id` FROM `zz_modules` AS `t` WHERE `t`.`name` = 'Tabelle'), '1', '1', '0', '0');
ALTER TABLE `zz_oauth2` ADD `nome` VARCHAR(255) NOT NULL AFTER `id`;
ALTER TABLE `zz_oauth2` ADD `is_login` BOOLEAN NOT NULL AFTER `after_configuration`;
ALTER TABLE `zz_oauth2` ADD `enabled` BOOLEAN NOT NULL DEFAULT TRUE AFTER `is_login`;
-- Viste modulo Oauth
INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `slow`, `format`, `search_inside`, `order_by`, `visible`, `summable`, `default`) VALUES
((SELECT `id` FROM `zz_modules` WHERE name='Accesso con OAuth'), 'id', 'id', 0, 1, 0, 0, '', '', 0, 0, 0),
((SELECT `id` FROM `zz_modules` WHERE name='Accesso con OAuth'), 'Nome', 'nome', 1, 1, 0, 0, '', '', 1, 0, 0);
INSERT INTO `zz_oauth2` (`nome`, `class`, `client_id`, `client_secret`, `config`, `state`, `access_token`, `refresh_token`, `after_configuration`, `is_login`, `enabled`) VALUES
('Microsoft', 'Modules\\Emails\\OAuth2\\MicrosoftLogin', '', '', '{\"tenant_id\":\"consumers\"}', '', NULL, NULL, '', 1, 0);