Merge branch 'v2.0' into 2683

This commit is contained in:
Christophe Maudoux 2022-02-03 21:00:45 +01:00
commit 67aaadf51b
155 changed files with 1489 additions and 377 deletions

View File

@ -61,6 +61,8 @@ build_centos_8:
extends: .build_job
image: buildpkg/centos:8
script:
- sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
- sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
- yum-config-manager --enable PowerTools
- yum-config-manager --enable AppStream
- yum -y install epel-release

View File

@ -10,6 +10,7 @@ Applications
applications/awx
applications/bugzilla
applications/bigbluebutton
applications/confluence
applications/cornerstone
applications/discourse
applications/django
@ -94,6 +95,7 @@ Application Configuration
.. image:: applications/logo-awx.png :doc:`AWX (Ansible Tower)<applications/awx>`
.. image:: applications/bigbluebutton-logo.png :doc:`BigBlueButton<applications/bigbluebutton>`
.. image:: applications/bugzilla_logo.png :doc:`Bugzilla<applications/bugzilla>`
.. image:: applications/confluence.png :doc:`Confluence<applications/confluence>` ✔ ✔
.. image:: applications/csod_logo.png :doc:`Cornerstone<applications/cornerstone>`
.. image:: applications/discourse.jpg :doc:`Discourse<applications/discourse>` ✔ ✔
.. image:: applications/django_logo.png :doc:`Django<applications/django>`

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,65 @@
Confluence
==========
Presentation
------------
Confluence is a web-based corporate wiki developed by Atlassian.
It is compatible with SAML and OpenID Connect. This tutorial will focus on SAML.
Configuration
-------------
You must first configure LemonLDAP::NG as a :doc:`SAML Identity Provider<../idpsaml>`.
Configure SAML in Confluence
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the SSO configuration page, choose SAML as the authentication method. And set the following parameters.
Don't forget to replace ``auth.example.com`` with your actual domain.
* Single sign on issuer: ``https://auth.example.com/saml/metadata``
* Identity provider single sign on URL: ``https://auth.example.com/saml/singleSignOn``
* X.509 certificate: You can find this certificate in the manager: SAML2 Service » Security » Signature » Public key
* Username mapping attribute: ``${uid}``
.. danger:: Make sure the certificate you copy into Confluence starts with BEGIN CERTIFICATE and not with BEGIN PRIVATE KEY
Write down the *Assertion Consumer Service URL* and the *Audience URL*, that Confluence is showing you, you will need it to configure LemonLDAP::NG
Configure LemonLDAP::NG
~~~~~~~~~~~~~~~~~~~~~~~
In the LemonLDAP::NG Manager, create a new *SAML Service Provider*
In *Metadata*, copy the following XML document, and don't forget to change ``AUDIENCE_URL`` and ``CONSUMER_SERVICE_URL`` the URLs with the values given by Confluence.
::
<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="AUDIENCE_URL">
<md:SPSSODescriptor
AuthnRequestsSigned="false"
WantAssertionsSigned="false"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="CONSUMER_SERVICE_URL"
index="1"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>
In *Exported Attributes*, add a new attribute:
* Variable name: the session variable containing user logins
* Attribute name: ``uid``
* Mandatory: ``On``
Finally, in *Options* » *Signature*, set
* Check SSO message signature: Off
* Check SLO message signature: Off

View File

@ -4,8 +4,8 @@ Error messages
.. note::
This page do not reference all error messages, but only the
most common
This page does not reference all error messages,
but only the most common ones
Lemonldap::NG::Common
---------------------
@ -140,3 +140,10 @@ set ``*`` in trustedDomains to accept all).
XSS attack detected
→ Some URL parameters contain forbidden characters.
::
Detailled error codes list
→ Corresponding error codes can be found in
:doc:`Portal error codes<error_codes>`

View File

@ -0,0 +1,113 @@
Error codes list
================
.. note::
This page references all Portal error codes.
```
PE_IDPCHOICE => -5,
PE_SENDRESPONSE => -4,
PE_INFO => -3,
PE_REDIRECT => -2,
PE_DONE => -1,
PE_OK => 0,
PE_SESSIONEXPIRED => 1,
PE_FORMEMPTY => 2,
PE_WRONGMANAGERACCOUNT => 3,
PE_USERNOTFOUND => 4,
PE_BADCREDENTIALS => 5,
PE_LDAPCONNECTFAILED => 6,
PE_LDAPERROR => 7,
PE_APACHESESSIONERROR => 8,
PE_FIRSTACCESS => 9,
PE_BADCERTIFICATE => 10,
PE_NO_PASSWORD_BE => 20,
PE_PP_ACCOUNT_LOCKED => 21,
PE_PP_PASSWORD_EXPIRED => 22,
PE_CERTIFICATEREQUIRED => 23,
PE_ERROR => 24,
PE_PP_CHANGE_AFTER_RESET => 25,
PE_PP_PASSWORD_MOD_NOT_ALLOWED => 26,
PE_PP_MUST_SUPPLY_OLD_PASSWORD => 27,
PE_PP_INSUFFICIENT_PASSWORD_QUALITY => 28,
PE_PP_PASSWORD_TOO_SHORT => 29,
PE_PP_PASSWORD_TOO_YOUNG => 30,
PE_PP_PASSWORD_IN_HISTORY => 31,
PE_PP_GRACE => 32,
PE_PP_EXP_WARNING => 33,
PE_PASSWORD_MISMATCH => 34,
PE_PASSWORD_OK => 35,
PE_NOTIFICATION => 36,
PE_BADURL => 37,
PE_NOSCHEME => 38,
PE_BADOLDPASSWORD => 39,
PE_MALFORMEDUSER => 40,
PE_SESSIONNOTGRANTED => 41,
PE_CONFIRM => 42,
PE_MAILFORMEMPTY => 43,
PE_BADMAILTOKEN => 44,
PE_MAILERROR => 45,
PE_MAILOK => 46,
PE_LOGOUT_OK => 47,
PE_SAML_ERROR => 48,
PE_SAML_LOAD_SERVICE_ERROR => 49,
PE_SAML_LOAD_IDP_ERROR => 50,
PE_SAML_SSO_ERROR => 51,
PE_SAML_UNKNOWN_ENTITY => 52,
PE_SAML_DESTINATION_ERROR => 53,
PE_SAML_CONDITIONS_ERROR => 54,
PE_SAML_IDPSSOINITIATED_NOTALLOWED => 55,
PE_SAML_SLO_ERROR => 56,
PE_SAML_SIGNATURE_ERROR => 57,
PE_SAML_ART_ERROR => 58,
PE_SAML_SESSION_ERROR => 59,
PE_SAML_LOAD_SP_ERROR => 60,
PE_SAML_ATTR_ERROR => 61,
PE_OPENID_EMPTY => 62,
PE_OPENID_BADID => 63,
PE_MISSINGREQATTR => 64,
PE_BADPARTNER => 65,
PE_MAILCONFIRMATION_ALREADY_SENT => 66,
PE_PASSWORDFORMEMPTY => 67,
PE_CAS_SERVICE_NOT_ALLOWED => 68,
PE_MAILFIRSTACCESS => 69,
PE_MAILNOTFOUND => 70,
PE_PASSWORDFIRSTACCESS => 71,
PE_MAILCONFIRMOK => 72,
PE_RADIUSCONNECTFAILED => 73,
PE_MUST_SUPPLY_OLD_PASSWORD => 74,
PE_FORBIDDENIP => 75,
PE_CAPTCHAERROR => 76,
PE_CAPTCHAEMPTY => 77,
PE_REGISTERFIRSTACCESS => 78,
PE_REGISTERFORMEMPTY => 79,
PE_REGISTERALREADYEXISTS => 80,
PE_NOTOKEN => 81,
PE_TOKENEXPIRED => 82,
PE_U2FFAILED => 83,
PE_UNAUTHORIZEDPARTNER => 84,
PE_RENEWSESSION => 85,
PE_WAIT => 86,
PE_MUSTAUTHN => 87,
PE_MUSTHAVEMAIL => 88,
PE_SAML_SERVICE_NOT_ALLOWED => 89,
PE_OIDC_SERVICE_NOT_ALLOWED => 90,
PE_OID_SERVICE_NOT_ALLOWED => 91,
PE_GET_SERVICE_NOT_ALLOWED => 92,
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
PE_ISSUERMISSINGREQATTR => 94,
PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED => 95,
PE_BADOTP => 96,
PE_RESETCERTIFICATE_INVALID => 97,
PE_RESETCERTIFICATE_FORMEMPTY => 98,
PE_RESETCERTIFICATE_FIRSTACCESS => 99,
PE_PP_NOT_ALLOWED_CHARACTER => 100,
PE_PP_NOT_ALLOWED_CHARACTERS => 101,
PE_UPGRADESESSION => 102,
PE_NO_SECOND_FACTORS => 103,
PE_BAD_DEVOPS_FILE => 104,
PE_FILENOTFOUND => 105,
PE_OIDC_AUTH_ERROR => 106
```

View File

@ -339,14 +339,14 @@ Options
- **Authentication Level**: required authentication level to access this application
- **Access Rule**: lets you specify a :doc:`Perl rule<rules_examples>` to restrict access to this client
- **Logout**
- **Logout**
- **Allowed redirection addresses for logout**: A space separated list of
URLs that this client can redirect the user to once the logout is done
(through ``post_logout_redirect_uri``)
- **URL**: Specify the relying party's logout URL
- **Type**: Type of Logout to perform (only Front-Channel is implemented for now)
- **Session required**: Whether to send the Session ID in the logout request
- **Allowed redirection addresses for logout**: A space separated list of
URLs that this client can redirect the user to once the logout is done
(through ``post_logout_redirect_uri``)
- **URL**: Specify the relying party's logout URL
- **Type**: Type of Logout to perform (only Front-Channel is implemented for now)
- **Session required**: Whether to send the Session ID in the logout request
Access Rule extra variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -4,11 +4,14 @@ Advanced features
.. toctree::
:maxdepth: 1
rbac
ssoaas
servertoserver
riskbased
smtp
notifications
passwordstore
cda
rbac
customfunctions
extendedfunctions
resetpassword
@ -16,8 +19,6 @@ Advanced features
logoutforward
securetoken
handlerauthbasic
ssoaas
servertoserver
safejail
loginhistory
fastcgi

View File

@ -12,4 +12,5 @@ Exploitation
monitoring
logs
error
error_codes
highavailability

View File

@ -83,20 +83,19 @@ Then, add the official LL::NG repository
::
# LemonLDAP::NG repository
deb https://lemonldap-ng.org/deb stable main
deb-src https://lemonldap-ng.org/deb stable main
deb https://lemonldap-ng.org/deb 2.0 main
.. tip::
- Use the ``stable`` repository to get packages from current major
version
- Use the ``oldstable`` repository to get packages from previous major
version
- Use the ``testing`` repository to get packages from next major
version
- Use the ``2.0`` repository to avoid upgrade to next major version
- Use the ``2.0`` repository to stay on this major version and avoid
upgrade to next major version
Finally update your APT cache:

View File

@ -44,7 +44,7 @@ The JSON response fields are:
- ``result``: authentication result, ``0`` if it fails, ``1`` if it
succeed
- ``error``: error code, the corresponding error can be found in
``Lemonldap::NG::Portal::Main::Constants``
:doc:`Portal error codes<error_codes>`
- ``id``: if authentication succeed, the session id is returned in this
field

View File

@ -18,6 +18,7 @@ Sessions for connected users (used by :doc:`LLNG Proxy<authproxy>`):
- GET /session/my/<type> : get session datas
- GET /session/my/<type>/key : get session key
- DELETE /session/my : ask for logout
- DELETE /sessions/my : ask for global logout (if GlobalLogout plugin is on)
Services for connected users (always enabled):

View File

@ -0,0 +1,77 @@
Risk-based Authentication
=========================
Our definition
--------------
Risk-based authentication is the ability to take into account the context of
the authentication process, and react accordingly, by increasing the
authentication challenge (second factor, email confirmation) or trigger out of
band actions (email notifications, alerts..).
.. warning::
All the features presented on this page are not natively supported by
LemonLDAP::NG but can be added through custom plugins or configuration
The authentication context can include:
* Source IP address
* Access time
* Previous authentications (history)
* Using the same browser as previous logins
Reactions can include:
* Triggering or skipping the second factor
* Sending an email to warn the user of a suspicious login
* Denying attempt if the suspicion level is too high
Implementation in LemonLDAP::NG
-------------------------------
LemonLDAP::NG uses the ``_riskLevel`` and ``_riskDetails`` session variables to
keep track of the risk associated to the current authentication.
Detection plugins will raise or lower the risk level, and store fine-grained
details in the risk details object.
Action plugins may use the risk level to trigger certain actions, and can
translate the risk detail items into user-friendly messages.
Compatible plugins
------------------
Detection
~~~~~~~~~
New location warning
^^^^^^^^^^^^^^^^^^^^
.. versionadded:: 2.0.14
The :doc:`New Location warning <newlocationwarning>` plugin will increase the risk level by 1 when triggered, and will store the **Session attribute to display** in ``$_riskDetail->{newLocation}``.
Action
~~~~~~
Forbidding/triggering second factors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can use the following activation rule to trigger second factors if the risk level is high::
$_riskLevel > 0
Or, if you use self registration::
has2f('TOTP') and $_riskLevel > 0
Denying login
^^^^^^^^^^^^^
You can use :doc:`session opening conditions <grantsession>` to deny access if the risk level is too high with a rule like this ::
$_riskLevel < 2
This will forbid sessions from being opened if the risk level is greater or equal to 2

View File

@ -43,7 +43,7 @@ Registration on first use
If you want to force a 2F registration on first login, you can use the *Force
2FA registration at login* option.
You can use a `rule<writingrulesand_headers>` to enable this behavior only for
You can use a :doc:`rule <writingrulesand_headers>` to enable this behavior only for
some users.
Session upgrade through 2FA

View File

@ -7,7 +7,7 @@ Our concept of SSOaaS
Access management provides 3 services:
- Global Authentication: Single Sign-On
- Authorization: to grant authentication is not enough. User rights
- Authorization: Grant authentication is not enough. User rights
must be checked
- Accounting: SSO logs (access) + application logs *(transactions and
results)*
@ -25,13 +25,13 @@ the ability for an app to manage authorizations and choose user
attributes to set. Authentication can not be really ``*aaS``: app must
just use it, not manage it.
LL::NG affords some features that can be used to provide SSO as a
service: a web application can manage its rules and headers. Docker or
LL::NG affords some features that can be used for providing SSO as a
Service: a web application can manage its rules and headers. Docker or
VM images (Nginx only) includes LL::NG Nginx configuration that aims to
a global
:ref:`LL::NG authorization server<platformsoverview-external-servers-for-nginx>`.
By default, all authenticated users can access and one header is set:
``Auth-User``. If application gives a RULES_URL parameter that refers to
``Auth-User``. If application defines a RULES_URL parameter that refers to
a JSON file, authorization server will read it, apply specified rules
and set required headers (see :doc:`DevOps Handler<devopshandler>`).
@ -41,6 +41,16 @@ There are two different architectures to do this:
- Using front reverse-proxies *(some cloud installations use
reverse-proxies in front-end)*
.. note::
Some requests can be dropped by the FastCGI/uWSGI server.
Example below with uWSGI server to avoid Load Balancer health check requests
being forwarded to DevOps Handler:
```route-remote-addr = ^127\.0\.0\.25[34]$ break: 403 Forbidden for IP ${REMOTE_ADDR}```
Example of a global FastCGI architecture:
|image0|
@ -56,8 +66,9 @@ Using a global FastCGI (or uWSGI) server
Nginx
^^^^^
In this example, web server templates (Nginx only) are configured to
request authorization from a central FastCGI server:
Examples below are web server templates (Nginx only) configured to
request authorization from a central FastCGI server.
With an uWSGI central server, use 'uwsgi_param' directive (Nginx only):
.. code::
@ -78,7 +89,11 @@ request authorization from a central FastCGI server:
# Keep original request (LLNG server will received /lmauth)
fastcgi_param X_ORIGINAL_URI $original_uri;
# Set dynamically rules (LLNG will poll it every 10 mn)
# Set redirection params
fastcgi_param HTTPS_REDIRECT "$https";
fastcgi_param PORT_REDIRECT $server_port;
# Set dynamically rules (LL::NG will poll it every 10 mn)
fastcgi_param RULES_URL http://rulesserver/my.json;
}
location /rules.json {
@ -107,22 +122,22 @@ Apache
^^^^^^
There is an experimental FastCGI client in LL::NG. You just have to
install FCGI::Client and add this in the apache2.conf or your web
applications or proxies.
install LemonLDAP::NG handler and FCGI::Client. Then, add this in
your apache2.conf, web applications or reverse-proxies.
The following configuration example assumes that you are in a "central
FastCGI" configuration.
.. code-block:: apache
<VirtualHost ...>
<VirtualHost port>
ServerName app.tls
PerlHeaderParserHandler Lemonldap::NG::Handler::ApacheMP2::FCGIClient
# This must point to the central FastCGI server
PerlSetVar LLNG_SERVER 192.0.2.1:9090
# Declare this vhost as a DevOps vhost, so that we do not have
# Declare this vhost as a DevOps protected vhost. So you do not have
# to declare it in the LemonLDAP::NG Manager
PerlSetVar VHOSTTYPE DevOps
@ -130,6 +145,8 @@ FastCGI" configuration.
# used to make the authentication decision about this virtualhost
# Make sure the central FastCGI server can reach it
PerlSetVar RULES_URL http://app.tld/rules.json
PerlSetVar HTTPS_REDIRECT HTTPS
PerlSetVar PORT_REDIRECT SERVER_PORT
...
</VirtualHost>
@ -150,6 +167,8 @@ you can protect also an Express server. Example:
port: 9090,
PARAMS: {
RULES_URL: 'http://my-server/rules.json'
HTTPS_REDIRECT: 'ON',
PORT_REDIRECT: '443'
}
});
@ -196,6 +215,8 @@ Simple example:
port => '9090',
fcgi_auth_params => {
RULES_URL => 'https://my-server/my.json',
HTTPS_REDIRECT => 'ON',
PORT_REDIRECT => 443
},
# Optional rejection subroutine
#on_reject => \&on_reject;
@ -221,6 +242,7 @@ directory.
.. code-block:: nginx
server {
listen <port>;
server_name "~^(?<vhost>.+?)\.dev\.sso\.my\.domain$";
location = /lmauth {
internal;
@ -235,6 +257,9 @@ directory.
fastcgi_param HOST $http_host;
# Keep original request (LL::NG server will received /lmauth)
fastcgi_param X_ORIGINAL_URI $original_uri;
# Set redirection params
fastcgi_param HTTPS_REDIRECT "$https";
fastcgi_param PORT_REDIRECT $server_port;
}
location /rules.json {
auth_request off;
@ -253,4 +278,3 @@ directory.
}
.. |image0| image:: /documentation/devops.png

View File

@ -154,6 +154,11 @@ If you defined the "Register page URL" or the password "Reset page URL" to an ex
Manager API
~~~~~~~~~~~
The service parameter set in a request to create or update a CAS application must now be an array, and no more a string.
Changes impacting plugin developpers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -1397,7 +1397,7 @@ components:
type: object
properties:
service:
type: string
type: array
userAttribute:
type: string
default: none

View File

@ -5,7 +5,7 @@ use Mouse;
use Safe;
use constant PE_OK => 0;
our $VERSION = '2.0.6';
our $VERSION = '2.0.14';
# Handle "if then else" (used during init)
# return a sub that can be called with ($req) to get a [array] of combination
@ -92,10 +92,12 @@ sub parseAnd {
$str{$r}++;
}
else {
return ( $r, $name ) unless ( $r == PE_OK );
return ( wantarray ? ( $r, $name ) : $r )
unless ( $r == PE_OK );
}
}
return ( ( %str ? join( ',', keys %str ) : PE_OK ), $expr );
my $res = %str ? join( ',', keys %str ) : PE_OK;
return wantarray ? ( $res, $expr ) : $res;
};
}
return \@res;
@ -135,7 +137,8 @@ sub parseMod {
my ($m) = @mods;
return sub {
my $sub = shift;
return ( $m->$sub(@_), $expr );
my $res = $m->$sub(@_);
return wantarray ? ( $res, $expr ) : $res;
};
}
return sub {
@ -149,10 +152,12 @@ sub parseMod {
$str{$res}++;
}
else {
return ( $res, $list[$i] ) unless ( $res == PE_OK );
return ( wantarray ? ( $res, $list[$i] ) : $res )
unless ( $res == PE_OK );
}
}
return ( ( %str ? join( ',', keys %str ) : PE_OK ), $expr );
my $res = %str ? join( ',', keys %str ) : PE_OK;
return wantarray ? ( $res, $expr ) : $res;
};
}

View File

@ -14,7 +14,7 @@ use MIME::Base64;
use Safe;
use Encode;
our $VERSION = '2.0.9';
our $VERSION = '2.0.14';
my $dataStart = tell(DATA);

View File

@ -18,7 +18,7 @@ our $VERSION = '2.0.12';
# Not that only functions, not methods, can be written here
our $functions =
[
qw(&checkLogonHours &date &dateToTime &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri &has2f)
qw(&checkLogonHours &date &dateToTime &checkDate &basic &unicode2iso &iso2unicode &groupMatch &isInNet6 &varIsInUri &has2f_internal)
];
## @function boolean checkLogonHours(string logon_hours, string syntax, string time_correction, boolean default_access)
@ -244,7 +244,7 @@ sub varIsInUri {
my $json = JSON::XS->new;
sub has2f {
sub has2f_internal {
my ( $session, $type ) = @_;
return 0 unless $session->{_2fDevices};

View File

@ -5,7 +5,7 @@ use Mouse;
use Lemonldap::NG::Common::Conf::Constants;
use JSON qw(from_json to_json);
our $VERSION = '2.0.9';
our $VERSION = '2.0.14';
has sessionTypes => ( is => 'rw' );
@ -293,4 +293,9 @@ sub getMod {
return $m;
}
sub getGlobal {
my ( $self ) = @_;
return $self->sessionTypes->{global};
}
1;

View File

@ -10,7 +10,7 @@ use Crypt::URandom;
use Digest::HMAC_SHA1 'hmac_sha1_hex';
use Lemonldap::NG::Common::Crypto;
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
has 'key' => (
is => 'ro',

View File

@ -21,7 +21,7 @@ use constant REDIRECT => Apache2::Const::REDIRECT;
use constant DECLINED => Apache2::Const::DECLINED;
use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR;
our $VERSION = '2.0.6';
our $VERSION = '2.0.14';
sub handler {
my ( $class, $r ) = @_;
@ -43,7 +43,7 @@ sub handler {
SERVER_PORT => $r->get_server_port,
REQUEST_METHOD => $r->method,
};
foreach (qw(VHOSTTYPE RULES_URL)) {
foreach (qw(VHOSTTYPE RULES_URL HTTPS_REDIRECT PORT_REDIRECT)) {
if ( my $t = $r->dir_config($_) ) {
$env->{$_} = $t;
}

View File

@ -94,6 +94,10 @@ q"I refuse to compile 'rules.json' when useSafeJail isn't activated! Yes I know,
$class->locationRulesInit( undef, { $vhost => $json->{rules} } );
$class->headersInit( undef, { $vhost => $json->{headers} } );
$class->tsv->{lastVhostUpdate}->{$vhost} = time;
$class->tsv->{https}->{$vhost} = uc $req->env->{HTTPS_REDIRECT} eq 'ON'
if exists $req->env->{HTTPS_REDIRECT};
$class->tsv->{port}->{$vhost} = $req->env->{PORT_REDIRECT}
if exists $req->env->{PORT_REDIRECT};
return;
}

View File

@ -3,7 +3,7 @@ use Lemonldap::NG::Common::JWT qw(getAccessTokenSessionId);
use strict;
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
sub retrieveSession {
my ( $class, $req, $id ) = @_;

View File

@ -5,7 +5,7 @@ use Mouse;
#use Lemonldap::NG::Handler::Main qw(:jailSharedVars);
our $VERSION = '2.0.11';
our $VERSION = '2.0.14';
has protection => ( is => 'rw', isa => 'Str' );
has rule => ( is => 'rw', isa => 'Str' );
@ -128,7 +128,7 @@ sub _authAndTrace {
eval "require $type";
die $@ if ($@);
my ( $res, $session ) = $type->run( $req, $self->{rule} );
eval { $self->portal( $type->tsv->{portal}->() ) };
eval { $self->portal( $type->tsv->{portal}->() ) } unless $self->portal;
$self->logger->warn($@) if $@;
$req->userData($session) if ($session);
@ -201,7 +201,7 @@ sub userId {
my $userId =
$req->userData->{ $Lemonldap::NG::Handler::Main::tsv->{whatToTrace}
|| '_whatToTrace' }
|| $req->userData->{'_user'} # Fix 2377
|| $req->userData->{'_user'} # Fix 2377
|| 'anonymous';
$self->logger->debug("Returned userId: $userId");

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Handler::Main::Reload;
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
package Lemonldap::NG::Handler::Main;
@ -65,7 +65,7 @@ sub checkConf {
or $class->cfgNum != $conf->{cfgNum}
or $class->cfgDate != $conf->{cfgDate} )
{
$class->logger->debug("Get configuration $conf->{cfgNum}");
$class->logger->debug("Get configuration $conf->{cfgNum} aged $conf->{cfgDate}");
unless ( $class->cfgNum( $conf->{cfgNum} )
&& $class->cfgDate( $conf->{cfgDate} ) )
{
@ -658,7 +658,7 @@ sub substitute {
$expr =~ s/\binGroup\(([^)]*)\)/listMatch(\$s->{'hGroups'},$1,1)/g;
# handle has2f
$expr =~ s/\bhas2f\(([^),]*)\)/has2f(\$s,$1)/g;
$expr =~ s/\bhas2f\(([^),]*)\)/has2f_internal(\$s,$1)/g;
return $expr;
}

View File

@ -9,7 +9,7 @@ use Lemonldap::NG::Handler::PSGI::Main;
extends 'Lemonldap::NG::Handler::Lib::PSGI', 'Lemonldap::NG::Common::PSGI';
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
sub init {
my ( $self, $args ) = @_;

View File

@ -3,7 +3,7 @@ package Lemonldap::NG::Handler::PSGI::Try;
use strict;
use Mouse;
our $VERSION = '2.0.6';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Handler::PSGI::Router';

View File

@ -69,7 +69,7 @@ ok(
ok( $res = &$code, "Function works" );
ok( $res == 1, 'Get good result' );
$sub = "sub { return(has2f(\$_[0],\$_[1])) }";
$sub = "sub { return(has2f_internal(\$_[0],\$_[1])) }";
$code = $jail->jail_reval($sub);
ok(
( defined($code) and ref($code) eq 'CODE' ),

View File

@ -62,7 +62,7 @@ ok( ( defined($listMatch) and ref($listMatch) eq 'CODE' ),
ok( &$listMatch eq '0', 'Get good result' );
# Test has2f method
my $sub7 = "sub { return(has2f(\$_[0],\$_[1])) }";
my $sub7 = "sub { return(has2f_internal(\$_[0],\$_[1])) }";
my $has2f = $jail->jail_reval($sub7);
ok(
( defined($has2f) and ref($has2f) eq 'CODE' ),

View File

@ -11,9 +11,11 @@ BEGIN {
init(
'Lemonldap::NG::Handler::Server',
{
#logLevel => 'debug',
#logLevel => 'debug',
vhostOptions => {
'test3.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostDevOpsRulesUrl =>
'http://donotuse.example.com/myfile.json',
},
@ -23,6 +25,42 @@ init(
my $res;
# Unauthorized queries
ok(
$res = $client->_get(
'/', undef,
'test3.example.com', undef,
VHOSTTYPE => 'DevOps',
RULES_URL => 'http://devops.example.com/file.json'
),
'Unauthorized query'
);
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
${ $res->[1] }[1] =~ m#http://auth\.example\.com/\?url=(.+?)%#;
ok( decode_base64 $1 eq 'http://test3.example.com/', 'Redirect URL found' )
or explain( decode_base64 $1, 'http://test3.example.com/' );
count(3);
Time::Fake->offset("+700s");
ok(
$res = $client->_get(
'/', undef,
'test3.example.com', undef,
HTTPS_REDIRECT => 'on',
PORT_REDIRECT => 8443,
VHOSTTYPE => 'DevOps',
RULES_URL => 'http://devops.example.com/file.json'
),
'Unauthorized query 2'
);
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
${ $res->[1] }[1] =~ m#http://auth\.example\.com/\?url=(.+?)%#;
ok( decode_base64 $1 eq 'https://test3.example.com:8443/',
'Redirect URL found' )
or explain( decode_base64 $1, 'https://test3.example.com:8443/' );
count(3);
# Authorized queries
ok(
$res = $client->_get(

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Manager::Api::Common;
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
package Lemonldap::NG::Manager::Api;
@ -110,6 +110,9 @@ sub _translateValueConfToApi {
elsif ( $optionName eq "oidcRPMetaDataOptionsAdditionalAudiences" ) {
return [ split( /\s+/, $optionValue, ) ];
}
elsif ( $optionName eq "casAppMetaDataOptionsService" ) {
return [ split( /\s+/, $optionValue, ) ];
}
else {
return $optionValue;
}
@ -134,7 +137,14 @@ sub _translateValueApiToConf {
# additionalAudiences is handled as an array
elsif ( $optionName eq 'additionalAudiences' ) {
die "postLogoutRedirectUris is not an array\n"
die "additionalAudiences is not an array\n"
unless ( ref($optionValue) eq "ARRAY" );
return join( ' ', @{$optionValue} );
}
# service is handled as an array
elsif ( $optionName eq 'service' ) {
die "service is not an array\n"
unless ( ref($optionValue) eq "ARRAY" );
return join( ' ', @{$optionValue} );
}

View File

@ -1,6 +1,6 @@
package Lemonldap::NG::Manager::Api::Providers::CasApp;
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
package Lemonldap::NG::Manager::Api;
@ -109,9 +109,9 @@ sub addCasApp {
return $self->sendError( $req, 'Invalid input: service is missing', 400 )
unless ( defined $add->{options}->{service} );
return $self->sendError( $req, 'Invalid input: service is not a string',
return $self->sendError( $req, 'Invalid input: service must be an array',
400 )
if ( ref $add->{options}->{service} );
unless ( ref $add->{options}->{service} eq "ARRAY" );
$self->logger->debug(
"[API] Add CAS App with confKey $add->{confKey} requested");
@ -125,18 +125,18 @@ sub addCasApp {
409
) if ( defined $self->_getCasAppByConfKey( $conf, $add->{confKey} ) );
my $res =
$self->_getCasAppByServiceUrl( $conf, $add->{options}->{service} );
if ( defined $res ) {
my $conflict = $res->{options}->{service};
return $self->sendError(
$req,
"Invalid input: A CAS application with service URL $conflict already exists",
409
);
for my $serviceUrl ( @{ $add->{options}->{service} } ) {
my $res = $self->_getCasAppByServiceUrl( $conf, $serviceUrl );
if ( defined $res ) {
return $self->sendError(
$req,
"Invalid input: A CAS application with service URL $serviceUrl already exists",
409
);
}
}
$res = $self->_pushCasApp( $conf, $add->{confKey}, $add, 1 );
my $res = $self->_pushCasApp( $conf, $add->{confKey}, $add, 1 );
return $self->sendError( $req, $res->{msg}, 400 )
unless ( $res->{res} eq 'ok' );
@ -285,12 +285,19 @@ sub _getCasAppByServiceUrl {
my ($serviceHost) = $serviceUrl =~ m#^(https?://[^/]+)(?:/.*)?$#;
return undef unless $serviceHost;
foreach ( keys %{ $conf->{casAppMetaDataOptions} } ) {
my $url =
$conf->{casAppMetaDataOptions}->{$_}->{casAppMetaDataOptionsService};
my ($curHost) = $url =~ m#^(https?://[^/]+)(?:/.*)?$#;
if ( $serviceHost eq $curHost ) {
return $self->_getCasAppByConfKey( $conf, $_ );
for my $confKey ( keys %{ $conf->{casAppMetaDataOptions} } ) {
for my $url (
split(
/\s+/,
$conf->{casAppMetaDataOptions}->{$confKey}
->{casAppMetaDataOptionsService}
)
)
{
my ($curHost) = $url =~ m#^(https?://[^/]+)(?:/.*)?$#;
if ( $serviceHost eq $curHost ) {
return $self->_getCasAppByConfKey( $conf, $confKey );
}
}
}
@ -301,14 +308,29 @@ sub _isNewCasAppServiceUrlUnique {
my ( $self, $conf, $confKey, $casApp ) = @_;
my $curServiceUrl =
$self->_getCasAppByConfKey( $conf, $confKey )->{options}->{service};
my $newServiceUrl = $casApp->{options}->{service} || "";
if ( $newServiceUrl ne '' && $newServiceUrl ne $curServiceUrl ) {
# Check service paramater
unless ( ref $casApp->{options}->{service} eq "ARRAY" ) {
return {
res => 'ko',
msg =>
res => 'ko',
msg => "The parameter 'service' must be an array",
};
}
my $newService = $casApp->{options}->{service} || [];
for my $newServiceUrl (@$newService) {
if ( $newServiceUrl ne ''
&& !grep( /^$newServiceUrl$/, @$curServiceUrl ) )
{
return {
res => 'ko',
msg =>
"A CAS application with service URL '$newServiceUrl' already exists"
}
if ( defined $self->_getCasAppByServiceUrl( $conf, $newServiceUrl ) );
}
if (
defined $self->_getCasAppByServiceUrl( $conf, $newServiceUrl )
);
}
}
return { res => 'ok' };

View File

@ -748,7 +748,7 @@ sub attributes {
'type' => 'text'
},
'casAppMetaDataOptionsService' => {
'type' => 'url'
'type' => 'text'
},
'casAppMetaDataOptionsUserAttribute' => {
'type' => 'text'

View File

@ -2526,7 +2526,7 @@ sub attributes {
documentation => 'CAS exported variables',
},
casAppMetaDataOptionsService => {
type => 'url',
type => 'text',
documentation => 'CAS App service',
},
casAppMetaDataOptionsUserAttribute => {

View File

@ -24,7 +24,7 @@ extends qw(
Lemonldap::NG::Common::Conf::RESTServer
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
#############################
# I. INITIALIZATION METHODS #

View File

@ -891,25 +891,32 @@ sub tests {
my %casUrl;
foreach my $casConfKey ( keys %{ $conf->{casAppMetaDataOptions} } )
{
my $appUrl =
$conf->{casAppMetaDataOptions}->{$casConfKey}
->{casAppMetaDataOptionsService}
|| "";
$appUrl =~ m#^(https?://[^/]+)(/.*)?$#;
my $appHost = $1;
unless ($appHost) {
push @msg, "$casConfKey CAS Application has no Service URL";
$res = 0;
next;
}
for my $appUrl (
split(
/\s+/,
$conf->{casAppMetaDataOptions}->{$casConfKey}
->{casAppMetaDataOptionsService}
)
)
{
$appUrl ||= "";
$appUrl =~ m#^(https?://[^/]+)(/.*)?$#;
my $appHost = $1;
unless ($appHost) {
push @msg,
"$casConfKey CAS Application has no Service URL";
$res = 0;
next;
}
if ( defined $casUrl{$appUrl} ) {
push @msg,
if ( defined $casUrl{$appUrl} ) {
push @msg,
"$casConfKey and $casUrl{$appUrl} have the same Service URL";
$res = 0;
next;
$res = 0;
next;
}
$casUrl{$appUrl} = $casConfKey;
}
$casUrl{$appUrl} = $casConfKey;
}
return ( $res, join( ', ', @msg ) );
},
@ -919,7 +926,9 @@ sub tests {
return 1 unless ( $conf->{sfRemovedMsgRule} );
return ( 1,
'Notification system must be enabled to display a notification if a SF is removed'
) if ( $conf->{sfRemovedUseNotif} and not $conf->{notification} );
)
if ( $conf->{sfRemovedUseNotif}
and not $conf->{notification} );
return 1;
},
@ -936,7 +945,8 @@ sub tests {
# Same with SameSite=(auto) and SAML issuer in use
SameSiteNoneWithSecure => sub {
return ( -1, 'SameSite value = None requires the secured flag' )
if ( getSameSite($conf) eq 'None' and !$conf->{securedCookie} );
if ( getSameSite($conf) eq 'None'
and !$conf->{securedCookie} );
return 1;
},

View File

@ -167,7 +167,7 @@
"casStorage":"CAS oturumları modül adı",
"casStorageOptions":"CAS oturumları modül seçenekleri",
"casStrictMatching":"Katı URL eşleşmesi kullan",
"casTicketExpiration":"Temporary ticket lifetime",
"casTicketExpiration":"Geçici bilet ömrü",
"categoryName":"Kategori ismi",
"cda":"Çoklu alan adları",
"certificateMailContent":"E-posta içeriği",
@ -183,7 +183,7 @@
"cfgLog":"Özet",
"cfgVersion":"Yapılandırma sürümü",
"checkDevOps":"Aktivasyon",
"checkDevOpsCheckSessionAttributes":"Check session attributes",
"checkDevOpsCheckSessionAttributes":"Oturum niteliklerini kontrol et",
"checkDevOpsDisplayNormalizedHeaders":"Normalleştirilmiş başlıkları görüntüle",
"checkDevOpsDownload":"Dosyayı indir",
"checkState":"Aktivasyon",
@ -356,7 +356,7 @@
"facebookExportedVars":"Dışa aktarılan değişkenler",
"facebookParams":"Facebook parametreleri",
"facebookUserField":"Alan kullanıcı kimliği içeriyor",
"failedLoginNumber":"Max failed logins count",
"failedLoginNumber":"Maksimum başarısız giriş sayısı",
"fileToUpload":"Yüklenecek dosya",
"findUser":"Aktivasyon",
"findUserControl":"Parametre kontrolü",
@ -662,7 +662,7 @@
"oidcParams":"OpenID Connect parametreleri",
"oidcRP":"OpenID Connect Relying Party",
"oidcRPCallbackGetParam":"GET parametresini geri çağır",
"oidcRPMetaDataExportedVars":"Exported attributes (claims)",
"oidcRPMetaDataExportedVars":"Dışa aktarılan nitelikler (talepler)",
"oidcRPMetaDataMacros":"Makrolar",
"oidcRPMetaDataNode":"OpenID Connect Relying Parties",
"oidcRPMetaDataNodes":"OpenID Connect Relying Parties",
@ -684,7 +684,7 @@
"oidcRPMetaDataOptionsClientSecret":"İstemci sırrı",
"oidcRPMetaDataOptionsDisplay":"Görüntüle",
"oidcRPMetaDataOptionsDisplayName":"Görüntülenen ad",
"oidcRPMetaDataOptionsExtraClaims":"Scope values content",
"oidcRPMetaDataOptionsExtraClaims":"Kapsam değerleri içeriği",
"oidcRPMetaDataOptionsIDTokenExpiration":"ID Jetonu sona erme",
"oidcRPMetaDataOptionsIDTokenForceClaims":"ID Jetonunda özelliklerin yayınlanmasını zorla",
"oidcRPMetaDataOptionsIDTokenSignAlg":"ID Token imzalama algoritması",
@ -1115,7 +1115,7 @@
"storePassword":"Kullanıcı parolasını oturumda sakla",
"string":"Dize",
"subtitle":"Altyazı",
"successLoginNumber":"Max successful logins count",
"successLoginNumber":"Maksimum başarılı giriş sayısı",
"successfullySaved":"Başarıyla kaydedildi",
"sympaHandler":"Sympa",
"sympaMailKey":"E-posta oturum anahtarı",
@ -1133,7 +1133,7 @@
"totp2fActivation":"Aktivasyon",
"totp2fAuthnLevel":"Doğrulama seviyesi",
"totp2fDigits":"Rakam sayısı",
"totp2fEncryptSecret":"Encrypt TOTP secrets",
"totp2fEncryptSecret":"TOTP sırlarını şifreleyin",
"totp2fInterval":"Süre aralığı",
"totp2fIssuer":"Düzenleyici adı",
"totp2fLabel":"Etiket",

View File

@ -28,7 +28,7 @@
<div class="col-lg-6 col-md-6 col-sm-8 col-xs-14" >
<form class="navbar-form" role="search">
<div class="input-group add-on">
<input class="form-control" placeholder="{{translate('search')}}" type="text" ng-model="searchString" ng-init="" ng-keyup="search2FA()"/>
<input class="form-control" trplaceholder="search" type="text" ng-model="searchString" ng-init="" ng-keyup="search2FA()"/>
<div class="input-group-btn">
<button class="btn btn-default" ng-click="search2FA(1)"><i class="glyphicon glyphicon-search"></i></button>
</div>

View File

@ -276,7 +276,7 @@ sub checkFindByProviderId {
($gotProviderId) = $result->{metadata} =~ m/entityID=['"](.+?)['"]/i;
}
elsif ( $providerIdName eq 'serviceUrl' ) {
$gotProviderId = $result->{options}->{service};
$gotProviderId = shift @{$result->{options}->{service}};
}
else {
$gotProviderId = $result->{$providerIdName};
@ -646,7 +646,7 @@ my $casApp = {
given_name => '$firstName',
},
options => {
service => 'http://mycasapp.example.com',
service => [ 'http://mycasapp.example.com', 'http://mycasapp2.example.com/test' ],
rule => '$uid eq \'dwho\'',
userAttribute => 'uid'
}
@ -654,7 +654,7 @@ my $casApp = {
$test = "CasApp - Add should succeed";
checkAdd( $test, 'cas/app', $casApp );
checkGet( $test, 'cas/app', 'myCasApp1', 'options/service',
checkGet( $test, 'cas/app', 'myCasApp1', 'options/service/0',
'http://mycasapp.example.com' );
checkGet( $test, 'cas/app', 'myCasApp1', 'options/userAttribute', 'uid' );
checkGet( $test, 'cas/app', 'myCasApp1', 'options/rule', '$uid eq \'dwho\'' );
@ -663,7 +663,7 @@ $test = "CasApp - Add should fail on duplicate confKey";
checkAddFailsIfExists( $test, 'cas/app', $casApp );
$test = "CasApp - Update should succeed and keep existing values";
$casApp->{options}->{service} = 'http://mycasapp.acme.com';
$casApp->{options}->{service} = [ 'http://mycasapp.acme.com' ];
$casApp->{options}->{userAttribute} = 'cn';
delete $casApp->{options}->{rule};
delete $casApp->{macros};
@ -671,8 +671,8 @@ delete $casApp->{exportedVars};
$casApp->{macros}->{given_name} = '$givenName';
$casApp->{exportedVars}->{cn} = 'uid';
checkUpdate( $test, 'cas/app', 'myCasApp1', $casApp );
checkGet( $test, 'cas/app', 'myCasApp1', 'options/service',
'http://mycasapp.acme.com' );
checkGet( $test, 'cas/app', 'myCasApp1', 'options/service/0',
'http://mycasapp.acme.com');
checkGet( $test, 'cas/app', 'myCasApp1', 'options/userAttribute', 'cn' );
checkGet( $test, 'cas/app', 'myCasApp1', 'options/rule', '$uid eq \'dwho\'' );
checkGet( $test, 'cas/app', 'myCasApp1', 'exportedVars/cn', 'uid' );
@ -686,17 +686,17 @@ delete $casApp->{options}->{playingPossum};
$test = "CasApp - Add should fail on non existing options";
$casApp->{confKey} = 'myCasApp2';
$casApp->{options}->{service} = 'http://mycasapp.skynet.com';
$casApp->{options}->{service} = [ 'http://mycasapp.skynet.com' ];
$casApp->{options}->{playingPossum} = 'ElephantInTheRoom';
checkAddWithUnknownAttributes( $test, 'cas/app', $casApp );
delete $casApp->{options}->{playingPossum};
$test = "CasApp - Add should fail because service host already exists";
$casApp->{options}->{service} = 'http://mycasapp.acme.com/ignoredbyissuer';
$casApp->{options}->{service} = [ 'http://mycasapp.acme.com/ignoredbyissuer' ];
checkAddFailsIfExists( $test, 'cas/app', $casApp );
$test = "CasApp - 2nd add should succeed";
$casApp->{options}->{service} = 'http://mycasapp.skynet.com';
$casApp->{options}->{service} = [ 'http://mycasapp.skynet.com' ];
checkAdd( $test, 'cas/app', $casApp );
$test = "CasApp - Update should fail if confKey not found";
@ -714,9 +714,13 @@ $test = "CasApp - Replace should fail on non existing or invalid options";
$casApp->{options}->{playingPossum} = 'elephant';
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
delete $casApp->{options}->{playingPossum};
$casApp->{options}->{service} = "XXX";
$casApp->{options}->{service} = [ "XXX" ];
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
$test = "CasApp - Replace should fail if service is not an array";
$casApp->{options}->{service} = "http://cas.url.string";
check409( $test, update( $test, 'cas/app', 'myCasApp2', $casApp ) );
$test = "CasApp - Replace should fail if confKey not found";
$casApp->{confKey} = 'myCasApp3';
checkReplaceNotFound( $test, 'cas/app', 'myCasApp3', $casApp );

View File

@ -559,6 +559,7 @@ t/30-SAML-ReAuth-with-choice.t
t/30-SAML-ReAuth.t
t/30-SAML-RelayState.t
t/30-SAML-SP-rule.t
t/31-Auth-and-issuer-CAS-declared-app-multiple-urls.t
t/31-Auth-and-issuer-CAS-declared-app-userattr.t
t/31-Auth-and-issuer-CAS-declared-app.t
t/31-Auth-and-issuer-CAS-declared-apps.t

View File

@ -23,7 +23,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_NO_SECOND_FACTORS
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Portal::Main::Plugin';
with 'Lemonldap::NG::Portal::Lib::OverConf';

View File

@ -5,7 +5,7 @@ use strict;
use Mouse;
use JSON qw(from_json to_json);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Plugin

View File

@ -187,6 +187,7 @@ sub fail {
MAIN_LOGO => $self->conf->{portalMainLogo},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
SKIN => $self->p->getSkin($req),
FAILED => 1
}

View File

@ -5,10 +5,14 @@ package Lemonldap::NG::Portal::Auth::AD;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Main::Constants
qw(PE_OK PE_PP_PASSWORD_EXPIRED PE_PP_CHANGE_AFTER_RESET PE_BADCREDENTIALS);
use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_PP_PASSWORD_EXPIRED
PE_PP_CHANGE_AFTER_RESET
PE_BADCREDENTIALS
);
our $VERSION = '2.0.6';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Portal::Auth::LDAP';
@ -158,4 +162,16 @@ sub authenticate {
return $res;
}
# Define which error codes will stop Combination process
# @param res error code
# @return result 1 if stop is needed
sub stop {
my ( $self, $res ) = @_;
return 1
if ( $res == PE_PP_PASSWORD_EXPIRED
or $res == PE_PP_CHANGE_AFTER_RESET );
return 0;
}
1;

View File

@ -3,12 +3,18 @@ package Lemonldap::NG::Portal::Auth::Combination;
use strict;
use Mouse;
use Lemonldap::NG::Common::Combination::Parser;
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK PE_ERROR PE_FIRSTACCESS);
use Lemonldap::NG::Portal::Main::Constants qw(
PE_CONFIRM
PE_ERROR
PE_FIRSTACCESS
PE_FORMEMPTY
PE_PASSWORD_OK
PE_OK
);
use Scalar::Util 'weaken';
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
# TODO: See Lib::Wrapper
extends 'Lemonldap::NG::Portal::Main::Auth';
with 'Lemonldap::NG::Portal::Lib::OverConf';
@ -126,7 +132,7 @@ sub getDisplayType {
$req->data->{dataKeep}->{combinationTry},
$req->data->{combinationStack}
);
my ( $res, $name ) = $stack->[$nb]->[0]->( 'getDisplayType', @_ );
my $res = $stack->[$nb]->[0]->( 'getDisplayType', @_ );
return $res;
}
@ -231,13 +237,14 @@ sub try {
return PE_ERROR;
}
my $stop = 0;
if ( $nb < @$stack - 1 ) {
# TODO: change logLevel for userLog()
( $res, $name ) = $stack->[$nb]->[$type]->( $subname, $req, @args );
# On error, restart authentication with next scheme
if ( $res > PE_OK ) {
unless ( $stop = $self->stop( $stack->[$nb]->[$type], $res ) ) {
$self->logger->info(qq'Scheme "$name" returned $res, trying next');
$req->data->{dataKeep}->{combinationTry}++;
$req->steps( [ @{ $req->data->{combinationSteps} } ] );
@ -251,11 +258,17 @@ sub try {
$req->sessionInfo->{ [ '_auth', '_userDB' ]->[$type] } = $name;
$req->sessionInfo->{_combinationTry} =
$req->data->{dataKeep}->{combinationTry};
if ( $res > 0 and $res != PE_FIRSTACCESS ) {
$self->userLogger->warn( 'All schemes failed'
. ( $req->user ? ' for user ' . $req->user : '' ) . ' ('
. $req->address
. ')' );
if ( $res > 0 ) {
if ($stop) {
$self->userLogger->info(
"Combination stopped by plugin $name (code $res)");
}
elsif ( $res != PE_FIRSTACCESS ) {
$self->userLogger->warn( 'All schemes failed'
. ( $req->user ? ' for user ' . $req->user : '' ) . ' ('
. $req->address
. ')' );
}
}
return $res;
}
@ -269,6 +282,32 @@ sub name {
|| 'Combination';
}
sub stop {
my ( $self, $mod, $res ) = @_;
return 1
if (
$res <= 0 # PE_OK
or $res == PE_CONFIRM
or $res == PE_PASSWORD_OK
# TODO: adding this may generate behavior change
#or $res == PE_FIRSTACCESS
#or $res == PE_FORMEMPTY
);
my ( $ret, $name );
$ret = $mod->( 'can', 'stop' );
if ($ret) {
eval { ( $ret, $name ) = $mod->( 'stop', $res ) };
if ($@) {
$self->logger->error(
"Optional ${name}::stop() method failed: " . $@ );
return 0;
}
}
return $ret;
}
package Lemonldap::NG::Portal::Lib::Combination::UserLogger;
# This logger rewrite "warn" to "notice"

View File

@ -7,11 +7,12 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_DONE
PE_ERROR
PE_LDAPCONNECTFAILED
PE_PP_ACCOUNT_LOCKED
PE_PP_PASSWORD_EXPIRED
PE_PP_CHANGE_AFTER_RESET
);
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
# Inheritance: UserDB::LDAP provides all needed ldap functions
extends qw(
@ -99,4 +100,17 @@ sub authLogout {
return PE_OK;
}
# Define which error codes will stop Combination process
# @param res error code
# @return result 1 if stop is needed
sub stop {
my ( $self, $res ) = @_;
return 1
if ( $res == PE_PP_PASSWORD_EXPIRED
or $res == PE_PP_ACCOUNT_LOCKED
or $res == PE_PP_CHANGE_AFTER_RESET );
return 0;
}
1;

View File

@ -10,7 +10,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_IDPCHOICE
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Auth

View File

@ -19,7 +19,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_PASSWORDFORMEMPTY
);
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Auth

View File

@ -11,7 +11,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
extends 'Lemonldap::NG::Portal::Lib::LDAP';
our $VERSION = '2.0.8';
our $VERSION = '2.0.14';
# PRIVATE METHOD
sub modifCertificate {

View File

@ -15,7 +15,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
URIRE
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Portal::Main::Issuer',
'Lemonldap::NG::Portal::Lib::CAS';
@ -61,8 +61,12 @@ sub init {
# Add CAS Services, so we can check service= parameter on logout
foreach my $casSrv ( keys %{ $self->casAppList } ) {
if ( my $serviceUrl =
$self->casAppList->{$casSrv}->{casAppMetaDataOptionsService} )
for my $serviceUrl (
split(
/\s+/,
$self->casAppList->{$casSrv}->{casAppMetaDataOptionsService}
)
)
{
push @{ $self->p->{additionalTrustedDomains} }, $serviceUrl;
$self->logger->debug(

View File

@ -20,7 +20,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
);
use String::Random qw/random_string/;
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Issuer

View File

@ -22,7 +22,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_UNAUTHORIZEDPARTNER
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Portal::Main::Issuer',
'Lemonldap::NG::Portal::Lib::SAML';

View File

@ -7,7 +7,7 @@ use XML::Simple;
use Lemonldap::NG::Common::UserAgent;
use URI;
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
# PROPERTIES
@ -531,22 +531,28 @@ sub getCasApp {
for my $app ( keys %{ $self->casAppList } ) {
my $candidateUri =
URI->new( $self->casAppList->{$app}->{casAppMetaDataOptionsService} );
my $candidateHost = $candidateUri->authority;
my $candidateCanon = $candidateUri->canonical;
for my $appservice (
split(
/\s+/, $self->casAppList->{$app}->{casAppMetaDataOptionsService}
)
)
{
my $candidateUri = URI->new($appservice);
my $candidateHost = $candidateUri->authority;
my $candidateCanon = $candidateUri->canonical;
# Try to match prefix, remembering the longest match found
if ( index( $uriCanon, $candidateCanon ) == 0 ) {
if ( length($longestCandidate) < length($candidateCanon) ) {
$longestCandidate = $candidateCanon;
$prefixConfKey = $app;
# Try to match prefix, remembering the longest match found
if ( index( $uriCanon, $candidateCanon ) == 0 ) {
if ( length($longestCandidate) < length($candidateCanon) ) {
$longestCandidate = $candidateCanon;
$prefixConfKey = $app;
}
}
}
# Try to match host, only if strict matching is disabled
unless ( $self->conf->{casStrictMatching} ) {
$hostnameConfKey = $app if ( $hostname eq $candidateHost );
# Try to match host, only if strict matching is disabled
unless ( $self->conf->{casStrictMatching} ) {
$hostnameConfKey = $app if ( $hostname eq $candidateHost );
}
}
}

View File

@ -7,7 +7,7 @@ use Safe;
extends 'Lemonldap::NG::Portal::Lib::Wrapper';
with 'Lemonldap::NG::Portal::Lib::OverConf';
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
has modules => ( is => 'rw', default => sub { {} } );
has rules => ( is => 'rw', default => sub { {} } );

View File

@ -45,7 +45,6 @@ sub newLdap {
)
)
{
$self->logger->error("LDAP initialization error: $@");
return undef;
}

View File

@ -52,7 +52,7 @@ sub new {
( $conf->{ldapVerify} ? ( verify => $conf->{ldapVerify} ) : () ),
);
unless ($self) {
$portal->logger->error($@);
$portal->logger->error("LDAP initialization error: ". $@);
return 0;
}
elsif ( $Net::LDAP::VERSION < '0.64' ) {
@ -65,7 +65,7 @@ sub new {
and $self->socket->errstr < 0 )
{
$portal->logger->error(
"SSL connection error: " . $self->socket->errstr );
"LDAP SSL connection failed: " . $self->socket->errstr );
return 0;
}
}
@ -84,7 +84,7 @@ sub new {
$h{verify} ||= $conf->{ldapVerify} if ( $conf->{ldapVerify} );
my $mesg = $self->start_tls(%h);
if ( $mesg->code ) {
$portal->logger->error( 'StartTLS failed: ' . $mesg->error );
$portal->logger->error( 'LDAP StartTLS failed: ' . $mesg->error );
return 0;
}
}

View File

@ -22,7 +22,7 @@ use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK PE_REDIRECT);
our $VERSION = '2.0.13';
our $VERSION = '2.0.14';
# OpenID Connect standard claims
use constant PROFILE => [

View File

@ -21,7 +21,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_SAML_SLO_ERROR
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
# PROPERTIES

View File

@ -3,7 +3,7 @@ package Lemonldap::NG::Portal::Main::Auth;
use strict;
use Mouse;
our $VERSION = '2.0.0';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Portal::Main::Plugin';
@ -11,4 +11,6 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
has authnLevel => ( is => 'rw' );
sub stop {0}
1;

View File

@ -85,6 +85,7 @@ sub display {
MAIN_LOGO => $self->conf->{portalMainLogo},
LANGS => $self->conf->{showLanguages},
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
NOTIFICATION => $notif,
HIDDEN_INPUTS => $self->buildHiddenForm($req),
AUTH_URL => $req->{data}->{_url},
@ -108,6 +109,7 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
AUTH_URL => $req->{data}->{_url},
MSG => $req->info,
HIDDEN_INPUTS => $self->buildHiddenForm($req),
@ -139,6 +141,7 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
AUTH_URL => $req->{data}->{_url},
HIDDEN_INPUTS => $self->buildHiddenForm($req),
ACTIVE_TIMER => $req->data->{activeTimer},
@ -150,7 +153,7 @@ sub display {
ASK_LOGINS => $req->param('checkLogins') || 0,
ASK_STAYCONNECTED => $req->param('stayconnected') || 0,
CONFIRMKEY => $self->stamp(),
LIST => $req->data->{list} || [],
LIST => $req->data->{list} || [],
(
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} )
@ -173,8 +176,9 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_ERROR => $self->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
MSG => $info,
URL => $req->{urldc} || $self->conf->{portal}, # Fix 2158
URL => $req->{urldc} || $self->conf->{portal}, # Fix 2158
HIDDEN_INPUTS => $self->buildOutgoingHiddenForm( $req, $method ),
ACTIVE_TIMER => $req->data->{activeTimer},
CHOICE_PARAM => $self->conf->{authChoiceParam},
@ -206,6 +210,7 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_ERROR => $self->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
PROVIDERURI => $p,
MSG => $req->info(),
(
@ -363,6 +368,7 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
LOCKTIME => $req->lockTime(),
(
$req->data->{customScript}
@ -381,15 +387,16 @@ sub display {
LANGS => $self->conf->{showLanguages},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
AUTH_URL => $req->{data}->{_url},
LOGIN => $login,
DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword},
CHECK_LOGINS => $self->conf->{portalCheckLogins},
ASK_LOGINS => $req->param('checkLogins') || 0,
ASK_LOGINS => $req->param('checkLogins') || 0,
ASK_STAYCONNECTED => $req->param('stayconnected') || 0,
DISPLAY_RESETPASSWORD => $self->conf->{portalDisplayResetPassword},
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
DISPLAY_UPDATECERTIF =>
DISPLAY_UPDATECERTIF =>
$self->conf->{portalDisplayCertificateResetByMail},
MAILCERTIF_URL => $self->conf->{certificateResetByMailURL},
MAIL_URL => $self->conf->{mailUrl},
@ -560,12 +567,12 @@ sub display {
: 0,
DISPLAY_SSL_FORM => $displayType =~ /sslform/ ? 1 : 0,
DISPLAY_GPG_FORM => $displayType =~ /gpgform/ ? 1 : 0,
DISPLAY_LOGO_FORM => $displayType eq "logo" ? 1 : 0,
DISPLAY_LOGO_FORM => $displayType eq "logo" ? 1 : 0,
DISPLAY_FINDUSER => scalar @$fields,
module => $displayType eq "logo"
? $self->getModule( $req, 'auth' )
: "",
AUTH_LOOP => [],
AUTH_LOOP => [],
PORTAL_URL =>
( $displayType eq "logo" ? $self->conf->{portal} : 0 ),
MSG => $req->info(),
@ -722,8 +729,7 @@ sub mkSessionArray {
delete @rememberedData{
grep {
( not $rememberedData{$_} )
or
( $rememberedData{$_} eq "__hidden__" )
or ( $rememberedData{$_} eq "__hidden__" )
} keys %rememberedData
};
@ -803,7 +809,8 @@ sub mkOidcConsent {
'oidcConsents',
params => {
partners => [
map { {
map {
{
name => $_,
epoch => $consents->{$_}->{epoch},
scope => $consents->{$_}->{scope},

View File

@ -8,7 +8,7 @@
# of lemonldap-ng.ini) and underlying handler configuration
package Lemonldap::NG::Portal::Main::Init;
our $VERSION = '2.0.13';
our $VERSION = '2.0.14';
package Lemonldap::NG::Portal::Main;

View File

@ -100,7 +100,7 @@ sub _redirect {
$self->logger->debug(
'Add ' . $self->ipath . ', ' . $self->ipath . 'Path in keepPdata' );
push @{ $req->pdata->{keepPdata} }, $self->ipath, $self->ipath . 'Path';
$req->{urldc} = $self->conf->{portal} . '/' . $self->path;
$req->{urldc} = $self->p->buildUrl( $self->path );
$req->pdata->{_url} = encode_base64( $req->urldc, '' );
$req->pdata->{issuerTs} = time;
}
@ -128,7 +128,7 @@ sub _redirect {
$self->restoreRequest( $_[0], $ir );
$self->cleanPdata( $_[0] );
return $self->run( @_, @path );
}
}
: ()
)
]

View File

@ -7,7 +7,7 @@ use Mouse;
use Clone 'clone';
use Lemonldap::NG::Portal::Main::Constants 'URIRE';
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Common::Module';
@ -116,6 +116,7 @@ sub params {
$res{DISPLAY_MODULES} = $self->displayModules($req);
$res{AUTH_ERROR_TYPE} =
$req->error_type( $res{AUTH_ERROR} = $req->menuError );
$res{AUTH_ERROR_ROLE} = $req->error_role;
# Display menu 2fRegisters link only if at least a 2F device is registered and rule
$res{sfaManager} =
@ -298,7 +299,7 @@ sub _buildApplicationHash {
my $appuri = $apphash->{options}->{uri} || "";
my $appdesc = $apphash->{options}->{description};
my $applogo = $apphash->{options}->{logo};
my $apptip = $apphash->{options}->{tooltip} || $appname;
my $apptip = $apphash->{options}->{tooltip} || $appname;
# Detect sub applications
my $subapphash;

View File

@ -11,7 +11,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_ERROR
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Common::Module';

View File

@ -85,9 +85,16 @@ has token => ( is => 'rw' );
has wantErrorRender => ( is => 'rw' );
# Error type
sub error_role {
my $req = shift;
return $req->error_type(@_) eq 'negative' ? 'alert' : 'status';
}
sub error_type {
my $req = shift;
my $code = shift || $req->error;
$req->error($code);
# Positive errors
return "positive"

View File

@ -289,6 +289,7 @@ sub do {
params => {
AUTH_ERROR => $err,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
}
);
}

View File

@ -10,7 +10,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADCREDENTIALS
);
our $VERSION = '2.0.8';
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Plugin

View File

@ -600,6 +600,7 @@ sub display {
MAIN_LOGO => $self->conf->{portalMainLogo},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
AUTH_URL => $req->data->{_url},
CHOICE_VALUE => $req->{_authChoice},
EXPMAILDATE => $req->data->{expMailDate},

View File

@ -9,7 +9,7 @@ use strict;
use Mouse;
use Lemonldap::NG::Portal;
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
extends 'Lemonldap::NG::Portal::Main::Plugin';

View File

@ -12,7 +12,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
PE_SENDRESPONSE
);
our $VERSION = '2.0.12';
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Plugin

View File

@ -567,6 +567,7 @@ sub display {
MAIN_LOGO => $self->conf->{portalMainLogo},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
AUTH_URL => $req->data->{_url},
CHOICE_VALUE => $req->{_authChoice},
EXPMAILDATE => $req->data->{expMailDate},

View File

@ -15,7 +15,7 @@
# * GET /session/my/<type> : get session data
# * GET /session/my/<type>/key : get session key
# * DELETE /session/my : ask for logout
# * DELETE /sessions/my : ask for global logout
# * DELETE /sessions/my : ask for global logout (if GlobalLogout plugin is on)
#
# - Authentication
# * GET /renewcaptcha : get token and captcha image
@ -200,9 +200,16 @@ sub init {
)
->addAuthRoute(
sessions => { my => { ':sessionType' => 'removeSessions' } },
session => { my => 'removeSession' },
['DELETE']
);
if ( $self->conf->{globalLogoutRule} ) {
$self->addAuthRoute(
sessions => { my => 'removeSessions' },
['DELETE']
);
}
}
if ( $self->conf->{restPasswordServer} ) {
@ -357,7 +364,7 @@ sub updateSession {
# Get session and store info
my $session = $self->getApacheSession( $mod, $id, $infos, $force )
or return $self->p->sendError( $req, 'Session id does not exists', 400 );
or return $self->p->sendError( $req, 'Session Id does not exist', 400 );
return $self->p->sendJSONresponse( $req, { result => 1 } );
}
@ -370,7 +377,7 @@ sub delSession {
# Get session
my $session = $self->getApacheSession( $mod, $id )
or return $self->p->sendError( $req, 'Session id does not exists', 400 );
or return $self->p->sendError( $req, 'Session Id does not exist', 400 );
# Delete it
$self->logger->debug("REST request to delete session $id");
@ -598,11 +605,30 @@ sub getError {
errorNum => $errNum ? $errNum : 'all',
errorsFileURL =>
"$self->{conf}->{staticPrefix}/languages/$lang.json",
( $errNum ? ( errorMsgRef => "PE$errNum" ) : () ),
( $errNum ? ( errorMsgRef => "PE$errNum" ) : () )
}
);
}
sub removeSession {
my ( $self, $req ) = @_;
my $id = $req->userData->{_session_id};
return $self->p->sendError( $req, 'ID is required', 400 ) unless ($id);
my $mod = $self->getGlobal()
or return $self->p->sendError( $req, undef, 400 );
# Get session
my $session = $self->getApacheSession( $mod, $id )
or return $self->p->sendError( $req, 'Session Id does not exist', 400 );
# Delete it
$self->logger->debug("REST request to delete global session $id");
my $res = $self->p->_deleteSession( $req, $session );
$self->logger->debug(" Result is $res");
return $self->p->sendJSONresponse( $req, { result => $res } );
}
sub removeSessions {
my ( $self, $req ) = @_;
my $glPlugin =
@ -749,9 +775,8 @@ sub getUser {
# Search user in database
$req->steps( [
'getUser', 'setSessionInfo',
'setMacros', 'setGroups',
'setLocalGroups'
'getUser', 'setSessionInfo',
$self->p->groupsAndMacros, 'setLocalGroups'
]
);
my $error = $self->p->process( $req, ( $mail ? ( useMail => 1 ) : () ) );
@ -783,7 +808,8 @@ sub myApplications {
{ Category => $_->{catname}, Applications => \@apps },
} @{ $self->p->menu->appslist($req) };
return $self->p->sendJSONresponse( $req, { result => 1, myapplications => \@appslist } );
return $self->p->sendJSONresponse( $req,
{ result => 1, myapplications => \@appslist } );
}
sub _checkSecret {

View File

@ -436,6 +436,7 @@ sub display {
MAIN_LOGO => $self->conf->{portalMainLogo},
AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type,
AUTH_ERROR_ROLE => $req->error_role,
AUTH_URL => $req->data->{_url},
CHOICE_PARAM => $self->conf->{authChoiceParam},
CHOICE_VALUE => $req->data->{_authChoice},

View File

@ -9,7 +9,7 @@ use Lemonldap::NG::Portal::Main::Constants qw(
extends 'Lemonldap::NG::Portal::Register::LDAP';
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
sub createUser {
my ( $self, $req ) = @_;

View File

@ -14,7 +14,7 @@ extends qw(
Lemonldap::NG::Portal::Register::Base
);
our $VERSION = '2.0.10';
our $VERSION = '2.0.14';
# RUNNING METHODS

View File

@ -9,6 +9,7 @@ setMsg = (msg, level) ->
$('#color').addClass "message-#{level}"
level = 'success' if level == 'positive'
$('#color').addClass "alert-#{level}"
$('#color').attr "role", "status"
displayError = (j, status, err) ->
console.log 'Error', err

View File

@ -10,6 +10,7 @@ setMsg = (msg, level) ->
$('#color').addClass "message-#{level}"
level = 'success' if level == 'positive'
$('#color').addClass "alert-#{level}"
$('#color').attr "role", "status"
displayError = (j, status, err) ->
setMsg 'notificationRetrieveFailed', 'warning'

View File

@ -13,6 +13,20 @@ translationFields = {}
# content
# - trplaceholder: set result in "placeholder" attribute
# - localtime : transform time (in ms)ing translate()
setDanger = (cond, field) ->
result = false
if cond
$("##{field}").addClass 'fa-check text-success'
$("##{field}").removeClass 'fa-times text-danger'
$("##{field}").attr 'role', 'status'
else
$("##{field}").addClass 'fa-times text-danger'
$("##{field}").removeClass 'fa-check text-success'
$("##{field}").attr 'role', 'alert'
result = true
result
translatePage = (lang) ->
$.getJSON "#{window.staticPrefix}languages/#{lang}.json", (data) ->
translationFields = data
@ -33,7 +47,9 @@ translatePage = (lang) ->
if msg.match /_hide_/
$(this).parent().hide()
$("[trplaceholder]").each ->
$(this).attr 'placeholder', translate($(this).attr('trplaceholder'))
tmp = translate($(this).attr('trplaceholder'))
$(this).attr 'placeholder', tmp
$(this).attr 'aria-label', tmp
$("[localtime]").each ->
d = new Date $(this).attr('localtime') * 1000
$(this).text d.toLocaleString()
@ -391,40 +407,16 @@ $(window).on 'load', () ->
checkpassword = (password) ->
result = true
if window.datas.ppolicy.minsize > 0
if password.length >= window.datas.ppolicy.minsize
$('#ppolicy-minsize-feedback').addClass 'fa-check text-success'
$('#ppolicy-minsize-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-minsize-feedback').removeClass 'fa-check text-success'
$('#ppolicy-minsize-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( password.length >= window.datas.ppolicy.minsize, 'ppolicy-minsize-feedback' )
if window.datas.ppolicy.minupper > 0
upper = password.match(/[A-Z]/g)
if upper and upper.length >= window.datas.ppolicy.minupper
$('#ppolicy-minupper-feedback').addClass 'fa-check text-success'
$('#ppolicy-minupper-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-minupper-feedback').removeClass 'fa-check text-success'
$('#ppolicy-minupper-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( upper and upper.length >= window.datas.ppolicy.minupper, 'ppolicy-minupper-feedback' )
if window.datas.ppolicy.minlower > 0
lower = password.match(/[a-z]/g)
if lower and lower.length >= window.datas.ppolicy.minlower
$('#ppolicy-minlower-feedback').addClass 'fa-check text-success'
$('#ppolicy-minlower-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-minlower-feedback').removeClass 'fa-check text-success'
$('#ppolicy-minlower-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( lower and lower.length >= window.datas.ppolicy.minlower, 'ppolicy-minlower-feedback')
if window.datas.ppolicy.mindigit > 0
digit = password.match(/[0-9]/g)
if digit and digit.length >= window.datas.ppolicy.mindigit
$('#ppolicy-mindigit-feedback').addClass 'fa-check text-success'
$('#ppolicy-mindigit-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-mindigit-feedback').removeClass 'fa-check text-success'
$('#ppolicy-mindigit-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( digit and digit.length >= window.datas.ppolicy.mindigit, 'ppolicy-mindigit-feedback')
if window.datas.ppolicy.allowedspechar
nonwhitespechar = window.datas.ppolicy.allowedspechar.replace(/\s/g, '')
@ -436,13 +428,7 @@ $(window).on 'load', () ->
if nonwhitespechar.indexOf(password.charAt(i)) < 0
hasforbidden = true
i++
if hasforbidden == false
$('#ppolicy-allowedspechar-feedback').addClass 'fa-check text-success'
$('#ppolicy-allowedspechar-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-allowedspechar-feedback').removeClass 'fa-check text-success'
$('#ppolicy-allowedspechar-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( hasforbidden == false, 'ppolicy-allowedspechar-feedback' )
if window.datas.ppolicy.minspechar > 0 and window.datas.ppolicy.allowedspechar
numspechar = 0
@ -452,13 +438,7 @@ $(window).on 'load', () ->
if nonwhitespechar.indexOf(password.charAt(i)) >= 0
numspechar++
i++
if numspechar >= window.datas.ppolicy.minspechar
$('#ppolicy-minspechar-feedback').addClass 'fa-check text-success'
$('#ppolicy-minspechar-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-minspechar-feedback').removeClass 'fa-check text-success'
$('#ppolicy-minspechar-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( numspechar >= window.datas.ppolicy.minspechar, 'ppolicy-minspechar-feedback')
if window.datas.ppolicy.minspechar > 0 and !window.datas.ppolicy.allowedspechar
numspechar = 0
@ -466,13 +446,7 @@ $(window).on 'load', () ->
while i < password.length
numspechar++ if !isAlphaNumeric(password.charAt(i))
i++
if numspechar >= window.datas.ppolicy.minspechar
$('#ppolicy-minspechar-feedback').addClass 'fa-check text-success'
$('#ppolicy-minspechar-feedback').removeClass 'fa-times text-danger'
else
$('#ppolicy-minspechar-feedback').removeClass 'fa-check text-success'
$('#ppolicy-minspechar-feedback').addClass 'fa-times text-danger'
result = false
result = false if setDanger( numspechar >= window.datas.ppolicy.minspechar, 'ppolicy-minspechar-feedback')
if result
$('.ppolicy').removeClass('border-danger').addClass 'border-success'

View File

@ -9,6 +9,7 @@ setMsg = (msg, level) ->
$('#color').addClass "message-#{level}"
level = 'success' if level == 'positive'
$('#color').addClass "alert-#{level}"
$('#msg').attr 'role', (if level == 'danger' then 'alert' else 'status')
displayError = (j, status, err) ->
console.log 'Error', err

View File

@ -9,6 +9,7 @@ setMsg = (msg, level) ->
$('#color').addClass "message-#{level}"
level = 'success' if level == 'positive'
$('#color').addClass "alert-#{level}"
$('#msg').attr 'role', (if level == 'danger' then 'alert' else 'status')
displayError = (j, status, err) ->
console.log 'Error', err

View File

@ -15,7 +15,8 @@ LemonLDAP::NG 2F registration script
if (level === 'positive') {
level = 'success';
}
return $('#color').addClass("alert-" + level);
$('#color').addClass("alert-" + level);
return $('#color').attr("role", "status");
};
displayError = function(j, status, err) {

View File

@ -1 +1 @@
(function(){var e,t,n;n=function(e,r){return $("#msg").attr("trspan",e),$("#msg").html(window.translate(e)),$("#color").removeClass("message-positive message-warning alert-success alert-warning"),$("#color").addClass("message-"+r),"positive"===r&&(r="success"),$("#color").addClass("alert-"+r)},t=function(e,r,t){var o;if(console.log("Error",t),(o=JSON.parse(e.responseText))&&o.error)return o=o.error.replace(/.* /,""),console.log("Returned error",o),o.match(/module/)?n("notAuthorized","warning"):n(o,"warning")},e=function(e,r){return"U2F"===e?e="u":"UBK"===e?e="yubikey":"TOTP"===e?e="totp":n("u2fFailed","warning"),$.ajax({type:"POST",url:portal+"2fregisters/"+e+"/delete",data:{epoch:r},dataType:"json",error:t,success:function(e){return e.error?e.error.match(/notAuthorized/)?n("notAuthorized","warning"):n("unknownAction","warning"):e.result?($("#delete-"+r).hide(),n("yourKeyIsUnregistered","positive")):void 0},error:t})},$(document).ready(function(){return $("body").on("click",".remove2f",function(){return e($(this).attr("device"),$(this).attr("epoch"))}),$("#goback").attr("href",portal),$(".data-epoch").each(function(){var e;return e=new Date(1e3*$(this).text()),$(this).text(e.toLocaleString())})})}).call(this);
!function(){var o=function(e,r){return $("#msg").attr("trspan",e),$("#msg").html(window.translate(e)),$("#color").removeClass("message-positive message-warning alert-success alert-warning"),$("#color").addClass("message-"+r),"positive"===r&&(r="success"),$("#color").addClass("alert-"+r),$("#color").attr("role","status")},t=function(e,r,t){if(console.log("Error",t),(e=JSON.parse(e.responseText))&&e.error)return e=e.error.replace(/.* /,""),console.log("Returned error",e),e.match(/module/)?o("notAuthorized","warning"):o(e,"warning")},e=function(e,r){return"U2F"===e?e="u":"UBK"===e?e="yubikey":"TOTP"===e?e="totp":o("u2fFailed","warning"),$.ajax({type:"POST",url:portal+"2fregisters/"+e+"/delete",data:{epoch:r},dataType:"json",error:t,success:function(e){return e.error?e.error.match(/notAuthorized/)?o("notAuthorized","warning"):o("unknownAction","warning"):e.result?($("#delete-"+r).hide(),o("yourKeyIsUnregistered","positive")):void 0}})};$(document).ready(function(){return $("body").on("click",".remove2f",function(){return e($(this).attr("device"),$(this).attr("epoch"))}),$("#goback").attr("href",portal),$(".data-epoch").each(function(){var e=new Date(1e3*$(this).text());return $(this).text(e.toLocaleString())})})}.call(this);

View File

@ -1 +1 @@
{"version":3,"sources":["2fregistration.js"],"names":["delete2F","displayError","setMsg","msg","level","$","attr","html","window","translate","removeClass","addClass","j","status","err","res","console","log","JSON","parse","responseText","error","replace","match","device","epoch","ajax","type","url","portal","data","dataType","success","resp","result","hide","document","ready","on","this","each","myDate","Date","text","toLocaleString","call"],"mappings":"CAMA,WACE,IAAIA,EAAUC,EAAcC,EAE5BA,EAAS,SAASC,EAAKC,GAQrB,OAPAC,EAAE,QAAQC,KAAK,SAAUH,GACzBE,EAAE,QAAQE,KAAKC,OAAOC,UAAUN,IAChCE,EAAE,UAAUK,YAAY,gEACxBL,EAAE,UAAUM,SAAS,WAAaP,GACpB,aAAVA,IACFA,EAAQ,WAEHC,EAAE,UAAUM,SAAS,SAAWP,IAGzCH,EAAe,SAASW,EAAGC,EAAQC,GACjC,IAAIC,EAGJ,GAFAC,QAAQC,IAAI,QAASH,IACrBC,EAAMG,KAAKC,MAAMP,EAAEQ,gBACRL,EAAIM,MAGb,OAFAN,EAAMA,EAAIM,MAAMC,QAAQ,MAAO,IAC/BN,QAAQC,IAAI,iBAAkBF,GAC1BA,EAAIQ,MAAM,UACLrB,EAAO,gBAAiB,WAExBA,EAAOa,EAAK,YAKzBf,EAAW,SAASwB,EAAQC,GAU1B,MATe,QAAXD,EACFA,EAAS,IACW,QAAXA,EACTA,EAAS,UACW,SAAXA,EACTA,EAAS,OAETtB,EAAO,YAAa,WAEfG,EAAEqB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,eAAiBL,EAAS,UACxCM,KAAM,CACJL,MAAOA,GAETM,SAAU,OACVV,MAAOpB,EACP+B,QAAS,SAASC,GAChB,OAAIA,EAAKZ,MACHY,EAAKZ,MAAME,MAAM,iBACZrB,EAAO,gBAAiB,WAExBA,EAAO,gBAAiB,WAExB+B,EAAKC,QACd7B,EAAE,WAAaoB,GAAOU,OACfjC,EAAO,wBAAyB,kBAFlC,GAKTmB,MAAOpB,KAIXI,EAAE+B,UAAUC,MAAM,WAKhB,OAJAhC,EAAE,QAAQiC,GAAG,QAAS,YAAa,WACjC,OAAOtC,EAASK,EAAEkC,MAAMjC,KAAK,UAAWD,EAAEkC,MAAMjC,KAAK,YAEvDD,EAAE,WAAWC,KAAK,OAAQuB,QACnBxB,EAAE,eAAemC,KAAK,WAC3B,IAAIC,EAEJ,OADAA,EAAS,IAAIC,KAAsB,IAAjBrC,EAAEkC,MAAMI,QACnBtC,EAAEkC,MAAMI,KAAKF,EAAOG,wBAI9BC,KAAKN"}
{"version":3,"sources":["2fregistration.js"],"names":["setMsg","msg","level","$","attr","html","window","translate","removeClass","addClass","displayError","j","status","err","console","log","res","JSON","parse","responseText","error","replace","match","delete2F","device","epoch","ajax","type","url","portal","data","dataType","success","resp","result","hide","document","ready","on","this","each","myDate","Date","text","toLocaleString","call"],"mappings":"CAMA,WACE,IAEAA,EAAS,SAASC,EAAKC,GASrB,OARAC,EAAE,QAAQC,KAAK,SAAUH,GACzBE,EAAE,QAAQE,KAAKC,OAAOC,UAAUN,IAChCE,EAAE,UAAUK,YAAY,gEACxBL,EAAE,UAAUM,SAAS,WAAaP,GACpB,aAAVA,IACFA,EAAQ,WAEVC,EAAE,UAAUM,SAAS,SAAWP,GACzBC,EAAE,UAAUC,KAAK,OAAQ,WAGlCM,EAAe,SAASC,EAAGC,EAAQC,GAIjC,GAFAC,QAAQC,IAAI,QAASF,IACrBG,EAAMC,KAAKC,MAAMP,EAAEQ,gBACRH,EAAII,MAGb,OAFAJ,EAAMA,EAAII,MAAMC,QAAQ,MAAO,IAC/BP,QAAQC,IAAI,iBAAkBC,GAC1BA,EAAIM,MAAM,UACLtB,EAAO,gBAAiB,WAExBA,EAAOgB,EAAK,YAKzBO,EAAW,SAASC,EAAQC,GAU1B,MATe,QAAXD,EACFA,EAAS,IACW,QAAXA,EACTA,EAAS,UACW,SAAXA,EACTA,EAAS,OAETxB,EAAO,YAAa,WAEfG,EAAEuB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,eAAiBL,EAAS,UACxCM,KAAM,CACJL,MAAOA,GAETM,SAAU,OANEX,MAoBLV,EAZPsB,QAAS,SAASC,GAChB,OAAIA,EAAKb,MACHa,EAAKb,MAAME,MAAM,iBACZtB,EAAO,gBAAiB,WAExBA,EAAO,gBAAiB,WAExBiC,EAAKC,QACd/B,EAAE,WAAasB,GAAOU,OACfnC,EAAO,wBAAyB,kBAFlC,MASbG,EAAEiC,UAAUC,MAAM,WAKhB,OAJAlC,EAAE,QAAQmC,GAAG,QAAS,YAAa,WACjC,OAAOf,EAASpB,EAAEoC,MAAMnC,KAAK,UAAWD,EAAEoC,MAAMnC,KAAK,YAEvDD,EAAE,WAAWC,KAAK,OAAQyB,QACnB1B,EAAE,eAAeqC,KAAK,WAC3B,IACAC,EAAS,IAAIC,KAAsB,IAAjBvC,EAAEoC,MAAMI,QAC1B,OAAOxC,EAAEoC,MAAMI,KAAKF,EAAOG,uBAI9BC,KAAKN"}

View File

@ -16,7 +16,8 @@ LemonLDAP::NG Notifications script
if (level === 'positive') {
level = 'success';
}
return $('#color').addClass("alert-" + level);
$('#color').addClass("alert-" + level);
return $('#color').attr("role", "status");
};
displayError = function(j, status, err) {

View File

@ -1 +1 @@
(function(){var t,o,a,i,e,r,n;o=$("#msg").attr("trspan"),a=function(t,e){return $("#msg").html(window.translate(t)),$("#color").removeClass("message-positive message-warning alert-success alert-warning"),$("#color").addClass("message-"+e),"positive"===e&&(e="success"),$("#color").addClass("alert-"+e)},t=function(t,e,n){return a("notificationRetrieveFailed","warning"),console.log("Error:",n,"Status:",e)},r=function(t){return t?($("#icon-explorer-button").removeClass("fa-eye"),$("#icon-explorer-button").addClass("fa-eye-slash")):($("#icon-explorer-button").removeClass("fa-eye-slash"),$("#icon-explorer-button").addClass("fa-eye"))},e=function(t){return t?($("#explorer").hide(),$("#color").hide(),r(0)):($("#explorer").show(),$("#color").show(),r(1))},i=function(t,e,n){return a(o,"positive"),$(".btn-danger").each(function(){return $(this).removeClass("btn-danger"),$(this).addClass("btn-success")}),$(".fa-eye-slash").each(function(){return $(this).removeClass("fa-eye-slash"),$(this).addClass("fa-eye")}),$(".verify").each(function(){return $(this).text(window.translate("verify")),$(this).attr("trspan","verify")}),e&&n?(t.removeClass("btn-success"),t.addClass("btn-danger"),$("#icon-"+e+"-"+n).removeClass("fa-eye"),$("#icon-"+e+"-"+n).addClass("fa-eye-slash"),$("#text-"+e+"-"+n).text(window.translate("hide")),$("#text-"+e+"-"+n).attr("trspan","hide"),$("#myNotification").removeAttr("hidden"),r(1)):($("#myNotification").attr("hidden","true"),$("#explorer-button").attr("hidden","true"))},n=function(n,o,r){return console.log("Ref:",n,"epoch:",o),n&&o?(console.log("Send AJAX request"),$.ajax({type:"GET",url:portal+"mynotifications/"+n,data:{epoch:o},dataType:"json",error:t,success:function(t){var e;return t.result?(console.log("Notification:",t.notification),i(r,n,o),$("#displayNotif").html(t.notification),$("#notifRef").text(n),e=new Date(1e3*o),$("#notifEpoch").text(e.toLocaleString()),$("#explorer-button").removeAttr("hidden")):a("notificationNotFound","warning")}})):a("notificationRetrieveFailed","warning")},$(document).ready(function(){return $(".data-epoch").each(function(){var t;return t=new Date(1e3*$(this).text()),$(this).text(t.toLocaleString())}),$("#goback").attr("href",portal),$("body").on("click",".btn-success",function(){return n($(this).attr("notif"),$(this).attr("epoch"),$(this))}),$("body").on("click",".btn-danger",function(){return i($(this))}),$("body").on("click",".btn-info",function(){return e($("#explorer").is(":visible"))})})}).call(this);
!function(){var o=$("#msg").attr("trspan"),r=function(t,e){return $("#msg").html(window.translate(t)),$("#color").removeClass("message-positive message-warning alert-success alert-warning"),$("#color").addClass("message-"+e),"positive"===e&&(e="success"),$("#color").addClass("alert-"+e),$("#color").attr("role","status")},t=function(t,e,n){return r("notificationRetrieveFailed","warning"),console.log("Error:",n,"Status:",e)},a=function(t){return t?($("#icon-explorer-button").removeClass("fa-eye"),$("#icon-explorer-button").addClass("fa-eye-slash")):($("#icon-explorer-button").removeClass("fa-eye-slash"),$("#icon-explorer-button").addClass("fa-eye"))},e=function(t){return t?($("#explorer").hide(),$("#color").hide(),a(0)):($("#explorer").show(),$("#color").show(),a(1))},i=function(t,e,n){return r(o,"positive"),$(".btn-danger").each(function(){return $(this).removeClass("btn-danger"),$(this).addClass("btn-success")}),$(".fa-eye-slash").each(function(){return $(this).removeClass("fa-eye-slash"),$(this).addClass("fa-eye")}),$(".verify").each(function(){return $(this).text(window.translate("verify")),$(this).attr("trspan","verify")}),e&&n?(t.removeClass("btn-success"),t.addClass("btn-danger"),$("#icon-"+e+"-"+n).removeClass("fa-eye"),$("#icon-"+e+"-"+n).addClass("fa-eye-slash"),$("#text-"+e+"-"+n).text(window.translate("hide")),$("#text-"+e+"-"+n).attr("trspan","hide"),$("#myNotification").removeAttr("hidden"),a(1)):($("#myNotification").attr("hidden","true"),$("#explorer-button").attr("hidden","true"))},n=function(e,n,o){return console.log("Ref:",e,"epoch:",n),e&&n?(console.log("Send AJAX request"),$.ajax({type:"GET",url:portal+"mynotifications/"+e,data:{epoch:n},dataType:"json",error:t,success:function(t){return t.result?(console.log("Notification:",t.notification),i(o,e,n),$("#displayNotif").html(t.notification),$("#notifRef").text(e),t=new Date(1e3*n),$("#notifEpoch").text(t.toLocaleString()),$("#explorer-button").removeAttr("hidden")):r("notificationNotFound","warning")}})):r("notificationRetrieveFailed","warning")};$(document).ready(function(){return $(".data-epoch").each(function(){var t=new Date(1e3*$(this).text());return $(this).text(t.toLocaleString())}),$("#goback").attr("href",portal),$("body").on("click",".btn-success",function(){return n($(this).attr("notif"),$(this).attr("epoch"),$(this))}),$("body").on("click",".btn-danger",function(){return i($(this))}),$("body").on("click",".btn-info",function(){return e($("#explorer").is(":visible"))})})}.call(this);

View File

@ -1 +1 @@
{"version":3,"sources":["notifications.js"],"names":["displayError","msg","setMsg","toggle","toggle_explorer","toggle_eye","viewNotif","$","attr","level","html","window","translate","removeClass","addClass","j","status","err","console","log","slash","visible","hide","show","button","notif","epoch","each","this","text","removeAttr","ajax","type","url","portal","data","dataType","error","success","resp","myDate","result","notification","Date","toLocaleString","document","ready","on","is","call"],"mappings":"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"}
{"version":3,"sources":["notifications.js"],"names":["msg","$","attr","setMsg","level","html","window","translate","removeClass","addClass","displayError","j","status","err","console","log","toggle_eye","slash","toggle_explorer","visible","hide","show","toggle","button","notif","epoch","each","this","text","removeAttr","viewNotif","ajax","type","url","portal","data","dataType","error","success","resp","result","notification","myDate","Date","toLocaleString","document","ready","on","is","call"],"mappings":"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"}

View File

@ -5,11 +5,27 @@ LemonLDAP::NG Portal jQuery scripts
*/
(function() {
var datas, delKey, getCookie, getQueryParam, getValues, isHiddenFormValueSet, ping, removeOidcConsent, restoreOrder, setCookie, setKey, setOrder, setSelector, translate, translatePage, translationFields,
var datas, delKey, getCookie, getQueryParam, getValues, isHiddenFormValueSet, ping, removeOidcConsent, restoreOrder, setCookie, setDanger, setKey, setOrder, setSelector, translate, translatePage, translationFields,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
translationFields = {};
setDanger = function(cond, field) {
var result;
result = false;
if (cond) {
$("#" + field).addClass('fa-check text-success');
$("#" + field).removeClass('fa-times text-danger');
$("#" + field).attr('role', 'status');
} else {
$("#" + field).addClass('fa-times text-danger');
$("#" + field).removeClass('fa-check text-success');
$("#" + field).attr('role', 'alert');
result = true;
}
return result;
};
translatePage = function(lang) {
return $.getJSON(window.staticPrefix + "languages/" + lang + ".json", function(data) {
var k, ref, ref1, v;
@ -45,7 +61,10 @@ LemonLDAP::NG Portal jQuery scripts
}
});
$("[trplaceholder]").each(function() {
return $(this).attr('placeholder', translate($(this).attr('trplaceholder')));
var tmp;
tmp = translate($(this).attr('trplaceholder'));
$(this).attr('placeholder', tmp);
return $(this).attr('aria-label', tmp);
});
return $("[localtime]").each(function() {
var d;
@ -411,45 +430,25 @@ LemonLDAP::NG Portal jQuery scripts
var digit, hasforbidden, i, len, lower, nonwhitespechar, numspechar, ref3, ref4, result, upper;
result = true;
if (window.datas.ppolicy.minsize > 0) {
if (password.length >= window.datas.ppolicy.minsize) {
$('#ppolicy-minsize-feedback').addClass('fa-check text-success');
$('#ppolicy-minsize-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-minsize-feedback').removeClass('fa-check text-success');
$('#ppolicy-minsize-feedback').addClass('fa-times text-danger');
if (setDanger(password.length >= window.datas.ppolicy.minsize, 'ppolicy-minsize-feedback')) {
result = false;
}
}
if (window.datas.ppolicy.minupper > 0) {
upper = password.match(/[A-Z]/g);
if (upper && upper.length >= window.datas.ppolicy.minupper) {
$('#ppolicy-minupper-feedback').addClass('fa-check text-success');
$('#ppolicy-minupper-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-minupper-feedback').removeClass('fa-check text-success');
$('#ppolicy-minupper-feedback').addClass('fa-times text-danger');
if (setDanger(upper && upper.length >= window.datas.ppolicy.minupper, 'ppolicy-minupper-feedback')) {
result = false;
}
}
if (window.datas.ppolicy.minlower > 0) {
lower = password.match(/[a-z]/g);
if (lower && lower.length >= window.datas.ppolicy.minlower) {
$('#ppolicy-minlower-feedback').addClass('fa-check text-success');
$('#ppolicy-minlower-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-minlower-feedback').removeClass('fa-check text-success');
$('#ppolicy-minlower-feedback').addClass('fa-times text-danger');
if (setDanger(lower && lower.length >= window.datas.ppolicy.minlower, 'ppolicy-minlower-feedback')) {
result = false;
}
}
if (window.datas.ppolicy.mindigit > 0) {
digit = password.match(/[0-9]/g);
if (digit && digit.length >= window.datas.ppolicy.mindigit) {
$('#ppolicy-mindigit-feedback').addClass('fa-check text-success');
$('#ppolicy-mindigit-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-mindigit-feedback').removeClass('fa-check text-success');
$('#ppolicy-mindigit-feedback').addClass('fa-times text-danger');
if (setDanger(digit && digit.length >= window.datas.ppolicy.mindigit, 'ppolicy-mindigit-feedback')) {
result = false;
}
}
@ -466,12 +465,7 @@ LemonLDAP::NG Portal jQuery scripts
}
i++;
}
if (hasforbidden === false) {
$('#ppolicy-allowedspechar-feedback').addClass('fa-check text-success');
$('#ppolicy-allowedspechar-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-allowedspechar-feedback').removeClass('fa-check text-success');
$('#ppolicy-allowedspechar-feedback').addClass('fa-times text-danger');
if (setDanger(hasforbidden === false, 'ppolicy-allowedspechar-feedback')) {
result = false;
}
}
@ -485,12 +479,7 @@ LemonLDAP::NG Portal jQuery scripts
}
i++;
}
if (numspechar >= window.datas.ppolicy.minspechar) {
$('#ppolicy-minspechar-feedback').addClass('fa-check text-success');
$('#ppolicy-minspechar-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-minspechar-feedback').removeClass('fa-check text-success');
$('#ppolicy-minspechar-feedback').addClass('fa-times text-danger');
if (setDanger(numspechar >= window.datas.ppolicy.minspechar, 'ppolicy-minspechar-feedback')) {
result = false;
}
}
@ -503,12 +492,7 @@ LemonLDAP::NG Portal jQuery scripts
}
i++;
}
if (numspechar >= window.datas.ppolicy.minspechar) {
$('#ppolicy-minspechar-feedback').addClass('fa-check text-success');
$('#ppolicy-minspechar-feedback').removeClass('fa-times text-danger');
} else {
$('#ppolicy-minspechar-feedback').removeClass('fa-check text-success');
$('#ppolicy-minspechar-feedback').addClass('fa-times text-danger');
if (setDanger(numspechar >= window.datas.ppolicy.minspechar, 'ppolicy-minspechar-feedback')) {
result = false;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,8 @@ LemonLDAP::NG TOTP registration script
if (level === 'positive') {
level = 'success';
}
return $('#color').addClass("alert-" + level);
$('#color').addClass("alert-" + level);
return $('#msg').attr('role', (level === 'danger' ? 'alert' : 'status'));
};
displayError = function(j, status, err) {

View File

@ -1 +1 @@
(function(){var r,e,s,o,t;s=function(e,r){return $("#msg").attr("trspan",e),$("#msg").html(window.translate(e)),$("#color").removeClass("message-positive message-warning message-danger alert-success alert-warning alert-danger"),$("#color").addClass("message-"+r),"positive"===r&&(r="success"),$("#color").addClass("alert-"+r)},r=function(e,r,t){var o;if(console.log("Error",t),(o=JSON.parse(e.responseText))&&o.error)return o=o.error.replace(/.* /,""),console.log("Returned error",o),s(o,"warning")},o="",e=function(){return s("yourTotpKey","warning"),$.ajax({type:"POST",url:portal+"/2fregisters/totp/getkey",dataType:"json",error:r,success:function(e){var r,t;return e.error?(e.error.match(/totpExistingKey/)&&$("#divToHide").hide(),s(e.error,"warning")):e.portal&&e.user&&e.secret?($("#divToHide").show(),r="otpauth://totp/"+escape(e.portal)+":"+escape(e.user)+"?secret="+e.secret+"&issuer="+escape(e.portal),6!==e.digits&&(r+="&digits="+e.digits),30!==e.interval&&(r+="&period="+e.interval),new QRious({element:document.getElementById("qr"),value:r,size:150}),t=e.secret||"",$("#secret").text(t.toUpperCase().replace(/(.{4})/g,"$1 ").trim()),e.newkey?s("yourNewTotpKey","warning"):s("yourTotpKey","success"),o=e.token):s("PE24","danger")}})},t=function(){var e;return(e=$("#code").val())?$.ajax({type:"POST",url:portal+"/2fregisters/totp/verify",dataType:"json",data:{token:o,code:e,TOTPName:$("#TOTPName").val()},error:r,success:function(e){return e.error?e.error.match(/bad(Code|Name)/)?s(e.error,"warning"):s(e.error,"danger"):s("yourKeyIsRegistered","success")}}):(s("totpMissingCode","warning"),$("#code").focus())},$(document).ready(function(){return e(),$("#verify").on("click",function(){return t()})})}).call(this);
!function(){var s=function(e,r){return $("#msg").attr("trspan",e),$("#msg").html(window.translate(e)),$("#color").removeClass("message-positive message-warning message-danger alert-success alert-warning alert-danger"),$("#color").addClass("message-"+r),"positive"===r&&(r="success"),$("#color").addClass("alert-"+r),$("#msg").attr("role","danger"===r?"alert":"status")},r=function(e,r,t){if(console.log("Error",t),(e=JSON.parse(e.responseText))&&e.error)return e=e.error.replace(/.* /,""),console.log("Returned error",e),s(e,"warning")},t="",e=function(){return s("yourTotpKey","warning"),$.ajax({type:"POST",url:portal+"/2fregisters/totp/getkey",dataType:"json",error:r,success:function(e){var r;return e.error?(e.error.match(/totpExistingKey/)&&$("#divToHide").hide(),s(e.error,"warning")):e.portal&&e.user&&e.secret?($("#divToHide").show(),r="otpauth://totp/"+escape(e.portal)+":"+escape(e.user)+"?secret="+e.secret+"&issuer="+escape(e.portal),6!==e.digits&&(r+="&digits="+e.digits),30!==e.interval&&(r+="&period="+e.interval),new QRious({element:document.getElementById("qr"),value:r,size:150}),r=e.secret||"",$("#secret").text(r.toUpperCase().replace(/(.{4})/g,"$1 ").trim()),e.newkey?s("yourNewTotpKey","warning"):s("yourTotpKey","success"),t=e.token):s("PE24","danger")}})},o=function(){var e=$("#code").val();return e?$.ajax({type:"POST",url:portal+"/2fregisters/totp/verify",dataType:"json",data:{token:t,code:e,TOTPName:$("#TOTPName").val()},error:r,success:function(e){return e.error?e.error.match(/bad(Code|Name)/)?s(e.error,"warning"):s(e.error,"danger"):s("yourKeyIsRegistered","success")}}):(s("totpMissingCode","warning"),$("#code").focus())};$(document).ready(function(){return e(),$("#verify").on("click",o)})}.call(this);

View File

@ -1 +1 @@
{"version":3,"sources":["totpregistration.js"],"names":["displayError","getKey","setMsg","token","verify","msg","level","$","attr","html","window","translate","removeClass","addClass","j","status","err","res","console","log","JSON","parse","responseText","error","replace","ajax","type","url","portal","dataType","success","data","s","secret","match","hide","user","show","escape","digits","interval","QRious","element","document","getElementById","value","size","text","toUpperCase","trim","newkey","val","code","TOTPName","focus","ready","on","call","this"],"mappings":"CAMA,WACE,IAAIA,EAAcC,EAAQC,EAAQC,EAAOC,EAEzCF,EAAS,SAASG,EAAKC,GAQrB,OAPAC,EAAE,QAAQC,KAAK,SAAUH,GACzBE,EAAE,QAAQE,KAAKC,OAAOC,UAAUN,IAChCE,EAAE,UAAUK,YAAY,4FACxBL,EAAE,UAAUM,SAAS,WAAaP,GACpB,aAAVA,IACFA,EAAQ,WAEHC,EAAE,UAAUM,SAAS,SAAWP,IAGzCN,EAAe,SAASc,EAAGC,EAAQC,GACjC,IAAIC,EAGJ,GAFAC,QAAQC,IAAI,QAASH,IACrBC,EAAMG,KAAKC,MAAMP,EAAEQ,gBACRL,EAAIM,MAGb,OAFAN,EAAMA,EAAIM,MAAMC,QAAQ,MAAO,IAC/BN,QAAQC,IAAI,iBAAkBF,GACvBf,EAAOe,EAAK,YAIvBd,EAAQ,GAERF,EAAS,WAEP,OADAC,EAAO,cAAe,WACfK,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVN,MAAOvB,EACP8B,QAAS,SAASC,GAChB,IAAQC,EAAGC,EACX,OAAIF,EAAKR,OACHQ,EAAKR,MAAMW,MAAM,oBACnB3B,EAAE,cAAc4B,OAEXjC,EAAO6B,EAAKR,MAAO,YAEtBQ,EAAKH,QAAUG,EAAKK,MAAQL,EAAKE,QAGvC1B,EAAE,cAAc8B,OAChBL,EAAI,kBAAqBM,OAAOP,EAAKH,QAAW,IAAOU,OAAOP,EAAKK,MAAS,WAAaL,EAAKE,OAAS,WAAcK,OAAOP,EAAKH,QAC7G,IAAhBG,EAAKQ,SACPP,GAAK,WAAaD,EAAKQ,QAEH,KAAlBR,EAAKS,WACPR,GAAK,WAAaD,EAAKS,UAEpB,IAAIC,OAAO,CACdC,QAASC,SAASC,eAAe,MACjCC,MAAOb,EACPc,KAAM,MAERb,EAASF,EAAKE,QAAU,GACxB1B,EAAE,WAAWwC,KAAKd,EAAOe,cAAcxB,QAAQ,UAAW,OAAOyB,QAC7DlB,EAAKmB,OACPhD,EAAO,iBAAkB,WAEzBA,EAAO,cAAe,WAEjBC,EAAQ4B,EAAK5B,OAtBXD,EAAO,OAAQ,cA2B9BE,EAAS,WACP,IAAI+C,EAEJ,OADAA,EAAM5C,EAAE,SAAS4C,OAKR5C,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVE,KAAM,CACJ5B,MAAOA,EACPiD,KAAMD,EACNE,SAAU9C,EAAE,aAAa4C,OAE3B5B,MAAOvB,EACP8B,QAAS,SAASC,GAChB,OAAIA,EAAKR,MACHQ,EAAKR,MAAMW,MAAM,kBACZhC,EAAO6B,EAAKR,MAAO,WAEnBrB,EAAO6B,EAAKR,MAAO,UAGrBrB,EAAO,sBAAuB,eArB3CA,EAAO,kBAAmB,WACnBK,EAAE,SAAS+C,UA2BtB/C,EAAEoC,UAAUY,MAAM,WAEhB,OADAtD,IACOM,EAAE,WAAWiD,GAAG,QAAS,WAC9B,OAAOpD,UAIVqD,KAAKC"}
{"version":3,"sources":["totpregistration.js"],"names":["setMsg","msg","level","$","attr","html","window","translate","removeClass","addClass","displayError","j","status","err","console","log","res","JSON","parse","responseText","error","replace","token","getKey","ajax","type","url","portal","dataType","success","data","secret","match","hide","user","show","s","escape","digits","interval","QRious","element","document","getElementById","value","size","text","toUpperCase","trim","newkey","verify","val","code","TOTPName","focus","ready","on","call","this"],"mappings":"CAMA,WACE,IAEAA,EAAS,SAASC,EAAKC,GASrB,OARAC,EAAE,QAAQC,KAAK,SAAUH,GACzBE,EAAE,QAAQE,KAAKC,OAAOC,UAAUN,IAChCE,EAAE,UAAUK,YAAY,4FACxBL,EAAE,UAAUM,SAAS,WAAaP,GACpB,aAAVA,IACFA,EAAQ,WAEVC,EAAE,UAAUM,SAAS,SAAWP,GACzBC,EAAE,QAAQC,KAAK,OAAmB,WAAVF,EAAqB,QAAU,WAGhEQ,EAAe,SAASC,EAAGC,EAAQC,GAIjC,GAFAC,QAAQC,IAAI,QAASF,IACrBG,EAAMC,KAAKC,MAAMP,EAAEQ,gBACRH,EAAII,MAGb,OAFAJ,EAAMA,EAAII,MAAMC,QAAQ,MAAO,IAC/BP,QAAQC,IAAI,iBAAkBC,GACvBhB,EAAOgB,EAAK,YAIvBM,EAAQ,GAERC,EAAS,WAEP,OADAvB,EAAO,cAAe,WACfG,EAAEqB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVR,MAAOV,EACPmB,QAAS,SAASC,GAChB,IAAWC,EACX,OAAID,EAAKV,OACHU,EAAKV,MAAMY,MAAM,oBACnB7B,EAAE,cAAc8B,OAEXjC,EAAO8B,EAAKV,MAAO,YAEtBU,EAAKH,QAAUG,EAAKI,MAAQJ,EAAKC,QAGvC5B,EAAE,cAAcgC,OAChBC,EAAI,kBAAqBC,OAAOP,EAAKH,QAAW,IAAOU,OAAOP,EAAKI,MAAS,WAAaJ,EAAKC,OAAS,WAAcM,OAAOP,EAAKH,QAC7G,IAAhBG,EAAKQ,SACPF,GAAK,WAAaN,EAAKQ,QAEH,KAAlBR,EAAKS,WACPH,GAAK,WAAaN,EAAKS,UAEpB,IAAIC,OAAO,CACdC,QAASC,SAASC,eAAe,MACjCC,MAAOR,EACPS,KAAM,MAERd,EAASD,EAAKC,QAAU,GACxB5B,EAAE,WAAW2C,KAAKf,EAAOgB,cAAc1B,QAAQ,UAAW,OAAO2B,QAC7DlB,EAAKmB,OACPjD,EAAO,iBAAkB,WAEzBA,EAAO,cAAe,WAEjBsB,EAAQQ,EAAKR,OAtBXtB,EAAO,OAAQ,cA2B9BkD,EAAS,WACP,IACAC,EAAMhD,EAAE,SAASgD,MACjB,OAAKA,EAIIhD,EAAEqB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVE,KAAM,CACJR,MAAOA,EACP8B,KAAMD,EACNE,SAAUlD,EAAE,aAAagD,OAE3B/B,MAAOV,EACPmB,QAAS,SAASC,GAChB,OAAIA,EAAKV,MACHU,EAAKV,MAAMY,MAAM,kBACZhC,EAAO8B,EAAKV,MAAO,WAEnBpB,EAAO8B,EAAKV,MAAO,UAGrBpB,EAAO,sBAAuB,eArB3CA,EAAO,kBAAmB,WACnBG,EAAE,SAASmD,UA2BtBnD,EAAEuC,UAAUa,MAAM,WAEhB,OADAhC,IACOpB,EAAE,WAAWqD,GAAG,QACdN,MAIVO,KAAKC"}

View File

@ -15,7 +15,8 @@ LemonLDAP::NG U2F registration script
if (level === 'positive') {
level = 'success';
}
return $('#color').addClass("alert-" + level);
$('#color').addClass("alert-" + level);
return $('#msg').attr('role', (level === 'danger' ? 'alert' : 'status'));
};
displayError = function(j, status, err) {

View File

@ -1 +1 @@
(function(){var n,r,t,e;t=function(r,e){return $("#msg").attr("trspan",r),$("#msg").html(window.translate(r)),$("#color").removeClass("message-positive message-warning message-danger alert-success alert-warning alert-danger"),$("#color").addClass("message-"+e),"positive"===e&&(e="success"),$("#color").addClass("alert-"+e)},n=function(r,e,n){var s;if(console.log("Error",n),(s=JSON.parse(r.responseText))&&s.error)return s=s.error.replace(/.* /,""),console.log("Returned error",s),t(s,"warning")},r=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/register",data:{},dataType:"json",error:n,success:function(e){var r;return r=[{challenge:e.challenge,version:e.version}],t("touchU2fDevice","positive"),$("#u2fPermission").show(),u2f.register(e.appId,r,[],function(r){return $("#u2fPermission").hide(),r.errorCode?t(r.error,"warning"):$.ajax({type:"POST",url:portal+"2fregisters/u/registration",data:{registration:JSON.stringify(r),challenge:JSON.stringify(e),keyName:$("#keyName").val()},dataType:"json",success:function(r){return r.error?r.error.match(/badName/)?t(r.error,"warning"):t("u2fFailed","danger"):r.result?t("yourKeyIsRegistered","positive"):void 0},error:n})})}})},e=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/verify",data:{},dataType:"json",error:n,success:function(e){return t("touchU2fDevice","positive"),u2f.sign(e.appId,e.challenge,e.registeredKeys,function(r){return r.errorCode?t("unableToGetKey","warning"):$.ajax({type:"POST",url:portal+"2fregisters/u/signature",data:{signature:JSON.stringify(r),challenge:e.challenge},dataType:"json",success:function(r){return r.error?t("u2fFailed","danger"):r.result?t("yourKeyIsVerified","positive"):void 0},error:function(r,e,n){return console.log("error",n)}})})}})},$(document).ready(function(){return $("#u2fPermission").hide(),$("#register").on("click",r),$("#verify").on("click",e),$("#goback").attr("href",portal)})}).call(this);
!function(){var s=function(r,e){return $("#msg").attr("trspan",r),$("#msg").html(window.translate(r)),$("#color").removeClass("message-positive message-warning message-danger alert-success alert-warning alert-danger"),$("#color").addClass("message-"+e),"positive"===e&&(e="success"),$("#color").addClass("alert-"+e),$("#msg").attr("role","danger"===e?"alert":"status")},t=function(r,e,t){if(console.log("Error",t),(r=JSON.parse(r.responseText))&&r.error)return r=r.error.replace(/.* /,""),console.log("Returned error",r),s(r,"warning")},r=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/register",data:{},dataType:"json",error:t,success:function(e){var r=[{challenge:e.challenge,version:e.version}];return s("touchU2fDevice","positive"),$("#u2fPermission").show(),u2f.register(e.appId,r,[],function(r){return $("#u2fPermission").hide(),r.errorCode?s(r.error,"warning"):$.ajax({type:"POST",url:portal+"2fregisters/u/registration",data:{registration:JSON.stringify(r),challenge:JSON.stringify(e),keyName:$("#keyName").val()},dataType:"json",success:function(r){return r.error?r.error.match(/badName/)?s(r.error,"warning"):s("u2fFailed","danger"):r.result?s("yourKeyIsRegistered","positive"):void 0},error:t})})}})},e=function(){return $.ajax({type:"POST",url:portal+"2fregisters/u/verify",data:{},dataType:"json",error:t,success:function(e){return s("touchU2fDevice","positive"),u2f.sign(e.appId,e.challenge,e.registeredKeys,function(r){return r.errorCode?s("unableToGetKey","warning"):$.ajax({type:"POST",url:portal+"2fregisters/u/signature",data:{signature:JSON.stringify(r),challenge:e.challenge},dataType:"json",success:function(r){return r.error?s("u2fFailed","danger"):r.result?s("yourKeyIsVerified","positive"):void 0},error:function(r,e,t){return console.log("error",t)}})})}})};$(document).ready(function(){return $("#u2fPermission").hide(),$("#register").on("click",r),$("#verify").on("click",e),$("#goback").attr("href",portal)})}.call(this);

View File

@ -1 +1 @@
{"version":3,"sources":["u2fregistration.js"],"names":["displayError","register","setMsg","verify","msg","level","$","attr","html","window","translate","removeClass","addClass","j","status","err","res","console","log","JSON","parse","responseText","error","replace","ajax","type","url","portal","data","dataType","success","ch","request","challenge","version","show","u2f","appId","hide","errorCode","registration","stringify","keyName","val","resp","match","result","sign","registeredKeys","signature","document","ready","on","call","this"],"mappings":"CAMA,WACE,IAAIA,EAAcC,EAAUC,EAAQC,EAEpCD,EAAS,SAASE,EAAKC,GAQrB,OAPAC,EAAE,QAAQC,KAAK,SAAUH,GACzBE,EAAE,QAAQE,KAAKC,OAAOC,UAAUN,IAChCE,EAAE,UAAUK,YAAY,4FACxBL,EAAE,UAAUM,SAAS,WAAaP,GACpB,aAAVA,IACFA,EAAQ,WAEHC,EAAE,UAAUM,SAAS,SAAWP,IAGzCL,EAAe,SAASa,EAAGC,EAAQC,GACjC,IAAIC,EAGJ,GAFAC,QAAQC,IAAI,QAASH,IACrBC,EAAMG,KAAKC,MAAMP,EAAEQ,gBACRL,EAAIM,MAGb,OAFAN,EAAMA,EAAIM,MAAMC,QAAQ,MAAO,IAC/BN,QAAQC,IAAI,iBAAkBF,GACvBd,EAAOc,EAAK,YAIvBf,EAAW,WACT,OAAOK,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,yBACdC,KAAM,GACNC,SAAU,OACVP,MAAOtB,EACP8B,QAAS,SAASC,GAChB,IAAIC,EASJ,OARAA,EAAU,CACR,CACEC,UAAWF,EAAGE,UACdC,QAASH,EAAGG,UAGhBhC,EAAO,iBAAkB,YACzBI,EAAE,kBAAkB6B,OACbC,IAAInC,SAAS8B,EAAGM,MAAOL,EAAS,GAAI,SAASJ,GAElD,OADAtB,EAAE,kBAAkBgC,OAChBV,EAAKW,UACArC,EAAO0B,EAAKN,MAAO,WAEnBhB,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,6BACdC,KAAM,CACJY,aAAcrB,KAAKsB,UAAUb,GAC7BK,UAAWd,KAAKsB,UAAUV,GAC1BW,QAASpC,EAAE,YAAYqC,OAEzBd,SAAU,OACVC,QAAS,SAASc,GAChB,OAAIA,EAAKtB,MACHsB,EAAKtB,MAAMuB,MAAM,WACZ3C,EAAO0C,EAAKtB,MAAO,WAEnBpB,EAAO,YAAa,UAEpB0C,EAAKE,OACP5C,EAAO,sBAAuB,iBADhC,GAIToB,MAAOtB,UAQnBG,EAAS,WACP,OAAOG,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,uBACdC,KAAM,GACNC,SAAU,OACVP,MAAOtB,EACP8B,QAAS,SAASC,GAEhB,OADA7B,EAAO,iBAAkB,YAClBkC,IAAIW,KAAKhB,EAAGM,MAAON,EAAGE,UAAWF,EAAGiB,eAAgB,SAASpB,GAClE,OAAIA,EAAKW,UACArC,EAAO,iBAAkB,WAEzBI,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,0BACdC,KAAM,CACJqB,UAAW9B,KAAKsB,UAAUb,GAC1BK,UAAWF,EAAGE,WAEhBJ,SAAU,OACVC,QAAS,SAASc,GAChB,OAAIA,EAAKtB,MACApB,EAAO,YAAa,UAClB0C,EAAKE,OACP5C,EAAO,oBAAqB,iBAD9B,GAIToB,MAAO,SAAST,EAAGC,EAAQC,GACzB,OAAOE,QAAQC,IAAI,QAASH,YAS1CT,EAAE4C,UAAUC,MAAM,WAIhB,OAHA7C,EAAE,kBAAkBgC,OACpBhC,EAAE,aAAa8C,GAAG,QAASnD,GAC3BK,EAAE,WAAW8C,GAAG,QAASjD,GAClBG,EAAE,WAAWC,KAAK,OAAQoB,YAGlC0B,KAAKC"}
{"version":3,"sources":["u2fregistration.js"],"names":["setMsg","msg","level","$","attr","html","window","translate","removeClass","addClass","displayError","j","status","err","console","log","res","JSON","parse","responseText","error","replace","register","ajax","type","url","portal","data","dataType","success","ch","request","challenge","version","show","u2f","appId","hide","errorCode","registration","stringify","keyName","val","resp","match","result","verify","sign","registeredKeys","signature","document","ready","on","call","this"],"mappings":"CAMA,WACE,IAEAA,EAAS,SAASC,EAAKC,GASrB,OARAC,EAAE,QAAQC,KAAK,SAAUH,GACzBE,EAAE,QAAQE,KAAKC,OAAOC,UAAUN,IAChCE,EAAE,UAAUK,YAAY,4FACxBL,EAAE,UAAUM,SAAS,WAAaP,GACpB,aAAVA,IACFA,EAAQ,WAEVC,EAAE,UAAUM,SAAS,SAAWP,GACzBC,EAAE,QAAQC,KAAK,OAAmB,WAAVF,EAAqB,QAAU,WAGhEQ,EAAe,SAASC,EAAGC,EAAQC,GAIjC,GAFAC,QAAQC,IAAI,QAASF,IACrBG,EAAMC,KAAKC,MAAMP,EAAEQ,gBACRH,EAAII,MAGb,OAFAJ,EAAMA,EAAII,MAAMC,QAAQ,MAAO,IAC/BP,QAAQC,IAAI,iBAAkBC,GACvBhB,EAAOgB,EAAK,YAIvBM,EAAW,WACT,OAAOnB,EAAEoB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,yBACdC,KAAM,GACNC,SAAU,OACVR,MAAOV,EACPmB,QAAS,SAASC,GAChB,IACAC,EAAU,CACR,CACEC,UAAWF,EAAGE,UACdC,QAASH,EAAGG,UAKhB,OAFAjC,EAAO,iBAAkB,YACzBG,EAAE,kBAAkB+B,OACbC,IAAIb,SAASQ,EAAGM,MAAOL,EAAS,GAAI,SAASJ,GAElD,OADAxB,EAAE,kBAAkBkC,OAChBV,EAAKW,UACAtC,EAAO2B,EAAKP,MAAO,WAEnBjB,EAAEoB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,6BACdC,KAAM,CACJY,aAActB,KAAKuB,UAAUb,GAC7BK,UAAWf,KAAKuB,UAAUV,GAC1BW,QAAStC,EAAE,YAAYuC,OAEzBd,SAAU,OACVC,QAAS,SAASc,GAChB,OAAIA,EAAKvB,MACHuB,EAAKvB,MAAMwB,MAAM,WACZ5C,EAAO2C,EAAKvB,MAAO,WAEnBpB,EAAO,YAAa,UAEpB2C,EAAKE,OACP7C,EAAO,sBAAuB,iBADhC,GAIToB,MAAOV,UAQnBoC,EAAS,WACP,OAAO3C,EAAEoB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,uBACdC,KAAM,GACNC,SAAU,OACVR,MAAOV,EACPmB,QAAS,SAASC,GAEhB,OADA9B,EAAO,iBAAkB,YAClBmC,IAAIY,KAAKjB,EAAGM,MAAON,EAAGE,UAAWF,EAAGkB,eAAgB,SAASrB,GAClE,OAAIA,EAAKW,UACAtC,EAAO,iBAAkB,WAEzBG,EAAEoB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,0BACdC,KAAM,CACJsB,UAAWhC,KAAKuB,UAAUb,GAC1BK,UAAWF,EAAGE,WAEhBJ,SAAU,OACVC,QAAS,SAASc,GAChB,OAAIA,EAAKvB,MACApB,EAAO,YAAa,UAClB2C,EAAKE,OACP7C,EAAO,oBAAqB,iBAD9B,GAIToB,MAAO,SAAST,EAAGC,EAAQC,GACzB,OAAOC,QAAQC,IAAI,QAASF,YAS1CV,EAAE+C,UAAUC,MAAM,WAIhB,OAHAhD,EAAE,kBAAkBkC,OACpBlC,EAAE,aAAaiD,GAAG,QAAS9B,GAC3BnB,EAAE,WAAWiD,GAAG,QAASN,GAClB3C,EAAE,WAAWC,KAAK,OAAQsB,WAGlC2B,KAAKC"}

View File

@ -337,4 +337,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -337,4 +337,4 @@
"yourProfile":"Know your profile",
"yourTotpKey":"Your TOTP key",
"yubikey2f":"Yubikey"
}
}

View File

@ -337,4 +337,4 @@
"yourProfile":"Conozca su perfil",
"yourTotpKey":"Su llave TOTP",
"yubikey2f":"Yubikey"
}
}

Some files were not shown because too many files have changed in this diff Show More