Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
1 result

Target

Select target project
  • iml-open-source/mfa-server
1 result
Select Git revision
  • main
1 result
Show changes

Commits on Source 2

......@@ -3,22 +3,15 @@
* mfa-ensure.php
*
* @author Axel Hahn <axel.hahn@unibe>
* @package IML-Appmonitor
*
*/
if(!($_SERVER['REMOTE_USER']??false)){
return true;
}
$aConfig = @include "mfaconfig.php";
if(!($aConfig['api']??false)){
return true;
}
require_once __DIR__.'/mfaclient.class.php';
$mfa = new mfaclient($aConfig, ($_SERVER['REMOTE_USER']??''));
$mfa = new mfaclient();
$mfa->debug($aConfig['debug']??false);
$iHttpStatus=$mfa->ensure();
// mfa was skipped? Enable this line to see the reason
// echo $mfa->showStatus();
\ No newline at end of file
<?php
/**
*
* MFA CLIENT CLASS
*
* Connect a web app with MFA server
*
* Source: https://git-repo.iml.unibe.ch/iml-open-source/
* Docs: https://os-docs.iml.unibe.ch/mfa-client/index.html
* License: GNU GPL 3.0
*
* 2025-06-11 <axel.hahn@unibe.ch> initial version
* 2025-06-30 <axel.hahn@unibe.ch> set version 1.0.1 in user agenmt in http requests
*/
class mfaclient
{
protected string $_sVersion = "1.0.1";
protected array $aConfig = [];
// protected string $sSessionvarname = "mfaclient";
......@@ -13,6 +28,8 @@ class mfaclient
protected bool $bDebug = false;
protected array $aStatus = [];
/**
* Intialize mfa client - optional set config and user
*
......@@ -20,17 +37,14 @@ class mfaclient
* @see setUser
*
* @param array $aConfig optional: configuration with app id and base url
* @param string $sUser optional: user id that was logged in
*/
public function __construct(array $aConfig = [], string $sUser = "")
public function __construct(array $aConfig = [])
{
$this->loadConfig();
if ($aConfig) {
$this->setConfig($aConfig);
}
if ($sUser) {
$this->setUser($sUser);
}
$this->setUser($this->aConfig['user']??'');
}
......@@ -77,7 +91,7 @@ class mfaclient
// }
curl_setopt($ch, CURLOPT_TIMEOUT, $iTimeout);
curl_setopt($ch, CURLOPT_USERAGENT, 'IML MFA client' . __CLASS__);
curl_setopt($ch, CURLOPT_USERAGENT, "IML MFA client PHP v$this->_sVersion");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
......@@ -274,7 +288,6 @@ class mfaclient
if (file_exists($sCfgfile)) {
$aTmp = include $sCfgfile;
$this->aConfig = $aTmp??[];
$this->setUser($aTmp['user']??'');
}
}
/**
......@@ -300,7 +313,8 @@ class mfaclient
}
/**
* Logout
* Logout; unset user in session scope
*
* @return void
*/
public function logout()
......@@ -362,11 +376,24 @@ class mfaclient
session_start();
}
if (($_SESSION['mfa']['user'] ?? '') == $this->sUser) {
$this->aStatus[] = 'User still has a valid session after solving a challenge.';
return 200;
} else {
$this->logout();
}
foreach(['api', 'appid', 'shared_secret', 'user'] as $sKey){
if(!isset($this->aConfig[$sKey])){
$this->aStatus[] = "Skip: Key '$sKey' was not set in config.";
return 200;
}
if(!$this->aConfig[$sKey]){
$this->aStatus[] = "Skip: Key '$sKey' is empty in config.";
return 200;
}
}
$aMfaReturn = $this->check();
$this->_wd(__METHOD__ . "<br>Http request to mfa api<pre>" . print_r($aMfaReturn, 1) . "</pre>");
$aBody = json_decode($aMfaReturn['response']['body'] ?? '', 1);
......@@ -393,6 +420,8 @@ class mfaclient
);
}
$this->aStatus[] = 'User solved the session now.';
$_SESSION['mfa']['user'] = $this->sUser;
session_write_close();
......@@ -403,7 +432,8 @@ class mfaclient
/**
* Get an html button to open mfa setup page
*
* @param string $sSubmitBtn
* @param string $sSubmitBtn optional: html code for a submit button; default: '<button>MFA Setup</button>'
* @param string $sBackUrl optional: url to return from mfa server to the application; default: current url
* @return void
*/
public function getButtonSetup(string $sSubmitBtn = '<button>MFA Setup</button>', $sBackUrl = ''): string
......@@ -412,7 +442,7 @@ class mfaclient
// print_r($aBody);
$sUrl = $aBody['setup'] ?? '';
if ($sUrl) {
$sBackUrl = $sBackUrl ?: $_SERVER['HTTP_REFERER'];
$sBackUrl = $sBackUrl ?: ( "http".(($_SERVER['HTTPS']??'') === 'on' ? "s" : "")."://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
return $this->jumpform($sUrl, $sSubmitBtn, $sBackUrl);
} else {
return $aBody['message']??'';
......@@ -423,10 +453,9 @@ class mfaclient
/**
* Open User settings to setup mfa methods
*
* @param string $sUrl
* @param string $sSubmitBtn
* @param string $sUrl url to open
* @param string $sSubmitBtn html code for a submit button
* @return void
*/
public function openSetup(string $sUrl = '', string $sSubmitBtn = '<button>MFA Setup</button>', $sBackUrl = '')
{
if (!$sUrl) {
......@@ -438,6 +467,7 @@ class mfaclient
$this->_jump($sUrl, $sSubmitBtn, $sBackUrl);
}
}
*/
/**
* Get IP of current client (to be sent to MFA server)
......@@ -464,6 +494,24 @@ class mfaclient
return $ipaddress;
}
/**
* return current config
* @return array
*/
public function getConfig(): array
{
return $this->aConfig;
}
/**
* return current status
* @return array
*/
public function getStatus(): array
{
return $this->aStatus;
}
/**
* get list of urls from MFA server
*
......@@ -474,5 +522,16 @@ class mfaclient
return $this->_api("urls");
}
/**
* show current status if you want to find out why mfa was skipped
* @example <code>echo $mfa->showStatus();</code>
* @return string
*/
public function showStatus(): string
{
return 'MFA status: <ul><li>'
. implode('</li><li>', $this->aStatus)
.'</li></ul>'
;
}
}
......@@ -87,7 +87,8 @@ switch ($sAction) {
// $aConfig = include "classes/mfaconfig.php";
// $sOut.="Config:<pre>".print_r($aConfig,1)."</pre>";
$mfa = new mfaclient([], $sUser);
$mfa = new mfaclient();
$mfa->setUser($sUser);
// $aMfaReturn=$mfa->startMfa();
$aMfaReturn=$mfa->check();
......