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
No results found
Select Git revision
  • main
1 result
Show changes

Commits on Source 7

11 files
+ 107
36
Compare changes
  • Side-by-side
  • Inline

Files

Original line number Diff line number Diff line
@@ -21,8 +21,8 @@ return [
    "delete" => "Löschen",
    "edit" => "Bearbeiten",
    "help" => "Hilfe (en)",
    "no-data" => "No data available",
    "none" => "None",
    "no-data" => "Keine Daten vorhanden",
    "none" => "Keine",
    "reset" => "Zurücksetzen",
    "test" => "Testen",
    "view" => "Ansehen",
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@ return [
    "delete" => "Delete",
    "edit" => "Edit",
    "help" => "Help",
    "no-data" => "Keine Daten vorhanden",
    "none" => "Keine",
    "no-data" => "No data available",
    "none" => "None",
    "reset" => "Reset",
    "test" => "Test",
    "view" => "View",
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
<?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>'
            ;
    }
}
Original line number Diff line number Diff line
@@ -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();

Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ $sTplPage = file_get_contents('config/page_tpl.html');

$aReplacements = [
    '{{TITLE}}' => 'MFA Server',
    '{{VERSION}}' => 'v0.21',
    '{{VERSION}}' => 'v0.22',
    '{{APP}}' => '',
    '{{NAV}}' => '',
    '{{LANG}}' => '',
Original line number Diff line number Diff line
@@ -17,6 +17,24 @@ function getQueryParams() {
    return params;
}

/**
 * Hook on code input fields.
 * It submits a form after entering N chars or return key
 * 
 * @param {object}  oField  object of input field (this)
 * @param {int}     iSize   optional: size of code; default: 6
 */
function hookEnterCode(oField, iSize=6){
	var sCode=oField.value;
	if(sCode.length==iSize){
		oField.form.submit();
	}
	if (window.keyCode == 13) {
		oField.form.submit();
	}
}


/**
 * Apply search filter on a table
 * 
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ $CONTENT.="
    <form method=\"post\" class=\"pure-form\" action=\"$sPostUrl\">
    <fieldset>
        <input type=\"hidden\" name=\"action\" value=\"verify\">
        <input type=\"text\" class=\"big\" name=\"code\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
        <input type=\"text\" class=\"big\" name=\"code\" onkeyup=\"hookEnterCode(this,6);\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
        <br>
        <button class=\"pure-button button-primary\" >{{ico.send}} {{send}}</button>
        </fieldset>
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ $CONTENT.="
    <form method=\"post\" class=\"pure-form\" action=\"".$_SERVER['REQUEST_URI']."\">
    <fieldset>
        <input type=\"hidden\" name=\"action\" value=\"verify\">
        <input type=\"text\" class=\"big\" name=\"code\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
        <input type=\"text\" class=\"big\" name=\"code\" onkeyup=\"hookEnterCode(this,6);\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
        <br>
        <button class=\"pure-button button-primary\" >{{ico.send}} {{send}}</button>
        </fieldset>
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ if(count($_POST)){

                <form method=\"post\" class=\"pure-form\" action=\"".$_SERVER['REQUEST_URI']."\">
                    <input type=\"hidden\" name=\"action\" value=\"verify-code\">
                    <input type=\"text\" class=\"big\" name=\"code\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
                    <input type=\"text\" class=\"big\" name=\"code\" onkeyup=\"hookEnterCode(this,6);\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
                    <br>
                    <button class=\"pure-button\" onclick=\"history.back();\">{{ico.back}} {{back}}</button>
                    <button class=\"pure-button button-primary\" >{{ico.send}} {{send}}</button>
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ switch ($sAction) {
    // ----- dialog to setup a new TOTP secret
    case "create":

        $sInstance=$oApp->getLabel().' ('.$oApp->getUrl().')';
        $sInstance=$oApp->getLabel().' ('.parse_url($oApp->getUrl(), PHP_URL_HOST).')';
        $sUser=$oUser->getId();

        // TODO: Issuer from config
@@ -146,7 +146,7 @@ switch ($sAction) {
                    <form method=\"post\" class=\"pure-form\" action=\"".$_SERVER['REQUEST_URI']."\">
                        <input type=\"hidden\" name=\"action\" value=\"verify\">
                        <input type=\"hidden\" name=\"secret\" value=\"$sSecret\">
                        <input type=\"text\" class=\"big\" name=\"code\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
                        <input type=\"text\" class=\"big\" name=\"code\" onkeyup=\"hookEnterCode(this,6);\" value=\"\" autofocus required size=\"8\" placeholder=\"123456\"><br>
                        <br>
                        <button class=\"pure-button\" onclick=\"history.back();\">{{ico.back}} {{back}}</button>
                        <button class=\"pure-button button-primary\" >{{ico.send}} {{send}}</button>