Append GlobalLogout plugin (#1999)

This commit is contained in:
Christophe Maudoux 2019-11-13 20:56:56 +01:00
parent 818ebc89be
commit 7ef9e132c9
32 changed files with 99 additions and 42 deletions

View File

@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
use constant APPLYSECTION => "apply";
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|AllowOffline|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?)?|y(?:Deleted|Other))|AjaxHook)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|d(?:isablePersistentStorage|biDynamicHashEnabled|ontCompactConf)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|rest(?:(?:Session|Config)Server|ExportSecretKeys)|br(?:owsersDontStorePassword|uteForceProtection)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|AllowOffline|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?)?|y(?:Deleted|Other))|AjaxHook)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|d(?:isablePersistentStorage|biDynamicHashEnabled|ontCompactConf)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|rest(?:(?:Session|Config)Server|ExportSecretKeys)|br(?:owsersDontStorePassword|uteForceProtection)|(?:(?:globalLogout|active)Tim|wsdlServ)er|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs))$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -70,7 +70,7 @@ sub defaultValues {
'failedLoginNumber' => 5,
'formTimeout' => 120,
'globalLogoutRule' => 0,
'globalLogoutTimeout' => 30,
'globalLogoutTimer' => 1,
'globalStorage' => 'Apache::Session::File',
'globalStorageOptions' => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',

View File

@ -1225,9 +1225,9 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'default' => 0,
'type' => 'boolOrExpr'
},
'globalLogoutTimeout' => {
'default' => 30,
'type' => 'int'
'globalLogoutTimer' => {
'default' => 1,
'type' => 'bool'
},
'globalStorage' => {
'default' => 'Apache::Session::File',

View File

@ -473,10 +473,11 @@ sub attributes {
documentation => 'Global logout activation rule',
flags => 'p',
},
globalLogoutTimeout => {
default => 30,
type => 'int',
globalLogoutTimer => {
default => 1,
type => 'bool',
documentation => 'Global logout timeout',
flags => 'p',
},
impersonationMergeSSOgroups => {
default => 0,

View File

@ -676,7 +676,7 @@ sub tree {
help => 'globallogout.html',
form => 'simpleInputContainer',
nodes =>
[ 'globalLogoutRule', 'globalLogoutTimeout', ],
[ 'globalLogoutRule', 'globalLogoutTimer', ],
},
{
title => 'stateCheck',

View File

@ -298,7 +298,7 @@
"generalParameters":"المعاييرالعامة",
"globalLogout":"Global logout",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Logout timeout",
"globalLogoutTimer":"Logout timeout",
"globalStorage":"أباتشي :: وحدة الجلسة",
"globalStorageOptions":"أباتشي :: معايير وحدة الجلسة",
"gpgAuthnLevel":"مستوى إثبات الهوية",

View File

@ -298,7 +298,7 @@
"generalParameters":"General Parameters",
"globalLogout":"Global logout",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Logout timeout",
"globalLogoutTimer":"Logout timeout",
"globalStorage":"Apache::Session module",
"globalStorageOptions":"Apache::Session module parameters",
"gpgAuthnLevel":"Authentication level",

View File

@ -298,7 +298,7 @@
"generalParameters":"General Parameters",
"globalLogout":"Global logout",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Logout timeout",
"globalLogoutTimer":"Logout timeout",
"globalStorage":"Apache::Session module",
"globalStorageOptions":"Apache::Session module parameters",
"gpgAuthnLevel":"Authentication level",

View File

@ -298,7 +298,7 @@
"generalParameters":"Paramètres généraux",
"globalLogout":"Déconnexion globale",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Délai de déconnexion",
"globalLogoutTimer":"Délai de déconnexion globale automatique",
"globalStorage":"Module Apache::Session",
"globalStorageOptions":"Paramètres du module Apache::Session",
"gpgAuthnLevel":"Niveau d'authentification",

View File

@ -298,7 +298,7 @@
"generalParameters":"Parametri generali",
"globalLogout":"Global logout",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Logout timeout",
"globalLogoutTimer":"Logout timeout",
"globalStorage":"Modulo Apache::Session",
"globalStorageOptions":"Parametri di modulo Apache::Session",
"gpgAuthnLevel":"Livello di autenticazione",

View File

@ -298,7 +298,7 @@
"generalParameters":"Thông số chung",
"globalLogout":"Global logout",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Logout timeout",
"globalLogoutTimer":"Logout timeout",
"globalStorage":"Mô đun Apache :: Session",
"globalStorageOptions":"Tham số mô đun Apache :: Session ",
"gpgAuthnLevel":"Mức xác thực",

View File

@ -298,7 +298,7 @@
"generalParameters":"通用参数",
"globalLogout":"Global logout",
"globalLogoutRule":"Activation",
"globalLogoutTimeout":"Logout timeout",
"globalLogoutTimer":"Logout timeout",
"globalStorage":"Apache::Session 模块",
"globalStorageOptions":"Apache::Session module parameters",
"gpgAuthnLevel":"认证等级",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -35,15 +35,6 @@ has ott => (
}
);
# Default timeout: 30 seconds
has timeout => (
is => 'rw',
lazy => 1,
default => sub {
$_[0]->{conf}->{globalLogoutTimeout} // 30;
}
);
sub init {
my ($self) = @_;
$self->addAuthRoute( globallogout => 'globalLogout', [ 'POST', 'GET' ] );
@ -76,17 +67,14 @@ sub run {
}
# Looking for active sessions
my $sessions = $self->_activeSessions($req, $user);
my $sessions = $self->_activeSessions( $req, $user );
my $nbr = @{$sessions};
$self->logger->debug("GlobalLogout: $nbr session(s) found");
return PE_OK unless ( $nbr > 1 );
# Force GlobalLogout if timeout <= 0
unless ($self->conf->{globalLogoutTimeout}
and $self->conf->{globalLogoutTimeout} > 0 )
{
$self->logger->debug(
"GlobalLogout: timeout = $self->{conf}->{globalLogoutTimeout}");
# Force GlobalLogout if no timeout
unless ( $self->conf->{globalLogoutTimer} ) {
$self->logger->debug("GlobalLogout: timer disabled");
$self->userLogger->info("GlobalLogout: force global logout for $user");
my $as;
foreach (@$sessions) {
@ -116,13 +104,13 @@ sub run {
$req,
'globallogout',
params => {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
SESSIONS => $sessions,
TOKEN => $token,
LOGIN => $user,
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
SESSIONS => $sessions,
TOKEN => $token,
LOGIN => $user,
}
);
$req->response($tmp);

View File

@ -0,0 +1,17 @@
# Timer for globalLogout page
i = 30
go = () ->
$("#globallogout").submit()
timer = () ->
h = $('#timer').html()
i-- if i>0
h = h.replace /\d+/, i
$('#timer').html(h)
window.setTimeout timer, 1000
$(document).ready ->
window.setTimeout go, 30000
window.setTimeout timer, 1000

View File

@ -0,0 +1,27 @@
// Generated by CoffeeScript 1.12.7
(function() {
var go, i, timer;
i = 30;
go = function() {
return $("#globallogout").submit();
};
timer = function() {
var h;
h = $('#timer').html();
if (i > 0) {
i--;
}
h = h.replace(/\d+/, i);
$('#timer').html(h);
return window.setTimeout(timer, 1000);
};
$(document).ready(function() {
window.setTimeout(go, 30000);
return window.setTimeout(timer, 1000);
});
}).call(this);

View File

@ -0,0 +1 @@
(function(){var t,e,n;e=30,t=function(){return $("#globallogout").submit()},n=function(){var t;return t=$("#timer").html(),0<e&&e--,t=t.replace(/\d+/,e),$("#timer").html(t),window.setTimeout(n,1e3)},$(document).ready(function(){return window.setTimeout(t,3e4),window.setTimeout(n,1e3)})}).call(this);

View File

@ -0,0 +1 @@
{"version":3,"sources":["lemonldap-ng-portal/site/htdocs/static/common/js/globalLogout.js"],"names":["go","i","timer","$","submit","h","html","replace","window","setTimeout","document","ready","call","this"],"mappings":"CACA,WACE,IAAIA,EAAIC,EAAGC,EAEXD,EAAI,GAEJD,EAAK,WACH,OAAOG,EAAE,iBAAiBC,UAG5BF,EAAQ,WACN,IAAIG,EAOJ,OANAA,EAAIF,EAAE,UAAUG,OACR,EAAJL,GACFA,IAEFI,EAAIA,EAAEE,QAAQ,MAAON,GACrBE,EAAE,UAAUG,KAAKD,GACVG,OAAOC,WAAWP,EAAO,MAGlCC,EAAEO,UAAUC,MAAM,WAEhB,OADAH,OAAOC,WAAWT,EAAI,KACfQ,OAAOC,WAAWP,EAAO,SAGjCU,KAAKC"}

View File

@ -103,6 +103,7 @@
"authPortal":"بوابة إثبات الهوية",
"authRemaining":"٪ s المصادقة المتبقية، غيير كلمة المرور الخاصة بك!",
"autoAccept":"تقبل تلقائيا في 30 ثانية",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"التطبيق الذي قمت بتسجيل الخروج منه للتو قد وفرت وصلة قد ترغب في أن تتبعها",
"back2Portal":"العودة إلى البوابة",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Authentifizierungsportal",
"authRemaining":"%sverbleibende Authentifizierungen, bitte Passwort ändern!",
"autoAccept":"Automatisch in 30 Sekunden annehmen",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"Die Anwendung, von der Sie sich gerade abgemeldet haben, hat einen Link bereitgestellt, dem Sie folgen sollten",
"back2Portal":"Zurück zum Portal",
"badCode":"Falscher Code",

View File

@ -103,6 +103,7 @@
"authPortal":"Authentication portal",
"authRemaining":"%s authentications remaining, change your password!",
"autoAccept":"Automatically accept in 30 seconds",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"The application you just logged out of has provided a link it would like you to follow",
"back2Portal":"Go back to portal",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Portal de autenticación",
"authRemaining":"%s autenticaciones restantes, ¡cambie su contraseña!",
"autoAccept":"Aceptar automáticamente en 30 segundos ",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"La aplicación de la cual se acaba de desconectar le ha enviado un enlace y le gustaría que lo siguiese",
"back2Portal":"Volver al portal",
"badCode":"Código incorrecto",

View File

@ -103,6 +103,7 @@
"authPortal":"Todennus portaali",
"authRemaining":"%s authentications remaining, change your password!",
"autoAccept":"Automatically accept in 30 seconds",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"The application you just logged out of has provided a link it would like you to follow",
"back2Portal":"Palaa takaisin portaaliin",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Portail d'authentification",
"authRemaining":"%s authentifications restantes, changez votre mot de passe !",
"autoAccept":"Acceptation automatique dans 30 secondes",
"autoGlobalLogout":"Déconnexion globale automatique dans 30 secondes",
"back2CasUrl":"Le service duquel vous arrivez a fourni un lien que vous êtes invité à suivre",
"back2Portal":"Retourner au portail",
"badCode":"Mauvais code",

View File

@ -103,6 +103,7 @@
"authPortal":"Portale di autenticazione",
"authRemaining":"Rimangono ancora %s autenticazioni, modifica la password!",
"autoAccept":"Accetta automaticamente in 30 secondi",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"L'applicazione dalla quale ti sei appena sconnesso ha fornito un link che dovresti seguire",
"back2Portal":"Torna al portale",
"badCode":"Codice errato",

View File

@ -103,6 +103,7 @@
"authPortal":"Authentication portal",
"authRemaining":"%s authentications remaining, change your password!",
"autoAccept":"Automatically accept in 30 seconds",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"The application you just logged out of has provided a link it would like you to follow",
"back2Portal":"Go back to portal",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Authentication portal",
"authRemaining":"%s authentications remaining, change your password!",
"autoAccept":"Automatically accept in 30 seconds",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"The application you just logged out of has provided a link it would like you to follow",
"back2Portal":"Go back to portal",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Authentication portal",
"authRemaining":"%s authentications remaining, change your password!",
"autoAccept":"Automatically accept in 30 seconds",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"The application you just logged out of has provided a link it would like you to follow",
"back2Portal":"Go back to portal",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Cổng thông tin xác thực",
"authRemaining":"%s xác thực vẫn còn, thay đổi mật khẩu của bạn!",
"autoAccept":"Tự động chấp nhận trong 30 giây",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"Ứng dụng bạn vừa đăng xuất đã cung cấp một liên kết mà bạn muốn theo dõi",
"back2Portal":"Quay lại cổng thông tin",
"badCode":"Bad code",

View File

@ -103,6 +103,7 @@
"authPortal":"Authentication portal",
"authRemaining":"%s authentications remaining, change your password!",
"autoAccept":"30秒后自动接受",
"autoGlobalLogout":"Automatically global logout in 30 seconds",
"back2CasUrl":"The application you just logged out of has provided a link it would like you to follow",
"back2Portal":"回到首页",
"badCode":"Bad code",

View File

@ -32,7 +32,11 @@
</div>
</TMPL_IF>
</div>
<p>
<div class="card-footer bg-info">
<p id="timer" trspan="autoGlobalLogout">Automatically global logout in 30 seconds</p>
</div>
</p>
<form id="globallogout" action="/globallogout?all=1" method="post" class="password" role="form">
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<div class="buttons">
@ -51,6 +55,12 @@
</div>
</form>
<!-- //if:jsminified
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/globalLogout.min.js"></script>
//else -->
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/globalLogout.js"></script>
<!-- //endif -->
</div>
<TMPL_INCLUDE NAME="footer.tpl">