TOTP : improve email and fix small bug

This commit is contained in:
sparkyx 2025-08-05 11:56:36 +02:00
parent 4d0325438b
commit 645bc207e1
9 changed files with 49 additions and 27 deletions

View file

@ -36,7 +36,10 @@ if (defined('MULTI') && MULTI == 0)
$version = $rep->get_value('select val from version');
$http=new HttpInput();
/**
* If p_user is set , it means that the user tries to connect, the $_SESSION
* does not exist yet
*/
if ( isset ($_POST["p_user"] ) )
{
$http=new HttpInput();
@ -116,6 +119,9 @@ if ( isset ($_POST["p_user"] ) )
}
else
{
/**
* User has a session
*/
$rep=new Database();
/*
@ -160,6 +166,9 @@ else
}
$otp_send_secret = new Otp_Send_Secret_SQL($rep, $os_id);
/**
* second code is valid, so delete it
*/
if (
$vrf_code == $otp_send_secret->get('os_code')
|| $User->check_otp($vrf_code)
@ -172,6 +181,7 @@ else
// check that backurl is valid
$backurl=preg_replace('/^.*\?/','',$backurl);
$backurl=NOALYSS_URL."/do.php?$backurl";
$otp_send_secret->delete();
}
header("Location: $backurl");
return;

View file

@ -160,12 +160,10 @@ class Dossier
from ac_dossier as ds
join jnt_use_dos as jt on (jt.dos_id=ds.dos_id)
group by jt.use_id) as dossier_name on (jt_use_id=ac.use_id)
where
use_login!=$1
$sql
";
$res=$this->cn->get_array($sql, array(NOALYSS_ADMINISTRATOR));
$res=$this->cn->get_array($sql);
return $res;
}

View file

@ -1966,13 +1966,13 @@ Voici votre code secret pour NOALYSS : $code
$uuid= guidv4();
$repository=new \Database();
// remove old for this user
$repository->exec_sql("delete from otp_send_secret where use_id=$1"
$repository->exec_sql("delete from otp_send_secret where use_id=$1 and os_code is not null"
,[$this->id]);
// remove also old one
$repository->exec_sql("delete from otp_send_secret where os_valid_time < now()");
$now=new \DateTime();
$valid=new \DateTime();
$valid->modify('+20 minutes');
$valid->modify('+10 minutes');
$otp_send_secret=new Otp_Send_Secret_SQL($repository);
$otp_send_secret->set("use_id",$this->id)
@ -2000,6 +2000,9 @@ Voici votre code secret pour NOALYSS : $code
$noalyss_url = NOALYSS_URL;
$uuid = guidv4();
$id = $this->getId();
$valid_time=new \DateTime();
$valid_time->add(new \DateInterval('PT12H'));
$str_time=$valid_time->format('d-m-Y H:i');
/**
* save in DB first
*/
@ -2008,7 +2011,7 @@ Voici votre code secret pour NOALYSS : $code
Afin de pouvoir utiliser la double authentification avec 2FA: OTP, pourriez-vous
suivre ce lien et scanner le QRCode avec votre application android freeOTP ou Google Authenticator.
Ce lien ne sera actif que 12 heures.
Ce lien ne sera actif que 12 heures et expirera le {$str_time}.
{$noalyss_url}/index.php?otp={$uuid}
@ -2022,12 +2025,11 @@ Bien cordialement,
try {
$repository = new \Database();
// remove old for this user
$repository->exec_sql("delete from otp_send_secret where use_id=$1"
$repository->exec_sql("delete from otp_send_secret where use_id=$1 and os_code is null"
,[$this->id]);
// remove also old one
$repository->exec_sql("delete from otp_send_secret where os_valid_time < now()");
$valid_time=new \DateTime();
$valid_time->add(new \DateInterval('PT12H'));
$otp_send_secret_sql = new \Otp_Send_Secret_SQL($repository);
$otp_send_secret_sql->set('use_id', $id)
->set('os_valid_time',$valid_time->format('d-m-Y H:i'))

View file

@ -69,5 +69,14 @@ class OTP {
$this->authenticator->setSecret($secret);
return $this->authenticator->code();
}
public function get_authenticator() {
return $this->authenticator;
}
public function set_authenticator($authenticator) {
$this->authenticator = $authenticator;
return $this;
}
}

View file

@ -142,13 +142,14 @@ try {
$uuid = $http->get('otp');
$repository = new \Database(0);
// remove old request (> 24 hours)
$repository->exec_sql("delete from otp_send_secret where os_timestamp < now()-interval '24 hours'");
$repository->exec_sql("delete from otp_send_secret where os_timestamp < now()-interval '12 hours'");
// check if UUID exist
$id = $repository->get_value("select os_id from otp_send_secret where os_request=$1",
[$uuid]);
// if UUID doesn't exist exit
if ($repository->count() == 0) {
echo _("Expiré : vous devez redemander le renvoi de la clef");
return;
}
@ -158,13 +159,10 @@ try {
$secret = $user->get_otp_secret();
// OTP
$options = new AuthenticatorOptions;
$options->secret_length = 32;
$options->algorithm = AuthenticatorInterface::ALGO_SHA512;
$options->digits=6;
$authenticator = new Authenticator($options);
$authenticator->setSecret($secret);
$data= $authenticator->getUri(label:"noalyss:".$user->getEmail(),issuer:"noalyss.eu");
$authenticator = new \Noalyss\OTP();
$authenticator->get_authenticator()->setSecret($secret);
$data= $authenticator->get_authenticator()->getUri(label:"noalyss:".$user->getEmail(),issuer:"noalyss.eu");
// load secret for this id
//echo "use with php -S localhost:5000 puis ouvrir index.html ";
$writer = new PngWriter();

View file

@ -17,8 +17,7 @@ CREATE TABLE public.otp_send_secret (
use_id int4 NOT NULL, -- FK to ac_users
os_code varchar(8) NULL,
os_valid_time timestamp NOT NULL,
CONSTRAINT otp_send_secret_pk PRIMARY KEY (os_id),
CONSTRAINT otp_send_secret_unique UNIQUE (use_id)
CONSTRAINT otp_send_secret_pk PRIMARY KEY (os_id)
);
COMMENT ON TABLE public.otp_send_secret IS 'sent to user for scanning a QRCODE for FreeOTP
or digit to connect, depends of ac_users use_auth_method.';

View file

@ -142,8 +142,8 @@ form {
Rafraichissez la page pour recevoir un nouveau code.
</p>
<FORM method="post" action="login.php" >
<input type="text" placeholder="999999" id="vrf_code" name="vrf_code" autocomplete="off">
<input type="hidden" name="auth" value="to_validate">
<input type="text" placeholder="999999" id="vrf_code" name="vrf_code" autocomplete="off" autofocus>
<input type="hidden" name="auth" value="to_validate" >
<?=$str?>
<input type="hidden" name="backurl" value="<?=$url?>">
<p>

View file

@ -172,6 +172,12 @@ else if ($sbaction == "delete")
}
if ( $code != $ctl_code) {
echo_warning (_("Code invalide, effacement refusé"));
require_once NOALYSS_INCLUDE.'/user_detail.inc.php';
return;
}
if ($uid == 1) {
echo_warning(_("Administrateur ne peut pas être effacé"));
require_once NOALYSS_INCLUDE.'/user_detail.inc.php';
return;
}
$cn = new Database();
@ -301,7 +307,7 @@ if ( !empty ($a_user) )
echo '<th>'.$header->get_header(2).'</th>';
echo '<th>'.$header->get_header(4).'</th>';
echo "<th>"._('Type')."</th>";
echo '<th>'.$header->get_header(2).'</th>';
echo '<th>'.$header->get_header(3).'</th>';
echo '</tr>';
$a_auth=[0=>_("Mot de passe"),1=>'Email et OTP',2=>'OTP'];

View file

@ -126,8 +126,8 @@ $it_pass->value="";
$auth_method=new ISelect('auth_method');
$auth_method->value=array(
array('value'=>0,'label'=>_('Aucune')),
array('value'=>1,'label'=>_('email + OTP')),
array('value'=>2,'label'=>_('OTP')),
array('value'=>1,'label'=>_('Mot de passe et code par courriel (ou TOTP) ')),
array('value'=>2,'label'=>_('Mot de passe et TOTP')),
);
$auth_method->selected=$UserChange->authent_method;
echo $auth_method->input();
@ -144,7 +144,7 @@ $it_pass->value="";
</span>
<span style="display:block">
<input type="checkbox" name="email_otp" value="1"><?=_("envoyer email pour 2FA avec OTP ")?>
<span class="text-muted"><?=_("Un email sera envoyé avec un lien pour initialiser 2FA avec OTP")?>>
<span class="text-muted"> <?=_("Un email sera envoyé avec un lien pour initialiser 2FA avec OTP")?>
</span>
</td>