Merge branch 'v2.0'

This commit is contained in:
Yadd 2021-06-26 23:03:26 +02:00
commit 467bbf0f5e
38 changed files with 635 additions and 186 deletions

View File

@ -36,6 +36,7 @@ Applications
applications/office365
applications/publik
applications/phpldapadmin
applications/redmine
applications/roundcube
applications/salesforce
applications/sap
@ -116,6 +117,7 @@ Application Configuration
.. image:: applications/logo_office_365.png :doc:`Office 365<applications/office365>`
.. image:: applications/logo-publik.png :doc:`Publik<applications/publik>`
.. image:: applications/phpldapadmin_logo.png :doc:`phpLDAPAdmin<applications/phpldapadmin>`
.. image:: applications/redmine_logo.png :doc:`Redmine<applications/redmine>`
.. image:: applications/roundcube_logo.png :doc:`Roundcube<applications/roundcube>`
.. image:: applications/salesforce-logo.jpg :doc:`SalesForce<applications/salesforce>`
.. image:: applications/SAPLogo.gif :doc:`SAP<applications/sap>` ✔ ✔

View File

@ -0,0 +1,85 @@
Redmine
=======
|logo|
Presentation
------------
`Redmine <https://redmine.org/>`__ is is a flexible project management web application.
Written using the Ruby on Rails framework, it is cross-platform and cross-database.
It can be configured to authenticate users with :doc:`OpenID Connect <../idpopenidconnect>` with a plugin.
Configuration
--------------
LL:NG
~~~~~
Make sure you have already
:doc:`enabled OpenID Connect<../idpopenidconnect>` on your LemonLDAP::NG
server.
Make sure you have generated a set of signing keys in
``OpenID Connect Service`` » ``Security`` » ``Keys``
You also need to set a Signing key ID to a non-empty value of your choice.
Then, add a Relaying Party with the following configuration:
- Options » Basic » Client ID : choose a client ID, such as ``my_client_id``
- Options » Basic » Client Secret : choose a client secret, such as ``my_client_secret``
- Options » Basic » Allowed redirection address : ``https://my_redmine_server/oic/local_login``
- Options » Advanced » Force claims to be returned in ID Token : ``On``
- Options » Security » ID Token Signature Algorithm : ``RS512``
- Options » Logou( » Allowed redirection address for logout : ``https://my_redmine_server/oic/local_logout``
Define exported attributes:
- ``email``
- ``family_name``
- ``given_name``
- ``name``
- ``nickname``: the user login
To transfer groups:
- Declare ``member_of`` exported attribute as an array
- Declare a new scope named ``groups`` whith value ``member_of``
- Create a local macro ``member_of`` which will return ``["admin"]`` is user is administrator and ``["user"]`` else.
Redmine
~~~~~~~
Install `OpenID Connect plugin <https://github.com/devopskube/redmine_openid_connect>`__.
Go in Redmine admin console and configure the OpenID Connect plugin:
- Enabled: check the box
- Client ID: ``my_client_id``
- OpenID Connect server url: ``https://auth.example.com/``
- Client Secret: ``my_client_secret``
- OpenID Connect scopes: ``openid profile email groups``
- Authorized group: leave blank
- Admins group: ``admin``
- How often to retrieve openid configuration: leave blank
- Disable Ssl Validation: uncheck the box
- Login Selector: uncheck the box
- Create user if not exists: check the box
- Users from the following auth sources will be required to login with SSO: do not select anythin
.. attention::
A `bug <https://github.com/devopskube/redmine_openid_connect/issues/54>`__ has been reported, you must apply a patch
if you transfer groups.
.. note::
To bypass SSO, you can connect to `<https://my_redmine_server/login?local_login=true>`__
.. |logo| image:: /applications/redmine_logo.png
:class: align-center

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -60,7 +60,7 @@ Debian dist LLNG version Se
**8** Jessie `1.3.3 </documentation/1.3/>`__ |clean| CVE-2019-19791 tagged as minor **None** [1]_ June 2020 Probably 2023
**9** Stretch `1.9.7 </documentation/1.9/>`__ |clean| CVE-2019-19791 tagged as minor `Debian LTS Team <https://www.debian.org/lts/>`__ June 2022
\ *Stretch-backports* `2.0.2 </documentation/2.0/>`__ |bad| CVE-2019-12046, CVE-2019-13031, CVE-2019-15941 *None* *June 2019*
\ Stretch-backports-sloppy `2.0.11 </documentation/2.0/>`__ |clean| `LLNG Team </team>`__, "best effort" [3]_ Until Debian 11 release [4]_
\ Stretch-backports-sloppy `2.0.9 </documentation/2.0/>`__ |bad| *Maybe none*, "best effort" [3]_ Until Debian 11 release [4]_
**10** Buster `2.0.2 </documentation/2.0/>`__ |clean| CVE-2019-19791 tagged as minor `Debian Security Team <https://security-team.debian.org/>`__ Probably July 2024
\ Buster-backports `2.0.11 </documentation/2.0/>`__ |clean| `LLNG Team </team>`__ Until Debian 11 release [4]_
\ Bullseye `2.0.11 </documentation/2.0/>`__ |clean| `Debian Security Team <https://security-team.debian.org/>`__ Probably July 2026
@ -139,10 +139,11 @@ Other
Possible `Extended LTS <https://wiki.debian.org/LTS/Extended>`__
.. [3]
updated by `LLNG Team </team>`__ until dependencies are compatible
updated by `LLNG Team </team>`__ until dependencies are compatible,
however this distribution seems unmaintained now
.. [4]
around June 2021
around September 2021
.. [5]
few days after release

View File

@ -54,8 +54,9 @@ sub load {
$fields = $fields ? join( ",", @$fields ) : '*';
my $sth =
$self->_dbh->prepare(
"SELECT field,value from " . $self->{dbiTable} . " WHERE cfgNum=?" );
$sth->execute($cfgNum);
"SELECT field,value from " . $self->{dbiTable} . " WHERE cfgNum=?" )
or $self->logError;
$sth->execute($cfgNum) or $self->logError;
my ( $res, @row );
while ( @row = $sth->fetchrow_array ) {
$res->{ $row[0] } = $row[1];

View File

@ -36,8 +36,8 @@ sub available {
my $sth =
$self->_dbh->prepare( "SELECT DISTINCT cfgNum from "
. $self->{dbiTable}
. " order by cfgNum" );
$sth->execute();
. " order by cfgNum" ) or $self->logError;
$sth->execute() or $self->logError;
my @conf;
while ( my @row = $sth->fetchrow_array ) {
push @conf, $row[0];
@ -105,8 +105,9 @@ sub unlock {
sub delete {
my ( $self, $cfgNum ) = @_;
my $req =
$self->_dbh->prepare("DELETE FROM $self->{dbiTable} WHERE cfgNum=?");
my $res = $req->execute($cfgNum);
$self->_dbh->prepare("DELETE FROM $self->{dbiTable} WHERE cfgNum=?")
or $self->logError;
my $res = $req->execute($cfgNum) or $self->logError;
$Lemonldap::NG::Common::Conf::msg .=
"Unable to find conf $cfgNum (" . $self->_dbh->errstr . ")"
unless ($res);

View File

@ -338,7 +338,7 @@ sub defaultValues {
'sfManagerRule' => 1,
'sfRemovedMsgRule' => 0,
'sfRemovedNotifMsg' =>
'_removedSF_ expired second factor(s) has/have been removed!',
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
'sfRemovedNotifRef' => 'RemoveSF',
'sfRemovedNotifTitle' => 'Second factor notification',
'sfRequired' => 0,

View File

@ -248,6 +248,7 @@ t/15-combination.t
t/16-cli.t
t/17-extra2f.t
t/20-test-coverage.t
t/30-DBI-Cli.t
t/40-sessions.t
t/50-notifications-DBI.t
t/50-notifications.t
@ -267,6 +268,7 @@ t/jsonfiles/14-bad.json
t/jsonfiles/15-combination.json
t/jsonfiles/17-extra2f.json
t/jsonfiles/70-diff.json
t/lemonldap-ng-DBI-conf.ini
t/lemonldap-ng-dbi.ini
t/lemonldap-ng-noDiff.ini
t/lemonldap-ng.ini

View File

@ -3954,7 +3954,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'sfRemovedNotifMsg' => {
'default' =>
'_removedSF_ expired second factor(s) has/have been removed!',
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
'type' => 'text'
},
'sfRemovedNotifRef' => {

View File

@ -3238,7 +3238,7 @@ sub attributes {
sfRemovedNotifMsg => {
type => 'text',
default =>
'_removedSF_ expired second factor(s) has/have been removed!',
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
help => 'secondfactor.html',
documentation => 'Notification message',
},

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,67 @@
# Test notifications explorer API
use strict;
use Data::Dumper;
use IO::String;
use JSON qw(from_json);
use Test::More;
my $count = 0;
my $file = 't/conf.db';
my $maintests = 1;
my ( $res, $client );
eval { unlink $file };
sub count {
my $c = shift;
$count += $c if ($c);
return $count;
}
SKIP: {
eval { require DBI; require DBD::SQLite; };
if ($@) {
skip 'DBD::SQLite not found', $maintests;
}
my $dbh = DBI->connect("dbi:SQLite:dbname=$file");
$dbh->do('CREATE TABLE lmConfig (cfgNum int, data text)')
or die $DBI::errstr;
{
local $/ = undef;
open my $f, '<', 't/conf/lmConf-1.json';
my $content = <$f>;
close $f;
my $sth = $dbh->prepare('INSERT INTO lmConfig VALUES(1,?)')
or die $DBI::errstr;
$sth->execute($content) or die $DBI::errstr;
}
use_ok('Lemonldap::NG::Manager::Cli::Lib');
ok(
$client = Lemonldap::NG::Manager::Cli::Lib->new(
iniFile => 't/lemonldap-ng-DBI-conf.ini'
),
'Client object'
);
count(1);
use_ok('Lemonldap::NG::Manager::Cli');
count(1);
my @args = (qw(-yes 1 -force 1 set ldapSetPassword 0));
$ENV{LLNG_DEFAULTCONFFILE} = 't/lemonldap-ng-DBI-conf.ini';
Lemonldap::NG::Manager::Cli->run(@args);
my $res = $dbh->selectall_arrayref('SELECT * FROM lmConfig');
my $conf = from_json( $res->[0]->[1] );
ok( (
defined( $conf->{ldapSetPassword} )
and $conf->{ldapSetPassword} == 0
),
'Key inserted'
);
count(1);
}
eval { unlink $file };
done_testing( count($maintests) );

View File

@ -0,0 +1,27 @@
[all]
logLevel = debug
localSessionStorage =
localSessionStorageOptions =
[configuration]
type=CDBI
dbiChain=dbi:SQLite:dbname=t/conf.db
[portal]
checkXSS = 0
[handler]
https = 0
status = 0
useRedirectOnError = 0
[manager]
protection = manager
staticPrefix = app/
languages = fr, en, vi, ar
templateDir = site/templates/

View File

@ -521,6 +521,7 @@ t/29-AuthSSL.t
t/30-Auth-and-issuer-SAML-Artifact-with-SOAP-SLO-IdP-initiated.t
t/30-Auth-and-issuer-SAML-Artifact-with-SOAP-SLO.t
t/30-Auth-and-issuer-SAML-Metadata.t
t/30-Auth-and-issuer-SAML-NameID.t
t/30-Auth-and-issuer-SAML-POST-Hook.t
t/30-Auth-and-issuer-SAML-POST-IdP-initiated.t
t/30-Auth-and-issuer-SAML-POST-Missing-SLO.t
@ -576,6 +577,7 @@ t/32-OIDC-Hooks.t
t/32-OIDC-Macro.t
t/32-OIDC-Offline-Session.t
t/32-OIDC-Password-Grant-with-Bruteforce-and-Choice.t
t/32-OIDC-Password-Grant.t
t/32-OIDC-Refresh-Token.t
t/32-OIDC-Register.t
t/32-OIDC-RP-rule.t
@ -679,6 +681,7 @@ t/65-AutoSignin.t
t/65-CheckState.t
t/66-CDA-already-auth.t
t/66-CDA-PSGI-Try.t
t/66-CDA-wildcard.t
t/66-CDA-with-doubleCookies.t
t/66-CDA-with-REST.t
t/66-CDA-with-SOAP.t

View File

@ -240,6 +240,7 @@ sub run {
$self->logger->debug("Looking for expired 2F device(s)...");
my $removed = 0;
my $name = '';
my $now = time();
foreach my $device (@$_2fDevices) {
my $type = lc( $device->{type} );
@ -252,16 +253,18 @@ sub run {
);
$self->userLogger->info("Remove expired $device->{type}");
$device->{type} = 'EXPIRED';
$name .= "$device->{name}; ";
$removed++;
}
}
if ($removed) {
$name =~ s/;\s$//;
$self->logger->debug(
"Found $removed EXPIRED 2F device(s) => Update persistent session"
);
$self->userLogger->notice(
" -> $removed expired 2F device(s) removed");
" -> $removed expired 2F device(s) removed ($name)");
@$_2fDevices =
map { $_->{type} =~ /\bEXPIRED\b/ ? () : $_ } @$_2fDevices;
$self->p->updatePersistentSession( $req,
@ -276,13 +279,13 @@ sub run {
my $title = $self->conf->{sfRemovedNotifTitle}
|| 'Second factor notification';
my $msg = $self->conf->{sfRemovedNotifMsg}
|| "$removed expired second factor(s) has/have been removed!";
|| "$removed expired second factor(s) has/have been removed ($name)!";
$msg =~ s/_removedSF_/$removed/;
$msg =~ s/_nameSF_/$name/;
my $params =
$removed > 1
? { trspan => "expired2Fremoved, $removed" }
: { trspan => "oneExpired2Fremoved" };
? { trspan => "expired2Fremoved, $removed, $name" }
: { trspan => "oneExpired2Fremoved, $name" };
my $notifEngine = $self->p->loadedModules->{
'Lemonldap::NG::Portal::Plugins::Notifications'};
@ -384,8 +387,8 @@ sub run {
# bool public display2fRegisters($req, $session)
#
# Return true if at least 1 register module is available for this user. Used
# by Menu to display or not /2fregisters page
# Return true if at least 1 register module is available for this user.
# Used by Menu for displaying or not /2fregisters page
sub display2fRegisters {
my ( $self, $req, $session ) = @_;
foreach my $m ( @{ $self->sfRModules } ) {

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"يرجى استخدام يوبي كي الخاص بك",
"errorMsg":"رسالة خاطئة",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"الاسم الاول",
@ -225,7 +225,7 @@
"oidcConsent":"التطبيق ٪s هل ترغب في معرفة:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"فمثلا:http://myopenid.org/toto",
"openSSOSession":"افتح جلسة الدخول الموحد (سسو)",
"openSessionSpace":"هذه المساحة تتيح لك فتح جلسة تسجيل الدخول الموحد (سسو).سوف تساعدك على الوصول بشكل آمن إلى جميع التطبيقات التي أذن بها بروفيل الخاص بك.",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Gebe den TOTP Code ein",
"enterYubikey":"Benutze bitte deinen Yubikey",
"errorMsg":"Fehlermeldung",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"Vorname",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"zum Beispiel: http://myopenid.org/toto",
"openSSOSession":"Eine SSO Sitzung öffnen",
"openSessionSpace":"Mit diesem Bereich kannst du eine SSO-Sitzung öffnen. Dadurch kannst du sicher auf alle von deinem Profil autorisierten Anwendungen zugreifen.",
@ -292,7 +292,7 @@
"submit":"Absenden",
"switchContext":"Switch context",
"totp2f":"OTP App",
"totpExistingKey":"Es existiert bereits ein TOTP-Secret",
"totpExistingKey":"A TOTP device is already registered, you must remove it before adding a new TOTP device",
"totpMissingCode":"Please enter the code supplied by your TOTP application",
"totpQrCode":"Scan this QR code in your TOTP application",
"totpRegisterCode":"Input the code provided by your application",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"Please use your Yubikey",
"errorMsg":"Error Message",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"First name",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"for example:http://myopenid.org/toto",
"openSSOSession":"Open your SSO session",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Ingrese el código TOTP",
"enterYubikey":"Por favor utilice su Yubikey",
"errorMsg":"Mensaje de Error",
"expired2Fremoved":"¡%s dispositivos 2F caducados han sido suprimidos!",
"expired2Fremoved":"¡%s dispositivos 2F caducados han sido suprimidos (%s)!",
"explorer":"Explorer",
"ext2f":"Código de verificación",
"firstName":"Nombre",
@ -225,7 +225,7 @@
"oidcConsent":"La aplicación %s quisiera:",
"oidcConsents":"Permisos OIDC",
"oidcConsentsFull":"Permisos OpenID Connect",
"oneExpired2Fremoved":"¡Un dispositivo 2F caducado ha sido suprimido!",
"oneExpired2Fremoved":"¡Un dispositivo 2F caducado ha sido suprimido (%s)!",
"openIdExample":"por ejemplo:http://myopenid.org/juan",
"openSSOSession":"Abra su sesión SSO",
"openSessionSpace":"Este espacio le permite abrir una sesión SSO. Esto le ayudará a acceder de manera segura a todas las aplicaciones autorizadas por su perfil.",
@ -292,7 +292,7 @@
"submit":"Enviar",
"switchContext":"Cambiar contexto",
"totp2f":"Aplicación OTP",
"totpExistingKey":"Un secreto TOTP ya existe",
"totpExistingKey":"A TOTP device is already registered, you must remove it before adding a new TOTP device",
"totpMissingCode":"Please enter the code supplied by your TOTP application",
"totpQrCode":"Scan this QR code in your TOTP application",
"totpRegisterCode":"Input the code provided by your application",
@ -338,4 +338,4 @@
"yourProfile":"Conozca su perfil",
"yourTotpKey":"Su llave TOTP",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"Please use your Yubikey",
"errorMsg":"Virhe viesti",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"Etunimi",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"for example:http://myopenid.org/toto",
"openSSOSession":"Open your SSO session",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Entrez le code TOTP",
"enterYubikey":"Utilisez votre Yubikey",
"errorMsg":"Message d'erreur",
"expired2Fremoved":"%s seconds facteurs expirés ont été supprimés !",
"expired2Fremoved":"%s seconds facteurs expirés ont été supprimés (%s) !",
"explorer":"Explorateur",
"ext2f":"Code de vérification",
"firstName":"Prénom",
@ -225,7 +225,7 @@
"oidcConsent":"L'application %s voudrait :",
"oidcConsents":"Accords OIDC",
"oidcConsentsFull":"Accords OpenID Connect",
"oneExpired2Fremoved":"Un second facteur expiré a été supprimé !",
"oneExpired2Fremoved":"Un second facteur expiré a été supprimé (%s) !",
"openIdExample":"par exemple : http://myopenid.org/toto",
"openSSOSession":"Ouvrir une session SSO",
"openSessionSpace":"Cet espace vous permet d'ouvrir une session SSO. Celle-ci vous aidera à accéder de manière totalement sécurisée à l'ensemble des applications autorisées par votre profil utilisateur.",

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Inserisci il codice TOTP",
"enterYubikey":"Utilizza il tuo Yubikey",
"errorMsg":"Messaggio di errore",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"Nome",
@ -225,7 +225,7 @@
"oidcConsent":"L'applicazione %s vorrebbe sapere:",
"oidcConsents":"Consensi OIDC",
"oidcConsentsFull":"Consensi OpenID Connect",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"per esempio:http://myopenid.org/toto",
"openSSOSession":"Apri la sessione SSO",
"openSessionSpace":"Questo spazio consente di aprire una sessione SSO. Questo vi aiuterà ad accedere in modo sicuro a tutte le applicazioni autorizzate dal tuo profilo.",
@ -292,7 +292,7 @@
"submit":"Invia",
"switchContext":"Switch context",
"totp2f":"OTP App",
"totpExistingKey":"Un segreto TOTP esiste già",
"totpExistingKey":"A TOTP device is already registered, you must remove it before adding a new TOTP device",
"totpMissingCode":"Please enter the code supplied by your TOTP application",
"totpQrCode":"Scan this QR code in your TOTP application",
"totpRegisterCode":"Input the code provided by your application",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"La tua chiave TOTP",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"Please use your Yubikey",
"errorMsg":"Error Message",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"First name",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"for example:http://myopenid.org/toto",
"openSSOSession":"Open your SSO session",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Wpisz kod TOTP",
"enterYubikey":"Proszę użyć klucza Yubikey",
"errorMsg":"Komunikat o błędzie",
"expired2Fremoved":"%s przeterminowane urządzenia 2F zostały usunięte!",
"expired2Fremoved":"%s przeterminowane urządzenia 2F zostały usunięte (%s)!",
"explorer":"Eksplorator",
"ext2f":"Kod weryfikacyjny",
"firstName":"Imię",
@ -225,7 +225,7 @@
"oidcConsent":"Aplikacja %s chciałaby znać:",
"oidcConsents":"OIDC wyraża zgodę",
"oidcConsentsFull":"Zgody OpenID-Connect",
"oneExpired2Fremoved":"Przeterminowane urządzenie 2F zostało usunięte!",
"oneExpired2Fremoved":"Przeterminowane urządzenie 2F zostało usunięte (%s)!",
"openIdExample":"na przykład: http://myopenid.org/toto",
"openSSOSession":"Otwórz sesję logowania jednokrotnego",
"openSessionSpace":"Ta przestrzeń umożliwia otwarcie sesji SSO. Pomoże to w bezpiecznym dostępie do wszystkich aplikacji autoryzowanych przez Twój profil.",
@ -292,7 +292,7 @@
"submit":"Zatwierdź",
"switchContext":"Przełącz kontekst",
"totp2f":"Aplikacja OTP",
"totpExistingKey":"Sekret TOTP już istnieje",
"totpExistingKey":"A TOTP device is already registered, you must remove it before adding a new TOTP device",
"totpMissingCode":"Please enter the code supplied by your TOTP application",
"totpQrCode":"Scan this QR code in your TOTP application",
"totpRegisterCode":"Input the code provided by your application",
@ -338,4 +338,4 @@
"yourProfile":"Twój profil",
"yourTotpKey":"Twój klucz TOTP",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"Please use your Yubikey",
"errorMsg":"Error Message",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"First name",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"for example:http://myopenid.org/toto",
"openSSOSession":"Open your SSO session",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"Please use your Yubikey",
"errorMsg":"Error Message",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"First name",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"for example:http://myopenid.org/toto",
"openSSOSession":"Open your SSO session",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"TOTP kodunu gir",
"enterYubikey":"Lütfen Yubikey'inizi kullanın",
"errorMsg":"Hata Mesajı",
"expired2Fremoved":"Kullanım süresi dolan %s2F cihazı kaldırıldı!",
"expired2Fremoved":"Kullanım süresi dolan %s2F cihazı kaldırıldı (%s)!",
"explorer":"Explorer",
"ext2f":"Doğrulama kodu",
"firstName":"Ad",
@ -225,7 +225,7 @@
"oidcConsent":"%s uygulaması şunları yapmak istiyor:",
"oidcConsents":"OIDC izinleri",
"oidcConsentsFull":"OpenID Connect izinleri",
"oneExpired2Fremoved":"Kullanım süresi dolan bir 2F cihazı kaldırıldı!",
"oneExpired2Fremoved":"Kullanım süresi dolan bir 2F cihazı kaldırıldı (%s)!",
"openIdExample":"örneğin: http://myopenid.org/toto",
"openSSOSession":"TOA oturumunuzu açın",
"openSessionSpace":"Bu alan bir TOA oturumu açmanıza izin verir. Oturum açtığınızda profiliniz için yetkilendirilmiş tüm uygulamalara güvenli bir şekilde erişebilirsiniz.",
@ -292,7 +292,7 @@
"submit":"Gönder",
"switchContext":"Bağlam değiştir",
"totp2f":"OTP Uygulaması",
"totpExistingKey":"Bir TOTP sırrı zaten mevcut",
"totpExistingKey":"A TOTP device is already registered, you must remove it before adding a new TOTP device",
"totpMissingCode":"Please enter the code supplied by your TOTP application",
"totpQrCode":"Scan this QR code in your TOTP application",
"totpRegisterCode":"Input the code provided by your application",
@ -338,4 +338,4 @@
"yourProfile":"Profilini bil",
"yourTotpKey":"TOTP anahtarınız",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"Vui lòng sử dụng Yubikey của bạn",
"errorMsg":"Thông báo lỗi",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"Tên",
@ -225,7 +225,7 @@
"oidcConsent":"Ứng dụng %s muốn biết:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"ví dụ: http: //myopenid.org/toto",
"openSSOSession":"Mở phiên SSO của bạn",
"openSessionSpace":"Không gian này cho phép bạn mở phiên SSO. Điều này sẽ giúp bạn truy cập an toàn vào tất cả các ứng dụng được cho phép bởi profile của bạn. ",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"Enter TOTP code",
"enterYubikey":"请使用您的Yubikey",
"errorMsg":"错误消息",
"expired2Fremoved":"%s expired 2F devices have been removed!",
"expired2Fremoved":"%s expired 2F devices have been removed (%s)!",
"explorer":"Explorer",
"ext2f":"Verification code",
"firstName":"名",
@ -225,7 +225,7 @@
"oidcConsent":"The application %s would like to:",
"oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID Connect consents",
"oneExpired2Fremoved":"An expired 2F device has been removed!",
"oneExpired2Fremoved":"An expired 2F device has been removed (%s)!",
"openIdExample":"例如http://myopenid.org/toto",
"openSSOSession":"Open your SSO session",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
@ -338,4 +338,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -165,7 +165,7 @@
"enterTotpCode":"輸入 TOTP 代碼",
"enterYubikey":"請使用您的 Yubikey",
"errorMsg":"錯誤訊息",
"expired2Fremoved":"%s 個過期的雙因素驗證已被移除",
"expired2Fremoved":"%s 個過期的雙因素驗證已被移除 (%s)",
"explorer":"探索者",
"ext2f":"驗證代碼",
"firstName":"名",
@ -225,7 +225,7 @@
"oidcConsent":"應用程式 %s 想要:",
"oidcConsents":"OIDC 同意",
"oidcConsentsFull":"OpenID 連線同意",
"oneExpired2Fremoved":"過期的雙因素驗證裝置已被移除",
"oneExpired2Fremoved":"過期的雙因素驗證裝置已被移除 (%s)",
"openIdExample":"例如http://myopenid.org/toto",
"openSSOSession":"開啟您的 SSO 工作階段",
"openSessionSpace":"此空間讓您可以開啟 SSO 工作階段。這將協助您安全地存取您個人檔案授權的所有應用程式。",
@ -292,7 +292,7 @@
"submit":"遞交",
"switchContext":"切換內容",
"totp2f":"OTP 應用程式",
"totpExistingKey":"TOTP 祕密已存在",
"totpExistingKey":"A TOTP device is already registered, you must remove it before adding a new TOTP device",
"totpMissingCode":"Please enter the code supplied by your TOTP application",
"totpQrCode":"Scan this QR code in your TOTP application",
"totpRegisterCode":"Input the code provided by your application",
@ -338,4 +338,4 @@
"yourProfile":"知道您的個人檔案",
"yourTotpKey":"您的 TOTP 金鑰",
"yubikey2f":"Yubikey"
}
}

View File

@ -6,7 +6,7 @@ use JSON qw(to_json from_json);
BEGIN {
require 't/test-lib.pm';
}
my $maintests = 64;
my $maintests = 88;
SKIP: {
require Lemonldap::NG::Common::TOTP;
@ -133,6 +133,7 @@ SKIP: {
ok( $res->{result} == 1, 'TOTP is registered' );
## Try to register an U2F key
Time::Fake->offset("+3s");
ok(
$res = $client->_get(
'/2fregisters/u',
@ -278,6 +279,26 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
expectOK($res);
expectAuthenticatedAs( $res, 'rtyler' );
# 2fregisters
ok(
$res = $client->_get(
'/2fregisters',
cookie => "lemonldap=$id",
accept => 'text/html',
),
'Form 2fregisters'
);
ok( $res->[2]->[0] =~ /<span id="msg" trspan="choose2f">/,
'Found choose 2F' )
or print STDERR Dumper( $res->[2]->[0] );
my $devices;
ok(
$devices = $res->[2]->[0] =~ s%<span device=\'(?:TOTP|U2F)\' epoch=\'\d{10}\'%%g,
'2F device found'
) or print STDERR Dumper( $res->[2]->[0] );
ok( $devices == 2, '2F devices found' )
or explain( $devices, '2F devices registered' );
# Try to switch context 'dwho'
# ContextSwitching form
ok(
@ -321,25 +342,8 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_OFF">%,
'Found trspan="contextSwitching_OFF"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' );
# 2fregisters
ok(
$res = $client->_get(
'/2fregisters',
cookie => "lemonldap=$id2",
accept => 'text/html',
),
'Form 2fregisters'
);
ok( $res->[2]->[0] =~ /<span id="msg" trspan="choose2f">/,
'Found choose 2F' )
or print STDERR Dumper( $res->[2]->[0] );
my $devices;
ok( $devices = $res->[2]->[0] =~ s%<span device=\'(TOTP|U2F)\' epoch=\'\d{10}\'%%g,
'2F devices found' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $devices == 2, 'two 2F devices found' )
or explain( $devices, 'Two 2F devices registered' );
ok( $id2 ne $id, 'New SSO session created' )
or explain( $id2, 'New SSO session created' );
## Try to register a TOTP
# TOTP form
@ -351,9 +355,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
),
'Form registration'
);
ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /totpregistration\.(?:min\.)?js/, 'Found TOTP js' );
ok(
$res->[2]->[0] =~ qr%<img src="/static/common/logos/logo_llng_old.png"%,
'Found custom Main Logo'
@ -371,28 +373,18 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' );
ok( $res->{error} eq 'totpExistingKey', 'TOTP already registered' )
or explain( $res, 'Bad result' );
ok( $key = $res->{secret}, 'Found secret' ) or print STDERR Dumper($res);
ok( $token = $res->{token}, 'Found token' ) or print STDERR Dumper($res);
ok( $res->{user} eq 'dwho', 'Found user' )
or print STDERR Dumper($res);
$key = Convert::Base32::decode_base32($key);
# Try to unregister TOTP
ok(
$res = $client->_post(
'/2fregisters/totp/delete',
IO::String->new("epoch=1234567890"),
length => 16,
cookie => "lemonldap=$id2",
),
'Delete TOTP query'
);
eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' );
ok(
$data->{error} eq '2FDeviceNotFound', '2F device not found'
) or explain( $data, 'Bad result' );
# Try to verify TOTP
$s = "code=123456&token=1234567890&TOTPName=myTOTP";
# Post code
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
'Code' );
ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' );
my $s = "code=$code&token=$token&TOTPName=myTOTP";
my $epoch = time();
ok(
$res = $client->_post(
'/2fregisters/totp/verify',
@ -402,61 +394,199 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
),
'Post code'
);
eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' );
ok( $data->{error} eq 'PE82', 'PE82' )
or explain( $data, 'Bad result' );
eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' );
ok( $res->{result} == 1, 'TOTP is registered' );
## Try to register an U2F key
# U2F form
# 2fregisters
ok(
$res = $client->_get(
'/2fregisters/u',
'/2fregisters',
cookie => "lemonldap=$id2",
accept => 'text/html',
),
'Form registration'
'Form 2fregisters'
);
ok( $res->[2]->[0] =~ /u2fregistration\.(?:min\.)?js/, 'Found U2F js' );
ok( $res->[2]->[0] =~ /<span id="msg" trspan="choose2f">/,
'Found choose 2F' )
or print STDERR Dumper( $res->[2]->[0] );
my $devices;
ok(
$res->[2]->[0] =~ qr%<img src="/static/common/logos/logo_llng_old.png"%,
'Found custom Main Logo'
$devices = $res->[2]->[0] =~ s%<span device=\'TOTP\' epoch=\'\d{10}\'%%g,
'2F device found'
) or print STDERR Dumper( $res->[2]->[0] );
ok( $devices == 1, '2F device found' )
or explain( $devices, '2F device registered' );
# Ajax registration request
# Try to unregister TOTP
ok(
$res = $client->_post(
'/2fregisters/u/register', IO::String->new(''),
accept => 'application/json',
cookie => "lemonldap=$id2",
length => 0,
),
'Get registration challenge'
);
eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' );
ok(
$data->{challenge} =~ /\w+/, 'Get challenge'
) or explain( $data, 'Bad result' );
# Try to unregister U2F key
ok(
$res = $client->_post(
'/2fregisters/u/delete',
IO::String->new("epoch=1234567890"),
'/2fregisters/totp/delete',
IO::String->new("epoch=$epoch"),
length => 16,
cookie => "lemonldap=$id2",
),
'Delete U2F key query'
'Delete TOTP query'
);
eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' );
ok( $data->{result} == 1, 'TOTP removed' )
or explain( $data, '"result":1' );
$client->logout($id);
$client->logout($id2);
## Try to authenticate
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
( $host, $url, $query ) =
expectForm( $res, '#', undef, 'user', 'password' );
$query =~ s/user=/user=dwho/;
$query =~ s/password=/password=dwho/;
ok(
$data->{error} eq '2FDeviceNotFound', '2F device not found'
) or explain( $data, 'Bad result' );
$res = $client->_post(
'/',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Auth query'
);
$id = expectCookie($res);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as dwho'
) or print STDERR Dumper( $res->[2]->[0] );
expectAuthenticatedAs( $res, 'dwho' );
ok(
$res->[2]->[0] =~
m%<span trspan="contextSwitching_ON">contextSwitching_ON</span>%,
'contextSwitching allowed'
) or print STDERR Dumper( $res->[2]->[0] );
# Try to switch context 'rtyler'
# ContextSwitching form
ok(
$res = $client->_get(
'/switchcontext',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'ContextSwitching form',
);
( $host, $url, $query ) =
expectForm( $res, undef, '/switchcontext', 'spoofId' );
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_ON">%,
'Found trspan="contextSwitching_ON"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_ON"' );
## POST form
$query =~ s/spoofId=/spoofId=rtyler/;
ok(
$res = $client->_post(
'/switchcontext',
IO::String->new($query),
cookie => "lemonldap=$id",
length => length($query),
accept => 'text/html',
),
'POST switchcontext'
);
expectRedirection( $res, 'http://auth.example.com/' );
$id2 = expectCookie($res);
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id2",
accept => 'text/html'
),
'Get Menu',
);
expectAuthenticatedAs( $res, 'rtyler' );
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_OFF">%,
'Found trspan="contextSwitching_OFF"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' );
ok( $id2 ne $id, 'New SSO session created' )
or explain( $id2, 'New SSO session created' );
# 2fregisters
ok(
$res = $client->_get(
'/2fregisters',
cookie => "lemonldap=$id2",
accept => 'text/html',
),
'Form 2fregisters'
);
ok( $res->[2]->[0] =~ /<span id="msg" trspan="choose2f">/,
'Found choose 2F' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~ m%<span device=\'TOTP\' epoch=\'(\d{10})\'%,
'TOTP found'
) or print STDERR Dumper( $res->[2]->[0] );
$epoch = $1;
ok(
$devices = $res->[2]->[0] =~ s%<span device=\'(?:TOTP|U2F)\' epoch=\'(?:\d{10})\'%%g,
'2F devices found'
) or print STDERR Dumper( $res->[2]->[0] );
ok( $devices == 2, '2F devices registered' )
or explain( $devices, '2F devices registered' );
# Try to unregister TOTP
ok(
$res = $client->_post(
'/2fregisters/totp/delete',
IO::String->new("epoch=$epoch"),
length => 16,
cookie => "lemonldap=$id2",
),
'Delete TOTP query'
);
eval { $data = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), ' Content is JSON' )
or explain( [ $@, $res->[2] ], 'JSON content' );
ok( $data->{result} == 1, '2F removed' )
or explain( $data, '"result":1' );
# 2fregisters
ok(
$res = $client->_get(
'/2fregisters',
cookie => "lemonldap=$id2",
accept => 'text/html',
),
'Form 2fregisters'
);
ok( $res->[2]->[0] =~ /<span trspan="remove2fWarning">/,
'Found 2F modal' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ /<span id="msg" trspan="choose2f">/,
'Found choose 2F' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$devices = $res->[2]->[0] =~ s%<span device=\'(?:TOTP|U2F)\' epoch=\'(\d{10})\'%%g,
'2F device found'
) or print STDERR Dumper( $res->[2]->[0] );
ok( $devices == 1, '2F device registered' )
or explain( $devices, '2F device registered' );
$client->logout($id);
$client->logout($id2);

View File

@ -6,7 +6,7 @@ use JSON qw(to_json from_json);
BEGIN {
require 't/test-lib.pm';
}
my $maintests = 63;
my $maintests = 76;
SKIP: {
require Lemonldap::NG::Common::TOTP;
@ -460,6 +460,108 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
$client->logout($id);
$client->logout($id2);
## Try to authenticate
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
( $host, $url, $query ) =
expectForm( $res, '#', undef, 'user', 'password' );
$query =~ s/user=/user=dwho/;
$query =~ s/password=/password=dwho/;
ok(
$res = $client->_post(
'/',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Auth query'
);
$id = expectCookie($res);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as dwho'
) or print STDERR Dumper( $res->[2]->[0] );
expectAuthenticatedAs( $res, 'dwho' );
ok(
$res->[2]->[0] =~
m%<span trspan="contextSwitching_ON">contextSwitching_ON</span>%,
'contextSwitching allowed'
) or print STDERR Dumper( $res->[2]->[0] );
# Try to switch context 'rtyler'
# ContextSwitching form
ok(
$res = $client->_get(
'/switchcontext',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'ContextSwitching form',
);
( $host, $url, $query ) =
expectForm( $res, undef, '/switchcontext', 'spoofId' );
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_ON">%,
'Found trspan="contextSwitching_ON"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_ON"' );
## POST form
$query =~ s/spoofId=/spoofId=rtyler/;
ok(
$res = $client->_post(
'/switchcontext',
IO::String->new($query),
cookie => "lemonldap=$id",
length => length($query),
accept => 'text/html',
),
'POST switchcontext'
);
expectRedirection( $res, 'http://auth.example.com/' );
$id2 = expectCookie($res);
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id2",
accept => 'text/html'
),
'Get Menu',
);
expectAuthenticatedAs( $res, 'rtyler' );
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_OFF">%,
'Found trspan="contextSwitching_OFF"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' );
# 2fregisters
ok(
$res = $client->_get(
'/2fregisters',
cookie => "lemonldap=$id2",
accept => 'text/html',
),
'Form 2fregisters'
);
ok( $res->[2]->[0] =~ /<span id="msg" trspan="notAuthorized">/,
'Found choose 2F' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] !~ m%<span device=\'(TOTP|U2F)\' epoch=\'\d{10}\'%g,
'No 2F device found' )
or print STDERR Dumper( $res->[2]->[0] );
}
count($maintests);

View File

@ -99,8 +99,11 @@ ok(
'POST switchcontext'
);
expectRedirection( $res, 'http://auth.example.com/' );
# Refresh cookie value
my $id2 = expectCookie($res);
ok( $id2 ne $id, 'New SSO session created' )
or explain( $id2, 'New SSO session created' );
ok(
$res = $client->_get(
'/',
@ -121,10 +124,17 @@ ok(
),
'Stop context switching rtyler',
);
count(6);
# Refresh cookie value
$id = expectCookie($res);
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id2",
accept => 'text/html'
),
'Get Menu',
);
ok( $res->[2]->[0] =~ m%<span trmsg="1">%, 'Found PE_SESSIONEXPIRED' )
or explain( $res->[2]->[0], 'Session expired' );
count(9);
# ContextSwitching form: dwho -> french
# ------------------------
@ -153,8 +163,11 @@ ok(
'POST switchcontext'
);
expectRedirection( $res, 'http://auth.example.com/' );
# Refresh cookie value
$id2 = expectCookie($res);
ok( $id2 ne $id, 'New SSO session created' )
or explain( $id2, 'New SSO session created' );
ok(
$res = $client->_get(
'/',
@ -167,7 +180,7 @@ expectAuthenticatedAs( $res, 'french' );
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_OFF">%,
'Found trspan="contextSwitching_OFF"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' );
count(5);
count(6);
# CheckUser request
ok(
@ -180,11 +193,14 @@ eval { $res = JSON::from_json( $res->[2]->[0] ) };
ok( not($@), 'Content is JSON' )
or explain( $res->[2]->[0], 'JSON content' );
my @sessions_id =
map { $_->{key} =~ /_session_id$/ ? $_ : () } @{ $res->{ATTRIBUTES} };
map { $_->{key} =~ /^switching_session_id$/ ? $_ : () }
@{ $res->{ATTRIBUTES} };
ok( $sessions_id[0]->{value} eq $id, 'Good switching_id found' )
or explain( $sessions_id[0]->{value}, 'Switching_session_id' );
ok( $sessions_id[1]->{value} eq $id, 'Good Real_session_id found' )
or explain( $sessions_id[1]->{value}, 'Real_session_id' );
or explain( $sessions_id[0]->{value}, 'switching_session_id' );
my @real_values =
map { $_->{key} =~ /^real_/ ? $_ : () } @{ $res->{ATTRIBUTES} };
ok( scalar @real_values == 0, 'No real value found' )
or explain( scalar(@real_values), 'Found real value' );
count(4);
ok(

View File

@ -287,12 +287,14 @@ ok(
'POST switchcontext'
);
# Refresh cookie value
$id = expectCookie($res);
# Get cookie value
my $id1 = expectCookie($res);
ok( $id1 ne $id, 'New SSO session created' )
or explain( $id1, 'New SSO session created' );
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
cookie => "lemonldap=$id1",
accept => 'text/html'
),
'Get Menu',
@ -305,35 +307,37 @@ ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_OFF">%,
ok(
$res = $client->_get(
'/switchcontext',
cookie => "lemonldap=$id",
cookie => "lemonldap=$id1",
accept => 'text/html'
),
'Stop context switching',
);
count(2);
# Refresh cookie value
my $id1 = expectCookie($res);
# Get cookie value
my $id0 = expectCookie($res);
ok( $id0 eq $id, 'New SSO session created' )
or explain( $id0, 'New SSO session created' );
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1",
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
count(3);
expectAuthenticatedAs( $res, 'dwho' );
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_ON">%,
'Found trspan="contextSwitching_ON"' )
or explain( $res->[2]->[0], 'trspan="contextSwitching_ON"' );
count(1);
count(4);
# ContextSwitching form -> PE_OK
# ------------------------
ok(
$res = $client->_get(
'/switchcontext',
cookie => "lemonldap=$id1",
cookie => "lemonldap=$id",
accept => 'text/html'
),
'ContextSwitching form',
@ -349,16 +353,20 @@ ok(
$res = $client->_post(
'/switchcontext',
IO::String->new($query),
cookie => "lemonldap=$id1",
cookie => "lemonldap=$id",
length => length($query),
accept => 'text/html',
),
'POST switchcontext'
);
count(3);
# Refresh cookie value
my $id2 = expectCookie($res);
$client->logout($id1);
ok( $id2 ne $id, 'New SSO session created' )
or explain( $id2, 'New SSO session created' );
$client->logout($id);
ok(
$res = $client->_get(
@ -382,7 +390,7 @@ ok(
),
'Stop context switching',
);
count(6);
count(4);
ok( $res->[2]->[0] =~ m%<span trmsg="1">%, 'Found PE_SESSIONEXPIRED' )
or explain( $res->[2]->[0], 'Session expired' );

View File

@ -263,7 +263,7 @@ qr%<input type="hidden" name="reference1x1" value="RemoveSF-(\d{10})"/>%,
or print STDERR Dumper( $res->[2]->[0] ), time(), " / $1";
ok(
$res->[2]->[0] =~
qr%<p class="notifText">1 expired second factor\(s\) has/have been removed!</p>%,
qr%<p class="notifText">1 expired second factor\(s\) has/have been removed \(\d{10}\)!</p>%,
'Notification message found'
) or print STDERR Dumper( $res->[2]->[0] );
$id = expectCookie($res);
@ -298,7 +298,7 @@ qr%<input type="hidden" name="reference1x2" value="RemoveSF-(\d{10})"/>%,
or print STDERR Dumper( $res->[2]->[0] ), time(), " / $1";
my @notifs =
( $res->[2]->[0] =~
m%<p class="notifText">1 expired second factor\(s\) has/have been removed!</p>%gs
m%<p class="notifText">1 expired second factor\(s\) has/have been removed \((?:myTOTP|\d{10})\)!</p>%gs
);
ok( 2 == @notifs, '2 notifications found' )
or print STDERR Dumper( $res->[2]->[0] );

View File

@ -14,16 +14,17 @@ SKIP: {
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
totp2fSelfRegistration => 1,
totp2fActivation => 1,
totp2fTTL => 120,
sfRemovedMsgRule => '$uid eq "dwho"',
sfRemovedUseNotif => 1,
sfRemovedNotifRef => 'Remov_e_TOTP',
portalMainLogo => 'common/logos/logo_llng_old.png',
notification => 1,
notificationStorage => 'File',
logLevel => 'error',
totp2fSelfRegistration => 1,
totp2fActivation => 1,
totp2fTTL => 120,
sfRemovedMsgRule => '$uid eq "dwho"',
sfRemovedUseNotif => 1,
sfRemovedNotifRef => 'Remov_e_TOTP',
sfRemovedNotifMsg => '_removedSF_ SF removed = _nameSF_',
portalMainLogo => 'common/logos/logo_llng_old.png',
notification => 1,
notificationStorage => 'File',
notificationStorageOptions => { dirName => $main::tmpDir },
oldNotifFormat => 0,
}
@ -153,7 +154,7 @@ qr%<input type="hidden" name="reference1x1" value="Remov-e-TOTP-(\d{10})"/>%,
or print STDERR Dumper( $res->[2]->[0] ), time(), " / $1";
ok(
$res->[2]->[0] =~
qr%<p class="notifText">1 expired second factor\(s\) has/have been removed!</p>%,
qr%<p class="notifText">1 SF removed = myTOTP</p>%,
'Notification message found'
) or print STDERR Dumper( $res->[2]->[0] );
$id = expectCookie($res);

View File

@ -157,7 +157,7 @@ qr%<input type="hidden" name="reference1x1" value="Remove-TOTP-(\d{10})">%,
or print STDERR Dumper( $res->[2]->[0] ), time(), " / $1";
ok(
$res->[2]->[0] =~
qr%<p class="notifText">1 expired second factor\(s\) has/have been removed!</p>%,
qr%<p class="notifText">1 expired second factor\(s\) has/have been removed \(myTOTP\)!</p>%,
'Notification message found'
) or print STDERR Dumper( $res->[2]->[0] );
$id = expectCookie($res);

View File

@ -218,7 +218,7 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
expectOK($res);
ok(
$res->[2]->[0] =~
qr%<h3 trspan="oneExpired2Fremoved">oneExpired2Fremoved</h3>%,
qr%<h3 trspan="oneExpired2Fremoved, \d{10}">oneExpired2Fremoved, \d{10}</h3>%,
'Found expired 2F message'
) or print STDERR Dumper( $res->[2]->[0] );
my $c = getCookies($res);