Conditional Two Factor Authentication (v2023)

This public forum is for user-to-user discussions of PHPMaker. Note that this is not support forum.
Post Reply
philmills
User
Posts: 556

Conditional Two Factor Authentication (v2023)

Post by philmills »

I'm using 2FA for logins, but I need to have it enabled only when accessing the site from non-trusted IPs
I already had been doing this for CAPTCHA using the following code in globals:

//Disable reCaptcha for locally hosted servers
$localIPs="xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxy, xxx.xxx.xxx.xxz";
$externalIPs="xxx.xxx.xxx.abc, xxx.xxx.xxx.def";
if (strpos($localIPs,$_SERVER['SERVER_ADDR'])>0 || strpos($externalIPs,$_SERVER['REMOTE_ADDR'])>0) { // check if allowed local IP without recaptcha
$CaptchaClass = "CaptchaBase"; /// Without Recaptcha
}

2FA is part of the AUTH_CONFIG section, and the syntax is different.
How can I oveeride only these in Globals with false values?

"USE_TWO_FACTOR_AUTHENTICATION" => true,
"FORCE_TWO_FACTOR_AUTHENTICATION" => true,

arbei
User
Posts: 9384

Post by arbei »

You may generate another version of your project without 2FA, then compare the two version and find out the differences, and see if you can make the changes by server events.


philmills
User
Posts: 556

Post by philmills »

yes that's what I was thinking. I may generate two config files, one with and one without 2FA, rename them, then php include one or the other based on IP address.


philmills
User
Posts: 556

Post by philmills »

I've had this working for a while now... this was the code placed in globals:

/Bypass 2FA for trusted networks
//get external IPs
// Sanitize user input (user's IP address)
$conn = Conn();
$userIp = $_SERVER['REMOTE_ADDR'];
// Sanitize user input (user's IP address)
$userIp = $conn->quote($userIp);
// Construct the SQL query
$query = "SELECT IP FROM ClassAct_Trusted_IPs WHERE IP = $userIp";
// Execute the query
$result = $conn->executeQuery($query);
// Check the result and configure 2FA accordingly
$row = $result->fetchAssociative();
if (!empty($row)) {
    Config("USE_TWO_FACTOR_AUTHENTICATION", false);
    Config("FORCE_TWO_FACTOR_AUTHENTICATION", false);
	session_start();
	$_SESSION['redirme'] = 'trust'.time();
} else {
    Config("USE_TWO_FACTOR_AUTHENTICATION", true);
    Config("FORCE_TWO_FACTOR_AUTHENTICATION", true);
}
//End 2FA bypass

I don't like the fact that it's in globals (doesn't seem right) and it's not within a function, but also now I need to be able to bypass 2FA for certain users.
My site has a few demo accounts which mustn't request a security code at login.
So I'm trying to figure out way around that.
I have tried a few things and got it accidentally working only once.
Essentially, I'd need to throw the username into a session on first click of the Login button, and there would have to be some code in page_Load server event for the logon page.
So I deally I'm trying to adapt the code above to include username session checking.

I there a session already set on submit of the login form which I could use?
Or is there a simpler way to achieve what I'm looking for?


arbei
User
Posts: 9384

Post by arbei »

You may try to use User_CustomValidate server event to check the user name and change the config settings.


philmills
User
Posts: 556

Post by philmills »

What is the variable that is passed as username during login?
"username" ?


arbei
User
Posts: 9384

Post by arbei »


ethanlazarus
User
Posts: 63

Post by ethanlazarus »

Hi there - I'm working on this exact same thing. Did you figure out a way to dynamically enable and disable 2FA? I'd like to have it disabled on the local network, and enabled for people on outside ip addresses.

Anybody know - would it be possible to have conditional 2FA with SMS?

What I'd like to do is this - if person is on the local network, no 2FA. If outside the local network require 2FA.

Anybody know how to do this? Thanks!


ethanlazarus
User
Posts: 63

Post by ethanlazarus »

Been trying this out with the code above - I can get it to bypass the sms validation by placing you two lines of code in User_CustomValidate:

Config("USE_TWO_FACTOR_AUTHENTICATION", false);
Config("FORCE_TWO_FACTOR_AUTHENTICATION", false);

However, the system freezes, and I have to refresh the screen. Session Start, or even a meta redirect doesn't work. How can I make it proceed after setting the two Config lines so the user doesn't have to refresh the screen?

I think I'm close. Thanks.


arbei
User
Posts: 9384

Post by arbei »

You may use Page_Redirecting server event to check if the user is authenticated and set $this->IsModal = true; to simulate JSON response originally for 2FA.


ethanlazarus
User
Posts: 63

Post by ethanlazarus »

Yes - that works. Thanks very much!


philmills
User
Posts: 556

Post by philmills »

Can you post details exactly how? What does your Page_Redirecting look like now?


ethanlazarus
User
Posts: 63

Post by ethanlazarus »

sorry for delay.
note I replaced my local Ip addresses with xxx.

this is returning an error if login or password is wrong so I will continue to tweak, but this is the basic idea:

in login page, Page_Redirecting event:

    if ((isset($_SESSION['user_validated'])) && ($_SESSION['user_validated']))
    {
      $this->IsModal = true;
      $url = "Appointments";
    }

in global code, User_CustomValidate event:

$userIp = explode(".",$_SERVER['REMOTE_ADDR']); 

$isLocal = 0;

if (     ($userIp[0] == "::x")  || 
         ($userIp[0] == "xx") ||
         ($userIp[0] == "xxx")     )
              $isLocal = 1;

if ($isLocal)
{
   Config("USE_TWO_FACTOR_AUTHENTICATION", false);
   Config("FORCE_TWO_FACTOR_AUTHENTICATION", false);
   if (session_status() === PHP_SESSION_NONE)
         session_start();
   $_SESSION['user_validated'] = 1;
}

ethanlazarus
User
Posts: 63

Post by ethanlazarus »

Adding this above the previous post fixes redirect problems when wrong password:

//check if valid usr and pwd
$_SESSION['valid_login'] = 0;

$query = "SELECT password FROM staffinfo WHERE login = '".addslashes($usr)."'";
$password = ExecuteScalar($query);

if ($password == md5($pwd)) $_SESSION['valid_login'] = 1;
else $_SESSION['valid_login'] = 0;

if (!$_SESSION['valid_login']) RETURN FALSE;

Post Reply