Skip to content
Snippets Groups Projects
Commit 0090982e authored by Dominik Baránek's avatar Dominik Baránek
Browse files

feat: timeout dialog

parent 34e0b459
No related branches found
No related tags found
1 merge request!28feat: timeout dialog
...@@ -105,4 +105,14 @@ $config = [ ...@@ -105,4 +105,14 @@ $config = [
'cs' => 'Čeština', 'cs' => 'Čeština',
'en' => 'English', 'en' => 'English',
], ],
'timeout_dialog' => [
'ldap.hostname' => '',
'ldap.username' => '',
'ldap.password' => '',
'ldap.basedn' => '',
'ldap.timeout' => 0,
// 'refresh.dialog.timeout' => 5 * 60,
// 'identifier.attr.name' => 'OIDCClientID',
// 'url.attr.name' => 'rploginurl',
],
]; ];
...@@ -11,8 +11,10 @@ use SimpleSAML\Auth\State; ...@@ -11,8 +11,10 @@ use SimpleSAML\Auth\State;
use SimpleSAML\Configuration; use SimpleSAML\Configuration;
use SimpleSAML\Error; use SimpleSAML\Error;
use SimpleSAML\Error\UnserializableException; use SimpleSAML\Error\UnserializableException;
use SimpleSAML\Logger;
use SimpleSAML\Module; use SimpleSAML\Module;
use SimpleSAML\Module\core\Auth\UserPassBase; use SimpleSAML\Module\core\Auth\UserPassBase;
use SimpleSAML\Module\ldap\Auth\Ldap;
use SimpleSAML\Session; use SimpleSAML\Session;
use SimpleSAML\Utils; use SimpleSAML\Utils;
use Transliterator; use Transliterator;
...@@ -385,6 +387,69 @@ class Campusidp extends Source ...@@ -385,6 +387,69 @@ class Campusidp extends Source
return $filteredMetadata; return $filteredMetadata;
} }
/**
* @deprecated
*/
public static function useLoginURL($state, $config, $restartUrl)
{
$queryVarsStr = parse_url($state['saml:RelayState'], PHP_URL_QUERY);
if ($queryVarsStr) {
parse_str($queryVarsStr, $queryVars);
if (!empty($queryVars['client_id'])) {
$OIDCClientID = $queryVars['client_id'];
$OIDCLoginURL = self::getLoginURL($config, $OIDCClientID);
if ($OIDCLoginURL) {
$restartUrl = $OIDCLoginURL;
}
}
}
return $restartUrl;
}
/**
* @deprecated
*/
public static function getLoginURL($config, $clientId)
{
$hostname = $config->getString('ldap.hostname');
$port = $config->getInteger('ldap.port', 389);
$enable_tls = $config->getBoolean('ldap.enable_tls', false);
$debug = $config->getBoolean('ldap.debug', false);
$referrals = $config->getBoolean('ldap.referrals', true);
$timeout = $config->getInteger('ldap.timeout', 0);
$username = $config->getString('ldap.username', null);
$password = $config->getString('ldap.password', null);
try {
$ldap = new Ldap($hostname, $enable_tls, $debug, $timeout, $port, $referrals);
} catch (\Exception $e) {
Logger::warning($e->getMessage());
return null;
}
$ldap->bind($username, $password);
$identifierAttrName = $config->getString('identifier.attr.name', 'OIDCClientID');
$urlAttrName = $config->getString('url.attr.name', 'rploginurl');
$base = $config->getString('ldap.basedn');
$filter = '(&(objectClass=perunFacility)(' . $identifierAttrName . '=' . $clientId . '))';
try {
$entries = $ldap->searchformultiple([$base], $filter, [$urlAttrName], [], true, false);
} catch (\Exception $e) {
$entries = [];
}
if (count($entries) < 1 || empty($entries[0][$urlAttrName])) {
return null;
}
return $entries[0][$urlAttrName][0];
}
public function logout(&$state) public function logout(&$state)
{ {
assert(is_array($state)); assert(is_array($state));
......
...@@ -72,3 +72,9 @@ msgstr "zavřít" ...@@ -72,3 +72,9 @@ msgstr "zavřít"
msgid "{campusmultiauth:otp_help}" msgid "{campusmultiauth:otp_help}"
msgstr "Vložte jednorázový kód, například z TOTP aplikace." msgstr "Vložte jednorázový kód, například z TOTP aplikace."
msgid "{campusmultiauth:timeout_dialog}"
msgstr "Z důvodu neaktivity je nutné stránku obnovit."
msgid "{campusmultiauth:refresh}"
msgstr "obnovit"
...@@ -72,3 +72,9 @@ msgstr "close" ...@@ -72,3 +72,9 @@ msgstr "close"
msgid "{campusmultiauth:otp_help}" msgid "{campusmultiauth:otp_help}"
msgstr "Enter a one time code, e.g. from a TOTP app." msgstr "Enter a one time code, e.g. from a TOTP app."
msgid "{campusmultiauth:timeout_dialog}"
msgstr "Because of inactivity, it is needed to refresh the page."
msgid "{campusmultiauth:refresh}"
msgstr "refresh"
...@@ -18,5 +18,8 @@ ...@@ -18,5 +18,8 @@
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"prettier": "^2.6.0", "prettier": "^2.6.0",
"semantic-release": "^19.0.2" "semantic-release": "^19.0.2"
},
"dependencies": {
"dialog-polyfill": "^0.5.4"
} }
} }
<dialog role="dialog" id="refresh-required-dialog" data-timeout="{{ refresh_dialog_timeout }}">
<p role="alert">
{{ '{campusmultiauth:timeout_dialog}'|trans }}
</p>
<p{% if muni_jvs %} class="btn-wrap"{% endif %}>
<a href="{{ restart_url }}" class="btn btn-primary{% if muni_jvs %} btn-s{% endif %}">
<span class="{% if muni_jvs %}upper{% else %}text-uppercase{% endif %}">{{ '{campusmultiauth:refresh}'|trans }}</span>
</a>
</p>
</dialog>
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
{% if idphint is not defined %}{% set idphint = [] %}{% endif %} {% if idphint is not defined %}{% set idphint = [] %}{% endif %}
<meta name="idphint" content="{{ idphint | json_encode }}"> <meta name="idphint" content="{{ idphint | json_encode }}">
<script src="/{{baseurlpath}}module.php/campusmultiauth/resources/campus-idp.js"></script> <script type="module" src="/{{baseurlpath}}module.php/campusmultiauth/resources/campus-idp.js"></script>
{% endblock %} {% endblock %}
{% block contentwrapper %} {% block contentwrapper %}
......
...@@ -30,6 +30,9 @@ ...@@ -30,6 +30,9 @@
{% endblock contentwrapper %} {% endblock contentwrapper %}
<div id="push"></div> <div id="push"></div>
</div>{# layout #} </div>{# layout #}
{% if restart_url is defined %}
{% block timeoutDialog %}{% include '@campusmultiauth/includes/timeout-dialog.twig' %}{% endblock %}
{% endif %}
<div id="foot"> <div id="foot">
{% block footer %}{% include "_footer.twig" %}{% endblock %} {% block footer %}{% include "_footer.twig" %}{% endblock %}
</div> </div>
......
...@@ -353,6 +353,10 @@ body { ...@@ -353,6 +353,10 @@ body {
width: 100%; width: 100%;
} }
#refresh-required-dialog {
text-align: center;
}
.idps-form-div { .idps-form-div {
margin-top: 0; margin-top: 0;
margin-bottom: 24px; margin-bottom: 24px;
......
import dialogPolyfill from "dialog-polyfill";
function hideElement(element) { function hideElement(element) {
element.classList.add("vhide", "d-none"); element.classList.add("vhide", "d-none");
} }
...@@ -91,6 +93,15 @@ function selectizeLoad(query, callback) { ...@@ -91,6 +93,15 @@ function selectizeLoad(query, callback) {
} }
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
// show dialog after the specified timeout to refresh the page
const dialog = document.getElementById("refresh-required-dialog");
if (dialog && dialog.dataset.timeout) {
dialogPolyfill.registerDialog(dialog);
setTimeout(() => {
dialog.showModal();
}, dialog.dataset.timeout * 1000);
}
var moreOptions = document.querySelectorAll(".more-options"); var moreOptions = document.querySelectorAll(".more-options");
if (moreOptions) { if (moreOptions) {
moreOptions.forEach(function (showButton) { moreOptions.forEach(function (showButton) {
......
...@@ -160,6 +160,54 @@ if (!empty($_POST['q'])) { ...@@ -160,6 +160,54 @@ if (!empty($_POST['q'])) {
curl_close($ch); curl_close($ch);
} }
// <timeout dialog>
$timeoutDialogConfig =
Configuration::getConfig('module_campusmultiauth.php')->getConfigItem('timeout_dialog');
if (!empty($timeoutDialogConfig)) {
$restartUrl = '#';
if (isset($state['SPMetadata']['RelayState'])) {
$rsUrl = filter_var(
$state['SPMetadata']['RelayState'],
FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
);
if ($rsUrl !== false) {
$restartUrl = $rsUrl;
}
}
if (isset($state['saml:RelayState'])) {
$rsUrl = filter_var(
$state['saml:RelayState'],
FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
);
if ($rsUrl !== false) {
$rs = parse_url($rsUrl);
$sp = $state['SPMetadata']['AssertionConsumerService'];
if (is_array($sp) && isset($sp[0])) {
$sp = $sp[0];
}
if (is_array($sp) && isset($sp['Location'])) {
$sp = $sp['Location'];
}
if (is_string($sp)) {
$sp = parse_url($sp);
if ($rs['scheme'] === $sp['scheme'] && $rs['host'] === $sp['host']) {
$restartUrl = $rsUrl;
}
}
// use login URL instead of redirecting to OIDC
$restartUrl = Campusidp::useLoginURL($state, $timeoutDialogConfig, $restartUrl);
}
}
}
// </timeout dialog>
$globalConfig = Configuration::getInstance(); $globalConfig = Configuration::getInstance();
$t = new Template($globalConfig, 'campusmultiauth:selectsource.php'); $t = new Template($globalConfig, 'campusmultiauth:selectsource.php');
...@@ -196,6 +244,11 @@ if (!empty($idphint)) { ...@@ -196,6 +244,11 @@ if (!empty($idphint)) {
} }
} }
if (isset($restartUrl)) {
$t->data['restart_url'] = $restartUrl;
$t->data['refresh_dialog_timeout'] = $timeoutDialogConfig->getInteger('refresh.dialog.timeout', 5 * 60);
}
$t->data['searchbox_indexes'] = json_encode(array_values(array_filter(array_map(function ($config, $index) { $t->data['searchbox_indexes'] = json_encode(array_values(array_filter(array_map(function ($config, $index) {
return $config['name'] === 'searchbox' ? $index : null; return $config['name'] === 'searchbox' ? $index : null;
}, $wayfConfig['components'], array_keys($wayfConfig['components'])), function ($a) { }, $wayfConfig['components'], array_keys($wayfConfig['components'])), function ($a) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment