Merge branch 'v2.0'

This commit is contained in:
Christophe Maudoux 2020-11-01 00:00:52 +01:00
commit ac98c223d3
108 changed files with 1109 additions and 472 deletions

1
debian/control vendored
View File

@ -285,6 +285,7 @@ Recommends: libcrypt-openssl-bignum-perl,
libgd-securityimage-perl, libgd-securityimage-perl,
libmime-tools-perl, libmime-tools-perl,
libnet-ldap-perl, libnet-ldap-perl,
libio-socket-timeout-perl,
libunicode-string-perl libunicode-string-perl
Suggests: gpg, Suggests: gpg,
libcrypt-u2f-server-perl, libcrypt-u2f-server-perl,

View File

@ -714,6 +714,28 @@
"$ref" : "#/components/schemas/casOptions" "$ref" : "#/components/schemas/casOptions"
} }
} }
};
defs.CasAppReplace = {
"type" : "object",
"properties" : {
"macros" : {
"type" : "object",
"example" : {
"myMacroName" : "$macro(rule)"
}
},
"exportedVars" : {
"type" : "object",
"default" : {
"cn" : "cn",
"mail" : "mail",
"uid" : "uid"
}
},
"options" : {
"$ref" : "#/components/schemas/casOptions"
}
}
}; };
defs.CasAppUpdate = { defs.CasAppUpdate = {
"type" : "object", "type" : "object",
@ -976,6 +998,38 @@
"$ref" : "#/components/schemas/OidcOptions" "$ref" : "#/components/schemas/OidcOptions"
} }
} }
};
defs.OidcRpReplace = {
"required" : [ "clientId", "redirectUris" ],
"type" : "object",
"properties" : {
"clientId" : {
"type" : "string"
},
"exportedVars" : {
"type" : "object",
"example" : {
"email" : "mail",
"family_name" : "sn",
"name" : "cn"
}
},
"extraClaims" : {
"type" : "object",
"example" : {
"myscope" : "myattr1 myattr2 myattr3"
}
},
"macros" : {
"type" : "object",
"example" : {
"myMacroName" : "$macro(rule)"
}
},
"options" : {
"$ref" : "#/components/schemas/OidcOptions"
}
}
}; };
defs.OidcRpUpdate = { defs.OidcRpUpdate = {
"type" : "object", "type" : "object",
@ -1111,6 +1165,31 @@
"$ref" : "#/components/schemas/samlOptions" "$ref" : "#/components/schemas/samlOptions"
} }
} }
};
defs.SamlSpReplace = {
"required" : [ "metadata" ],
"type" : "object",
"properties" : {
"metadata" : {
"type" : "string",
"example" : "<?xml version=\"1.0\"?><EntityDescriptor..."
},
"macros" : {
"type" : "object",
"example" : {
"myMacroName" : "$macro(rule)"
}
},
"exportedAttributes" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/samlAttribute"
}
},
"options" : {
"$ref" : "#/components/schemas/samlOptions"
}
}
}; };
defs.SamlSpUpdate = { defs.SamlSpUpdate = {
"type" : "object", "type" : "object",
@ -3233,7 +3312,7 @@ public class CasappApiExample {
CasappApi apiInstance = new CasappApi(); CasappApi apiInstance = new CasappApi();
confKey confKey = ; // confKey | Configuration key of CAS Application that needs to be replaced confKey confKey = ; // confKey | Configuration key of CAS Application that needs to be replaced
CasApp body = ; // CasApp | CasAppReplace body = ; // CasAppReplace |
try { try {
apiInstance.replaceCasApp(confKey, body); apiInstance.replaceCasApp(confKey, body);
} catch (ApiException e) { } catch (ApiException e) {
@ -3252,7 +3331,7 @@ public class CasappApiExample {
public static void main(String[] args) { public static void main(String[] args) {
CasappApi apiInstance = new CasappApi(); CasappApi apiInstance = new CasappApi();
confKey confKey = ; // confKey | Configuration key of CAS Application that needs to be replaced confKey confKey = ; // confKey | Configuration key of CAS Application that needs to be replaced
CasApp body = ; // CasApp | CasAppReplace body = ; // CasAppReplace |
try { try {
apiInstance.replaceCasApp(confKey, body); apiInstance.replaceCasApp(confKey, body);
} catch (ApiException e) { } catch (ApiException e) {
@ -3268,7 +3347,7 @@ public class CasappApiExample {
</div> --> </div> -->
<div class="tab-pane" id="examples-Casapp-replaceCasApp-0-objc"> <div class="tab-pane" id="examples-Casapp-replaceCasApp-0-objc">
<pre class="prettyprint"><code class="language-cpp">confKey *confKey = ; // Configuration key of CAS Application that needs to be replaced <pre class="prettyprint"><code class="language-cpp">confKey *confKey = ; // Configuration key of CAS Application that needs to be replaced
CasApp *body = ; // (optional) CasAppReplace *body = ; // (optional)
CasappApi *apiInstance = [[CasappApi alloc] init]; CasappApi *apiInstance = [[CasappApi alloc] init];
@ -3289,7 +3368,7 @@ CasappApi *apiInstance = [[CasappApi alloc] init];
var api = new LemonLdapngManagerApi.CasappApi() var api = new LemonLdapngManagerApi.CasappApi()
var confKey = ; // {{confKey}} Configuration key of CAS Application that needs to be replaced var confKey = ; // {{confKey}} Configuration key of CAS Application that needs to be replaced
var opts = { var opts = {
'body': // {{CasApp}} 'body': // {{CasAppReplace}}
}; };
var callback = function(error, data, response) { var callback = function(error, data, response) {
if (error) { if (error) {
@ -3321,7 +3400,7 @@ namespace Example
var apiInstance = new CasappApi(); var apiInstance = new CasappApi();
var confKey = new confKey(); // confKey | Configuration key of CAS Application that needs to be replaced var confKey = new confKey(); // confKey | Configuration key of CAS Application that needs to be replaced
var body = new CasApp(); // CasApp | (optional) var body = new CasAppReplace(); // CasAppReplace | (optional)
try try
{ {
@ -3344,7 +3423,7 @@ require_once(__DIR__ . '/vendor/autoload.php');
$api_instance = new Swagger\Client\ApiCasappApi(); $api_instance = new Swagger\Client\ApiCasappApi();
$confKey = ; // confKey | Configuration key of CAS Application that needs to be replaced $confKey = ; // confKey | Configuration key of CAS Application that needs to be replaced
$body = ; // CasApp | $body = ; // CasAppReplace |
try { try {
$api_instance->replaceCasApp($confKey, $body); $api_instance->replaceCasApp($confKey, $body);
@ -3361,7 +3440,7 @@ use WWW::SwaggerClient::CasappApi;
my $api_instance = WWW::SwaggerClient::CasappApi->new(); my $api_instance = WWW::SwaggerClient::CasappApi->new();
my $confKey = ; # confKey | Configuration key of CAS Application that needs to be replaced my $confKey = ; # confKey | Configuration key of CAS Application that needs to be replaced
my $body = WWW::SwaggerClient::Object::CasApp->new(); # CasApp | my $body = WWW::SwaggerClient::Object::CasAppReplace->new(); # CasAppReplace |
eval { eval {
$api_instance->replaceCasApp(confKey => $confKey, body => $body); $api_instance->replaceCasApp(confKey => $confKey, body => $body);
@ -3381,7 +3460,7 @@ from pprint import pprint
# create an instance of the API class # create an instance of the API class
api_instance = swagger_client.CasappApi() api_instance = swagger_client.CasappApi()
confKey = # confKey | Configuration key of CAS Application that needs to be replaced confKey = # confKey | Configuration key of CAS Application that needs to be replaced
body = # CasApp | (optional) body = # CasAppReplace | (optional)
try: try:
# Replaces a CAS Application # Replaces a CAS Application
@ -3440,7 +3519,7 @@ except ApiException as e:
"content" : { "content" : {
"application/json" : { "application/json" : {
"schema" : { "schema" : {
"$ref" : "#/components/schemas/CasApp" "$ref" : "#/components/schemas/CasAppReplace"
} }
} }
} }
@ -13528,7 +13607,7 @@ public class OidcrpApiExample {
OidcrpApi apiInstance = new OidcrpApi(); OidcrpApi apiInstance = new OidcrpApi();
confKey confKey = ; // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced confKey confKey = ; // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced
OidcRp body = ; // OidcRp | OidcRpReplace body = ; // OidcRpReplace |
try { try {
apiInstance.replaceOidcRp(confKey, body); apiInstance.replaceOidcRp(confKey, body);
} catch (ApiException e) { } catch (ApiException e) {
@ -13547,7 +13626,7 @@ public class OidcrpApiExample {
public static void main(String[] args) { public static void main(String[] args) {
OidcrpApi apiInstance = new OidcrpApi(); OidcrpApi apiInstance = new OidcrpApi();
confKey confKey = ; // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced confKey confKey = ; // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced
OidcRp body = ; // OidcRp | OidcRpReplace body = ; // OidcRpReplace |
try { try {
apiInstance.replaceOidcRp(confKey, body); apiInstance.replaceOidcRp(confKey, body);
} catch (ApiException e) { } catch (ApiException e) {
@ -13563,7 +13642,7 @@ public class OidcrpApiExample {
</div> --> </div> -->
<div class="tab-pane" id="examples-Oidcrp-replaceOidcRp-0-objc"> <div class="tab-pane" id="examples-Oidcrp-replaceOidcRp-0-objc">
<pre class="prettyprint"><code class="language-cpp">confKey *confKey = ; // Configuration key of OpenID Connect Relaying Party that needs to be replaced <pre class="prettyprint"><code class="language-cpp">confKey *confKey = ; // Configuration key of OpenID Connect Relaying Party that needs to be replaced
OidcRp *body = ; // (optional) OidcRpReplace *body = ; // (optional)
OidcrpApi *apiInstance = [[OidcrpApi alloc] init]; OidcrpApi *apiInstance = [[OidcrpApi alloc] init];
@ -13584,7 +13663,7 @@ OidcrpApi *apiInstance = [[OidcrpApi alloc] init];
var api = new LemonLdapngManagerApi.OidcrpApi() var api = new LemonLdapngManagerApi.OidcrpApi()
var confKey = ; // {{confKey}} Configuration key of OpenID Connect Relaying Party that needs to be replaced var confKey = ; // {{confKey}} Configuration key of OpenID Connect Relaying Party that needs to be replaced
var opts = { var opts = {
'body': // {{OidcRp}} 'body': // {{OidcRpReplace}}
}; };
var callback = function(error, data, response) { var callback = function(error, data, response) {
if (error) { if (error) {
@ -13616,7 +13695,7 @@ namespace Example
var apiInstance = new OidcrpApi(); var apiInstance = new OidcrpApi();
var confKey = new confKey(); // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced var confKey = new confKey(); // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced
var body = new OidcRp(); // OidcRp | (optional) var body = new OidcRpReplace(); // OidcRpReplace | (optional)
try try
{ {
@ -13639,7 +13718,7 @@ require_once(__DIR__ . '/vendor/autoload.php');
$api_instance = new Swagger\Client\ApiOidcrpApi(); $api_instance = new Swagger\Client\ApiOidcrpApi();
$confKey = ; // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced $confKey = ; // confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced
$body = ; // OidcRp | $body = ; // OidcRpReplace |
try { try {
$api_instance->replaceOidcRp($confKey, $body); $api_instance->replaceOidcRp($confKey, $body);
@ -13656,7 +13735,7 @@ use WWW::SwaggerClient::OidcrpApi;
my $api_instance = WWW::SwaggerClient::OidcrpApi->new(); my $api_instance = WWW::SwaggerClient::OidcrpApi->new();
my $confKey = ; # confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced my $confKey = ; # confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced
my $body = WWW::SwaggerClient::Object::OidcRp->new(); # OidcRp | my $body = WWW::SwaggerClient::Object::OidcRpReplace->new(); # OidcRpReplace |
eval { eval {
$api_instance->replaceOidcRp(confKey => $confKey, body => $body); $api_instance->replaceOidcRp(confKey => $confKey, body => $body);
@ -13676,7 +13755,7 @@ from pprint import pprint
# create an instance of the API class # create an instance of the API class
api_instance = swagger_client.OidcrpApi() api_instance = swagger_client.OidcrpApi()
confKey = # confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced confKey = # confKey | Configuration key of OpenID Connect Relaying Party that needs to be replaced
body = # OidcRp | (optional) body = # OidcRpReplace | (optional)
try: try:
# Replaces an OpenID Connect Relaying Party # Replaces an OpenID Connect Relaying Party
@ -13735,7 +13814,7 @@ except ApiException as e:
"content" : { "content" : {
"application/json" : { "application/json" : {
"schema" : { "schema" : {
"$ref" : "#/components/schemas/OidcRp" "$ref" : "#/components/schemas/OidcRpReplace"
} }
} }
} }
@ -16236,7 +16315,7 @@ public class SamlspApiExample {
SamlspApi apiInstance = new SamlspApi(); SamlspApi apiInstance = new SamlspApi();
confKey confKey = ; // confKey | Configuration key of SAML Service Provider that needs to be replaced confKey confKey = ; // confKey | Configuration key of SAML Service Provider that needs to be replaced
SamlSp body = ; // SamlSp | SamlSpReplace body = ; // SamlSpReplace |
try { try {
apiInstance.replaceSamlSp(confKey, body); apiInstance.replaceSamlSp(confKey, body);
} catch (ApiException e) { } catch (ApiException e) {
@ -16255,7 +16334,7 @@ public class SamlspApiExample {
public static void main(String[] args) { public static void main(String[] args) {
SamlspApi apiInstance = new SamlspApi(); SamlspApi apiInstance = new SamlspApi();
confKey confKey = ; // confKey | Configuration key of SAML Service Provider that needs to be replaced confKey confKey = ; // confKey | Configuration key of SAML Service Provider that needs to be replaced
SamlSp body = ; // SamlSp | SamlSpReplace body = ; // SamlSpReplace |
try { try {
apiInstance.replaceSamlSp(confKey, body); apiInstance.replaceSamlSp(confKey, body);
} catch (ApiException e) { } catch (ApiException e) {
@ -16271,7 +16350,7 @@ public class SamlspApiExample {
</div> --> </div> -->
<div class="tab-pane" id="examples-Samlsp-replaceSamlSp-0-objc"> <div class="tab-pane" id="examples-Samlsp-replaceSamlSp-0-objc">
<pre class="prettyprint"><code class="language-cpp">confKey *confKey = ; // Configuration key of SAML Service Provider that needs to be replaced <pre class="prettyprint"><code class="language-cpp">confKey *confKey = ; // Configuration key of SAML Service Provider that needs to be replaced
SamlSp *body = ; // (optional) SamlSpReplace *body = ; // (optional)
SamlspApi *apiInstance = [[SamlspApi alloc] init]; SamlspApi *apiInstance = [[SamlspApi alloc] init];
@ -16292,7 +16371,7 @@ SamlspApi *apiInstance = [[SamlspApi alloc] init];
var api = new LemonLdapngManagerApi.SamlspApi() var api = new LemonLdapngManagerApi.SamlspApi()
var confKey = ; // {{confKey}} Configuration key of SAML Service Provider that needs to be replaced var confKey = ; // {{confKey}} Configuration key of SAML Service Provider that needs to be replaced
var opts = { var opts = {
'body': // {{SamlSp}} 'body': // {{SamlSpReplace}}
}; };
var callback = function(error, data, response) { var callback = function(error, data, response) {
if (error) { if (error) {
@ -16324,7 +16403,7 @@ namespace Example
var apiInstance = new SamlspApi(); var apiInstance = new SamlspApi();
var confKey = new confKey(); // confKey | Configuration key of SAML Service Provider that needs to be replaced var confKey = new confKey(); // confKey | Configuration key of SAML Service Provider that needs to be replaced
var body = new SamlSp(); // SamlSp | (optional) var body = new SamlSpReplace(); // SamlSpReplace | (optional)
try try
{ {
@ -16347,7 +16426,7 @@ require_once(__DIR__ . '/vendor/autoload.php');
$api_instance = new Swagger\Client\ApiSamlspApi(); $api_instance = new Swagger\Client\ApiSamlspApi();
$confKey = ; // confKey | Configuration key of SAML Service Provider that needs to be replaced $confKey = ; // confKey | Configuration key of SAML Service Provider that needs to be replaced
$body = ; // SamlSp | $body = ; // SamlSpReplace |
try { try {
$api_instance->replaceSamlSp($confKey, $body); $api_instance->replaceSamlSp($confKey, $body);
@ -16364,7 +16443,7 @@ use WWW::SwaggerClient::SamlspApi;
my $api_instance = WWW::SwaggerClient::SamlspApi->new(); my $api_instance = WWW::SwaggerClient::SamlspApi->new();
my $confKey = ; # confKey | Configuration key of SAML Service Provider that needs to be replaced my $confKey = ; # confKey | Configuration key of SAML Service Provider that needs to be replaced
my $body = WWW::SwaggerClient::Object::SamlSp->new(); # SamlSp | my $body = WWW::SwaggerClient::Object::SamlSpReplace->new(); # SamlSpReplace |
eval { eval {
$api_instance->replaceSamlSp(confKey => $confKey, body => $body); $api_instance->replaceSamlSp(confKey => $confKey, body => $body);
@ -16384,7 +16463,7 @@ from pprint import pprint
# create an instance of the API class # create an instance of the API class
api_instance = swagger_client.SamlspApi() api_instance = swagger_client.SamlspApi()
confKey = # confKey | Configuration key of SAML Service Provider that needs to be replaced confKey = # confKey | Configuration key of SAML Service Provider that needs to be replaced
body = # SamlSp | (optional) body = # SamlSpReplace | (optional)
try: try:
# Replaces a SAML Service # Replaces a SAML Service
@ -16443,7 +16522,7 @@ except ApiException as e:
"content" : { "content" : {
"application/json" : { "application/json" : {
"schema" : { "schema" : {
"$ref" : "#/components/schemas/SamlSp" "$ref" : "#/components/schemas/SamlSpReplace"
} }
} }
} }

View File

@ -34,10 +34,46 @@ authentication:
</tomcat-users> </tomcat-users>
LL::NG provides a valve, available on :doc:`download page</download>`. LL::NG provides a valve that will check an HTTP header to set the authenticated user on
This valve will check an HTTP header to set the authenticated user on
the J2EE container. the J2EE container.
Compilation
-----------
The sources are available at `<https://github.com/LemonLDAPNG/lemonldap-valve-tomcat>`__
Required :
- ant
- jre > 1.4
- tomcat >= 5.5
Configure your tomcat home in ``build.properties`` files.
.. attention::
Be careful for Windows user, path must contains "/".
Example:
::
c:/my hardisk/tomcat/
Next run ant command:
::
ant
``ValveLemonLDAPNG.jar`` is created under ``/dist`` directory.
.. |image0| image:: /applications/tomcat_logo.png
:class: align-center
Installation Installation
------------ ------------
@ -85,40 +121,3 @@ Configure attributes:
in debug level. See `how configure logging in in debug level. See `how configure logging in
Tomcat <http://tomcat.apache.org/tomcat-5.5-doc/logging.html>`__ . Tomcat <http://tomcat.apache.org/tomcat-5.5-doc/logging.html>`__ .
Compilation
-----------
The sources are available on :doc:`download page</download>`.
Required :
- ant
- jre > 1.4
- tomcat >= 5.5
Configure your tomcat home in ``build.properties`` files.
.. attention::
Be careful for Windows user, path must contains "/".
Example:
::
c:/my hardisk/tomcat/
Next run ant command:
::
ant
``ValveLemonLDAPNG.jar`` is created under ``/dist`` directory.
.. |image0| image:: /applications/tomcat_logo.png
:class: align-center

View File

@ -92,7 +92,8 @@ Connection
bind is used. bind is used.
- **Password**: password to used to connect to LDAP server. By default, - **Password**: password to used to connect to LDAP server. By default,
anonymous bind is used. anonymous bind is used.
- **Timeout**: server idle timeout. - **Connection timeout**: applies only when initiating the connection
- **Operation timeout**: applies to all LDAP operations
- **Version**: LDAP protocol version. - **Version**: LDAP protocol version.
- **Binary attributes**: regular expression matching binary attributes - **Binary attributes**: regular expression matching binary attributes
(see (see

View File

@ -506,12 +506,13 @@ Some options are available:
- Type: handler type (normal, - Type: handler type (normal,
:doc:`ServiceToken Handler<servertoserver>`, :doc:`ServiceToken Handler<servertoserver>`,
:doc:`DevOps Handler<devopshandler>`,...) :doc:`DevOps Handler<devopshandler>`,...)
- Authentication level required: this option avoids to reject user with - Required authentication level: this option avoids to reject user with
a rule based on ``$_authenticationLevel``. When user hasn't got the a rule based on ``$_authenticationLevel``. When user has not got the
required level, he is redirected to an upgrade page in the portal. required level, he is redirected to an upgrade page in the portal.
This level is applied to ALL VirtualHost locations. This default level is required for ALL locations relative to this virtual host.
- ServiceToken timeout: The Service Token is only available during 30 It can be overrided for each locations.
seconds by default. This TTL can be customized for each virtual host. - ServiceToken timeout: by default, ServiceToken is just valid during 30
seconds. This TTL can be customized for each virtual host.
.. danger:: .. danger::

View File

@ -22,6 +22,8 @@ can be forbidden to assume.
identities like CEO, administrators or anonymous/protected users. identities like CEO, administrators or anonymous/protected users.
- **Unrestricted users rule**: Rule to define which users can switch - **Unrestricted users rule**: Rule to define which users can switch
context of ALL users. ``Identities use rule`` is bypassed. context of ALL users. ``Identities use rule`` is bypassed.
- **Allow 2FA modifications**: This option must be enabled to append,
verify or delete a second factor during context switching.
- **Stop by logout**: Stop context switching by sending a logout - **Stop by logout**: Stop context switching by sending a logout
request. request.

View File

@ -241,6 +241,7 @@ ldapSearchDeref "deref" param of Net::LD
ldapServer LDAP server (host or URI) ✔ ldapServer LDAP server (host or URI) ✔
ldapSetPassword ✔ ldapSetPassword ✔
ldapTimeout LDAP connection timeout ✔ ldapTimeout LDAP connection timeout ✔
ldapIOTimeout LDAP operation timeout ✔
ldapUsePasswordResetAttribute LDAP store reset flag in an attribute ✔ ldapUsePasswordResetAttribute LDAP store reset flag in an attribute ✔
ldapVerify Whether to validate LDAP certificates ✔ ldapVerify Whether to validate LDAP certificates ✔
ldapVersion LDAP protocol version ✔ ldapVersion LDAP protocol version ✔

View File

@ -308,7 +308,7 @@ Buttons
This node allows one to enable/disable buttons on the login page: This node allows one to enable/disable buttons on the login page:
- **Check last logins**: displays a checkbox on login form, allowing - **Check last logins**: display a checkbox on login form, allowing
user to check his login history right after opening session user to check his login history right after opening session
- **Reset password**: display a link to - **Reset password**: display a link to
:doc:`reset your password page<resetpassword>` (for password based :doc:`reset your password page<resetpassword>` (for password based
@ -316,6 +316,8 @@ This node allows one to enable/disable buttons on the login page:
times by default) times by default)
- **Register**: display a link to :doc:`register page<register>` (for - **Register**: display a link to :doc:`register page<register>` (for
password based authentication backends) password based authentication backends)
- **Reset certificate**: display a link to :doc:`reset certificate page<resetcertificate>` (for
password based authentication backends)
Password management Password management
------------------- -------------------

View File

@ -48,9 +48,9 @@ rule.
Self-care on Portal Self-care on Portal
------------------- -------------------
User may register second facrots themselves on the Portal by using the 2FA Manager. User may register second factors themselves on the Portal by using the 2FA Manager.
The link will be displayed if at least a SFA module is enabled. You can set a The link will be displayed if at least one SFA module is enabled. You can set a
rule to display or not the link. rule to display or not the link.
Session upgrade through 2FA Session upgrade through 2FA

View File

@ -10,6 +10,7 @@ To configure sessions, go in Manager, ``General Parameters`` »
- **Store user password in session data**: see - **Store user password in session data**: see
:doc:`password store documentation<passwordstore>`. :doc:`password store documentation<passwordstore>`.
- **Display session identifier**: Should the session ID be displayed in the manager's session explorer. The session ID is a sensitive information that should only be shown to highly trusted administrators.
- **Sessions timeout**: Maximum lifetime of a session. Old sessions are - **Sessions timeout**: Maximum lifetime of a session. Old sessions are
deleted by a cron script. deleted by a cron script.
- **Sessions activity timeout**: Maximum inactivity duration. - **Sessions activity timeout**: Maximum inactivity duration.

View File

@ -86,13 +86,13 @@ current URL.
Rules can also be used to intercept logout URL: Rules can also be used to intercept logout URL:
================================================================================================================= =================== ==== ================================================================================================================= =================== =====================================
Goal Regular expression Rule Goal Regular expression Rule
================================================================================================================= =================== ==== ================================================================================================================= =================== =====================================
Logout user from Lemonldap::NG and redirect it to http://intranet/ ^/index.php\?logout Logout user from Lemonldap::NG and redirect it to http://intranet/ ^/index.php\?logout logout_sso http://intranet/
Logout user from current application and redirect it to the menu **(Apache only)** ^/index.php\?logout Logout user from current application and redirect it to the menu **(Apache only)** ^/index.php\?logout logout_app https://auth.example.com/
Logout user from current application and from Lemonldap::NG and redirect it to http://intranet/ **(Apache only)** ^/index.php\?logout Logout user from current application and from Lemonldap::NG and redirect it to http://intranet/ **(Apache only)** ^/index.php\?logout logout_app_sso http://intranet/
================================================================================================================= =================== ==== ================================================================================================================= =================== =====================================
.. danger:: .. danger::

View File

@ -135,7 +135,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/SamlSp' $ref: '#/components/schemas/SamlSpReplace'
responses: responses:
204: 204:
$ref: '#/components/responses/NoContent' $ref: '#/components/responses/NoContent'
@ -327,7 +327,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/OidcRp' $ref: '#/components/schemas/OidcRpReplace'
responses: responses:
204: 204:
$ref: '#/components/responses/NoContent' $ref: '#/components/responses/NoContent'
@ -469,7 +469,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/CasApp' $ref: '#/components/schemas/CasAppReplace'
responses: responses:
204: 204:
$ref: '#/components/responses/NoContent' $ref: '#/components/responses/NoContent'
@ -1067,6 +1067,24 @@ components:
$ref: '#/components/schemas/samlAttribute' $ref: '#/components/schemas/samlAttribute'
options: options:
$ref: '#/components/schemas/samlOptions' $ref: '#/components/schemas/samlOptions'
SamlSpReplace:
type: object
required:
- metadata
properties:
metadata:
type: string
example: '<?xml version="1.0"?><EntityDescriptor...'
macros:
type: object
example:
myMacroName: "$macro(rule)"
exportedAttributes:
type: object
items:
$ref: '#/components/schemas/samlAttribute'
options:
$ref: '#/components/schemas/samlOptions'
samlOptions: samlOptions:
type: object type: object
properties: properties:
@ -1257,6 +1275,30 @@ components:
myMacroName: "$macro(rule)" myMacroName: "$macro(rule)"
options: options:
$ref: '#/components/schemas/OidcOptions' $ref: '#/components/schemas/OidcOptions'
OidcRpReplace:
type: object
required:
- clientId
- redirectUris
properties:
clientId:
type: string
exportedVars:
type: object
example:
email: mail
family_name: sn
name: cn
extraClaims:
type: object
example:
myscope: "myattr1 myattr2 myattr3"
macros:
type: object
example:
myMacroName: "$macro(rule)"
options:
$ref: '#/components/schemas/OidcOptions'
CasApp: CasApp:
required: required:
@ -1292,6 +1334,21 @@ components:
uid: uid uid: uid
options: options:
$ref: '#/components/schemas/casOptions' $ref: '#/components/schemas/casOptions'
CasAppReplace:
type: object
properties:
macros:
type: object
example:
myMacroName: "$macro(rule)"
exportedVars:
type: object
default:
cn: cn
mail: mail
uid: uid
options:
$ref: '#/components/schemas/casOptions'
casOptions: casOptions:
required: required:
- service - service

View File

@ -30,7 +30,7 @@ use constant DEFAULTCONFBACKENDOPTIONS => (
dirName => '/usr/local/lemonldap-ng/data/conf', dirName => '/usr/local/lemonldap-ng/data/conf',
); );
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/; our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|a(?:(?:daptativeAuthenticationLevelR|ut(?:hChoiceMod|oSigninR))ules|pplicationList)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:State|User|XSS)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/; our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|f(?:RemovedUseNotif|OnlyUpgrade)|kip(?:Upgrade|Renew)Confirmation|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|CertificateResetByMail|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:o(?:ntextSwitching(?:Allowed2fModifications|StopWithLogout)|mpactConf|rsEnabled)|a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:State|User|XSS)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|d(?:is(?:ablePersistentStorage|playSessionId)|biDynamicHashEnabled)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' ); our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -72,8 +72,9 @@ sub defaultValues {
'mail' => 'mail', 'mail' => 'mail',
'uid' => 'uid' 'uid' => 'uid'
}, },
'domain' => 'example.com', 'displaySessionId' => 1,
'exportedVars' => { 'domain' => 'example.com',
'exportedVars' => {
'UA' => 'HTTP_USER_AGENT' 'UA' => 'HTTP_USER_AGENT'
}, },
'ext2fActivation' => 0, 'ext2fActivation' => 0,
@ -139,12 +140,13 @@ sub defaultValues {
'ldapGroupAttributeNameSearch' => 'cn', 'ldapGroupAttributeNameSearch' => 'cn',
'ldapGroupAttributeNameUser' => 'dn', 'ldapGroupAttributeNameUser' => 'dn',
'ldapGroupObjectClass' => 'groupOfNames', 'ldapGroupObjectClass' => 'groupOfNames',
'ldapIOTimeout' => 10,
'ldapPasswordResetAttribute' => 'pwdReset', 'ldapPasswordResetAttribute' => 'pwdReset',
'ldapPasswordResetAttributeValue' => 'TRUE', 'ldapPasswordResetAttributeValue' => 'TRUE',
'ldapPwdEnc' => 'utf-8', 'ldapPwdEnc' => 'utf-8',
'ldapSearchDeref' => 'find', 'ldapSearchDeref' => 'find',
'ldapServer' => 'ldap://localhost', 'ldapServer' => 'ldap://localhost',
'ldapTimeout' => 120, 'ldapTimeout' => 10,
'ldapUsePasswordResetAttribute' => 1, 'ldapUsePasswordResetAttribute' => 1,
'ldapVerify' => 'require', 'ldapVerify' => 'require',
'ldapVersion' => 3, 'ldapVersion' => 3,

View File

@ -45,7 +45,7 @@ our $authParameters = {
githubParams => [qw(githubAuthnLevel githubClientID githubClientSecret githubUserField githubScope)], githubParams => [qw(githubAuthnLevel githubClientID githubClientSecret githubUserField githubScope)],
gpgParams => [qw(gpgAuthnLevel gpgDb)], gpgParams => [qw(gpgAuthnLevel gpgDb)],
kerberosParams => [qw(krbAuthnLevel krbKeytab krbByJs krbRemoveDomain)], kerberosParams => [qw(krbAuthnLevel krbKeytab krbByJs krbRemoveDomain)],
ldapParams => [qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapVerify ldapBase managerDn managerPassword ldapTimeout ldapVersion ldapRaw ldapCAFile ldapCAPath LDAPFilter AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapITDS)], ldapParams => [qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapVerify ldapBase managerDn managerPassword ldapTimeout ldapIOTimeout ldapVersion ldapRaw ldapCAFile ldapCAPath LDAPFilter AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapITDS)],
linkedinParams => [qw(linkedInAuthnLevel linkedInClientID linkedInClientSecret linkedInFields linkedInUserField linkedInScope)], linkedinParams => [qw(linkedInAuthnLevel linkedInClientID linkedInClientSecret linkedInFields linkedInUserField linkedInScope)],
nullParams => [qw(nullAuthnLevel)], nullParams => [qw(nullAuthnLevel)],
oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)], oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],

View File

@ -1,6 +1,8 @@
package Lemonldap::NG::Handler::Lib::CDA; package Lemonldap::NG::Handler::Lib::CDA;
use strict; use strict;
use URI;
use URI::QueryParam;
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
@ -9,7 +11,7 @@ sub run {
my $uri = $req->{env}->{REQUEST_URI}; my $uri = $req->{env}->{REQUEST_URI};
my $cn = $class->tsv->{cookieName}; my $cn = $class->tsv->{cookieName};
my ( $id, $session ); my ( $id, $session );
if ( $uri =~ s/[\?&;]${cn}cda=(\w+)$//oi ) { if ( $uri =~ m/[\?&;]${cn}cda=(\w+)/oi ) {
if ( $id = $class->fetchId($req) if ( $id = $class->fetchId($req)
and $session = $class->retrieveSession( $req, $id ) ) and $session = $class->retrieveSession( $req, $id ) )
{ {
@ -17,7 +19,13 @@ sub run {
'CDA asked for an already available session, skipping'); 'CDA asked for an already available session, skipping');
} }
else { else {
my $cdaid = $1; # Extract CDA code from URI
my $u = URI->new( $req->uri );
my $cdaid = $u->query_param("${cn}cda");
# Remove CDA param from URI
$u->query_param_delete("${cn}cda");
$class->logger->debug("CDA request with id $cdaid"); $class->logger->debug("CDA request with id $cdaid");
my $cdaInfos = $class->getCDAInfos( $req, $cdaid ); my $cdaInfos = $class->getCDAInfos( $req, $cdaid );
@ -26,7 +34,7 @@ sub run {
return $class->FORBIDDEN; return $class->FORBIDDEN;
} }
my $redirectUrl = $class->_buildUrl( $req, $uri ); my $redirectUrl = $class->_buildUrl( $req, $u->path_query );
my $redirectHttps = ( $redirectUrl =~ m/^https/ ); my $redirectHttps = ( $redirectUrl =~ m/^https/ );
$class->set_header_out( $class->set_header_out(
$req, $req,

View File

@ -57,6 +57,8 @@ sub checkConf {
$class->logger->debug($Lemonldap::NG::Common::Conf::msg); $class->logger->debug($Lemonldap::NG::Common::Conf::msg);
} }
} }
$Lemonldap::NG::Common::Conf::msg = '';
if ( $force or !$class->cfgNum or $class->cfgNum != $conf->{cfgNum} ) { if ( $force or !$class->cfgNum or $class->cfgNum != $conf->{cfgNum} ) {
$class->logger->debug("Get configuration $conf->{cfgNum}"); $class->logger->debug("Get configuration $conf->{cfgNum}");
unless ( $class->cfgNum( $conf->{cfgNum} ) ) { unless ( $class->cfgNum( $conf->{cfgNum} ) ) {

View File

@ -45,6 +45,8 @@ sub init {
$self->setTypes($conf); $self->setTypes($conf);
$self->{multiValuesSeparator} ||= '; '; $self->{multiValuesSeparator} ||= '; ';
$self->{hiddenAttributes} //= "_password"; $self->{hiddenAttributes} //= "_password";
$self->{hiddenAttributes} .= ' _session_id'
unless $conf->{displaySessionId};
$self->{TOTPCheck} = $self->{U2FCheck} = $self->{UBKCheck} = '1'; $self->{TOTPCheck} = $self->{U2FCheck} = $self->{UBKCheck} = '1';
return 1; return 1;
} }

View File

@ -11,7 +11,6 @@ use Lemonldap::NG::Manager::Conf::Parser;
extends 'Lemonldap::NG::Manager::Api::Common'; extends 'Lemonldap::NG::Manager::Api::Common';
sub getCasAppByConfKey { sub getCasAppByConfKey {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
@ -26,8 +25,7 @@ sub getCasAppByConfKey {
my $casApp = $self->_getCasAppByConfKey( $conf, $confKey ); my $casApp = $self->_getCasAppByConfKey( $conf, $confKey );
# Return 404 if not found # Return 404 if not found
return $self->sendError( $req, return $self->sendError( $req, "CAS application '$confKey' not found", 404 )
"CAS application '$confKey' not found", 404 )
unless ( defined $casApp ); unless ( defined $casApp );
return $self->sendJSONresponse( $req, $casApp ); return $self->sendJSONresponse( $req, $casApp );
@ -77,7 +75,8 @@ sub findCasAppsByServiceUrl {
return $self->sendError( $req, 'Invalid input: serviceUrl is missing', 400 ) return $self->sendError( $req, 'Invalid input: serviceUrl is missing', 400 )
unless ( defined $serviceUrl ); unless ( defined $serviceUrl );
$self->logger->debug("[API] Find CAS Apps by service URL $serviceUrl requested"); $self->logger->debug(
"[API] Find CAS Apps by service URL $serviceUrl requested");
# Get latest configuration # Get latest configuration
my $conf = $self->_confAcc->getConf; my $conf = $self->_confAcc->getConf;
@ -104,6 +103,9 @@ sub addCasApp {
400 ) 400 )
if ( ref $add->{confKey} ); if ( ref $add->{confKey} );
return $self->sendError( $req, 'Invalid input: confKey is empty', 400 )
unless ( $add->{confKey} );
return $self->sendError( $req, 'Invalid input: service is missing', 400 ) return $self->sendError( $req, 'Invalid input: service is missing', 400 )
unless ( defined $add->{options}->{service} ); unless ( defined $add->{options}->{service} );
@ -112,8 +114,7 @@ sub addCasApp {
if ( ref $add->{options}->{service} ); if ( ref $add->{options}->{service} );
$self->logger->debug( $self->logger->debug(
"[API] Add CAS App with confKey $add->{confKey} requested" "[API] Add CAS App with confKey $add->{confKey} requested");
);
# Get latest configuration # Get latest configuration
my $conf = $self->_confAcc->getConf( { noCache => 1 } ); my $conf = $self->_confAcc->getConf( { noCache => 1 } );
@ -167,8 +168,7 @@ sub updateCasApp {
# Return 404 if not found # Return 404 if not found
return $self->sendError( $req, return $self->sendError( $req, "CAS application '$confKey' not found", 404 )
"CAS application '$confKey' not found", 404 )
unless ( defined $current ); unless ( defined $current );
# check if new clientID exists already # check if new clientID exists already
@ -195,13 +195,6 @@ sub replaceCasApp {
return $self->sendError( $req, "Invalid input: " . $req->error, 400 ) return $self->sendError( $req, "Invalid input: " . $req->error, 400 )
unless ($replace); unless ($replace);
return $self->sendError( $req, 'Invalid input: confKey is missing', 400 )
unless ( defined $replace->{confKey} );
return $self->sendError( $req, 'Invalid input: confKey is not a string',
400 )
if ( ref $replace->{confKey} );
$self->logger->debug( $self->logger->debug(
"[API] CAS App $confKey configuration replace requested"); "[API] CAS App $confKey configuration replace requested");
@ -210,8 +203,7 @@ sub replaceCasApp {
# Return 404 if not found # Return 404 if not found
return $self->sendError( $req, return $self->sendError( $req, "CAS application '$confKey' not found", 404 )
"CAS application '$confKey' not found", 404 )
unless ( defined $self->_getCasAppByConfKey( $conf, $confKey ) ); unless ( defined $self->_getCasAppByConfKey( $conf, $confKey ) );
# check if new clientID exists already # check if new clientID exists already
@ -241,8 +233,7 @@ sub deleteCasApp {
# Return 404 if not found # Return 404 if not found
return $self->sendError( $req, return $self->sendError( $req, "CAS application '$confKey' not found", 404 )
"CAS application '$confKey' not found", 404 )
unless ( defined $delete ); unless ( defined $delete );
delete $conf->{casAppMetaDataOptions}->{$confKey}; delete $conf->{casAppMetaDataOptions}->{$confKey};
@ -255,7 +246,6 @@ sub deleteCasApp {
return $self->sendJSONresponse( $req, undef, code => 204 ); return $self->sendJSONresponse( $req, undef, code => 204 );
} }
sub _getCasAppByConfKey { sub _getCasAppByConfKey {
my ( $self, $conf, $confKey ) = @_; my ( $self, $conf, $confKey ) = @_;
@ -277,7 +267,7 @@ sub _getCasAppByConfKey {
my $configOption ( keys %{ $conf->{casAppMetaDataOptions}->{$confKey} } ) my $configOption ( keys %{ $conf->{casAppMetaDataOptions}->{$confKey} } )
{ {
$options->{ $self->_translateOptionConfToApi($configOption) } = $options->{ $self->_translateOptionConfToApi($configOption) } =
$conf->{casAppMetaDataOptions}->{$confKey}->{$configOption}; $conf->{casAppMetaDataOptions}->{$confKey}->{$configOption};
} }
return { return {
@ -307,7 +297,8 @@ sub _getCasAppByServiceUrl {
sub _isNewCasAppServiceUrlUnique { sub _isNewCasAppServiceUrlUnique {
my ( $self, $conf, $confKey, $casApp ) = @_; my ( $self, $conf, $confKey, $casApp ) = @_;
my $curServiceUrl = $self->_getCasAppByConfKey( $conf, $confKey )->{options}->{service}; my $curServiceUrl =
$self->_getCasAppByConfKey( $conf, $confKey )->{options}->{service};
my $newServiceUrl = $casApp->{options}->{service} || ""; my $newServiceUrl = $casApp->{options}->{service} || "";
if ( $newServiceUrl ne '' && $newServiceUrl ne $curServiceUrl ) { if ( $newServiceUrl ne '' && $newServiceUrl ne $curServiceUrl ) {
return { return {
@ -326,9 +317,9 @@ sub _pushCasApp {
my $translatedOptions = {}; my $translatedOptions = {};
if ($replace) { if ($replace) {
$conf->{casAppMetaDataOptions}->{$confKey} = {}; $conf->{casAppMetaDataOptions}->{$confKey} = {};
$conf->{casAppMetaDataExportedVars}->{$confKey} = {}; $conf->{casAppMetaDataExportedVars}->{$confKey} = {};
$conf->{casAppMetaDataMacros}->{$confKey} = {}; $conf->{casAppMetaDataMacros}->{$confKey} = {};
$translatedOptions = $self->_getDefaultValues('casAppMetaDataNodes'); $translatedOptions = $self->_getDefaultValues('casAppMetaDataNodes');
} }

View File

@ -103,6 +103,9 @@ sub addOidcRp {
400 ) 400 )
if ( ref $add->{confKey} ); if ( ref $add->{confKey} );
return $self->sendError( $req, 'Invalid input: confKey is empty', 400 )
unless ( $add->{confKey} );
return $self->sendError( $req, 'Invalid input: clientId is missing', 400 ) return $self->sendError( $req, 'Invalid input: clientId is missing', 400 )
unless ( defined $add->{clientId} ); unless ( defined $add->{clientId} );
@ -201,13 +204,6 @@ sub replaceOidcRp {
return $self->sendError( $req, "Invalid input: " . $req->error, 400 ) return $self->sendError( $req, "Invalid input: " . $req->error, 400 )
unless ($replace); unless ($replace);
return $self->sendError( $req, 'Invalid input: confKey is missing', 400 )
unless ( defined $replace->{confKey} );
return $self->sendError( $req, 'Invalid input: confKey is not a string',
400 )
if ( ref $replace->{confKey} );
return $self->sendError( $req, 'Invalid input: clientId is missing', 400 ) return $self->sendError( $req, 'Invalid input: clientId is missing', 400 )
unless ( defined $replace->{clientId} ); unless ( defined $replace->{clientId} );
@ -297,6 +293,9 @@ sub _getOidcRpByConfKey {
# Get macros # Get macros
my $macros = $conf->{oidcRPMetaDataMacros}->{$confKey} || {}; my $macros = $conf->{oidcRPMetaDataMacros}->{$confKey} || {};
# Redirect URIs, filled later
my $redirectUris;
# Get options # Get options
my $options = {}; my $options = {};
for for
@ -304,12 +303,15 @@ sub _getOidcRpByConfKey {
{ {
# redirectUris is handled as an array # redirectUris is handled as an array
if ( $configOption eq "oidcRPMetaDataOptionsRedirectUris" ) { if ( $configOption eq "oidcRPMetaDataOptionsRedirectUris" ) {
$options->{ $self->_translateOptionConfToApi($configOption) } = [ $redirectUris = [
split( split(
/\s+/, /\s+/,
$conf->{oidcRPMetaDataOptions}->{$confKey}->{$configOption} $conf->{oidcRPMetaDataOptions}->{$confKey}->{$configOption}
) )
]; ];
$options->{ $self->_translateOptionConfToApi($configOption) } =
$redirectUris;
} }
else { else {
$options->{ $self->_translateOptionConfToApi($configOption) } = $options->{ $self->_translateOptionConfToApi($configOption) } =
@ -320,6 +322,7 @@ sub _getOidcRpByConfKey {
return { return {
confKey => $confKey, confKey => $confKey,
clientId => $clientId, clientId => $clientId,
redirectUris => $redirectUris,
exportedVars => $exportedVars, exportedVars => $exportedVars,
extraClaims => $extraClaims, extraClaims => $extraClaims,
macros => $macros, macros => $macros,

View File

@ -96,6 +96,9 @@ sub addSamlSp {
return $self->sendError( $req, 'Invalid input: metadata is missing', 400 ) return $self->sendError( $req, 'Invalid input: metadata is missing', 400 )
unless ( defined $add->{metadata} ); unless ( defined $add->{metadata} );
return $self->sendError( $req, 'Invalid input: confKey is empty', 400 )
unless ( $add->{confKey} );
my $entityId = $self->_readSamlSpEntityId( $add->{metadata} ); my $entityId = $self->_readSamlSpEntityId( $add->{metadata} );
return $self->sendError( $req, return $self->sendError( $req,

View File

@ -22,7 +22,10 @@ sub perlExpr {
grep( { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_; } grep( { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_; }
split( /\n/, $@, 0 ) ) split( /\n/, $@, 0 ) )
); );
return $err ? ( -1, "__badExpression__: $err" ) : 1; return -1, "__badExpression__: $err" if $err;
return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/
? ( -1, '__badExpressionAssignment__' )
: 1;
} }
sub types { sub types {
@ -1253,6 +1256,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'default' => 0, 'default' => 0,
'type' => 'bool' 'type' => 'bool'
}, },
'displaySessionId' => {
'default' => 1,
'type' => 'bool'
},
'domain' => { 'domain' => {
'default' => 'example.com', 'default' => 'example.com',
'msgFail' => '__badDomainName__', 'msgFail' => '__badDomainName__',
@ -1667,6 +1674,10 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
'default' => 0, 'default' => 0,
'type' => 'bool' 'type' => 'bool'
}, },
'ldapIOTimeout' => {
'default' => 10,
'type' => 'int'
},
'ldapITDS' => { 'ldapITDS' => {
'default' => 0, 'default' => 0,
'type' => 'bool' 'type' => 'bool'
@ -1735,7 +1746,7 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
'type' => 'bool' 'type' => 'bool'
}, },
'ldapTimeout' => { 'ldapTimeout' => {
'default' => 120, 'default' => 10,
'type' => 'int' 'type' => 'int'
}, },
'ldapUsePasswordResetAttribute' => { 'ldapUsePasswordResetAttribute' => {

View File

@ -27,7 +27,10 @@ sub perlExpr {
my $err = join( '', my $err = join( '',
grep { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_ } grep { $_ =~ /(?:Undefined subroutine|Devel::StackTrace)/ ? () : $_ }
split( /\n/, $@ ) ); split( /\n/, $@ ) );
return $err ? ( -1, "__badExpression__: $err" ) : (1); return ( -1, "__badExpression__: $err" ) if $err;
return $val =~ qr/(?<=[^=<!>\|\?])=(?![=~])/
? ( -1, "__badExpressionAssignment__" )
: 1;
} }
my $url_re = $RE{URI}{HTTP}{ -scheme => "https?" }; my $url_re = $RE{URI}{HTTP}{ -scheme => "https?" };
@ -879,6 +882,11 @@ sub attributes {
default => '_password _2fDevices', default => '_password _2fDevices',
documentation => 'Name of attributes to hide in logs', documentation => 'Name of attributes to hide in logs',
}, },
displaySessionId => {
type => 'bool',
default => 1,
documentation => 'Display _session_id with sessions explorer',
},
persistentSessionAttributes => { persistentSessionAttributes => {
type => 'text', type => 'text',
default => '_loginHistory _2fDevices notification_', default => '_loginHistory _2fDevices notification_',
@ -1097,9 +1105,10 @@ sub attributes {
documentation => 'Display logout tab in portal', documentation => 'Display logout tab in portal',
}, },
portalDisplayCertificateResetByMail => { portalDisplayCertificateResetByMail => {
type => 'bool', type => 'bool',
default => 0, default => 0,
documentation => 'Display certificate reset by mail button in portal', documentation =>
'Display certificate reset by mail button in portal',
}, },
portalDisplayRegister => { portalDisplayRegister => {
default => 1, default => 1,
@ -1130,7 +1139,7 @@ sub attributes {
portalDisplayRefreshMyRights => { portalDisplayRefreshMyRights => {
default => 1, default => 1,
type => 'bool', type => 'bool',
documentation => 'Displays the link to refresh the user session', documentation => 'Display link to refresh the user session',
}, },
# Cookies # Cookies
@ -2125,14 +2134,14 @@ sub attributes {
documentation => 'List of auto signin rules', documentation => 'List of auto signin rules',
}, },
# Adaptative Authentication Level plugin # Adaptative Authentication Level plugin
adaptativeAuthenticationLevelRules => { adaptativeAuthenticationLevelRules => {
type => 'keyTextContainer', type => 'keyTextContainer',
keyTest => sub { keyTest => sub {
eval { qr/$_[0]/ }; eval { qr/$_[0]/ };
return $@ ? 0 : 1; return $@ ? 0 : 1;
}, },
keyMsgFail => '__badRegexp__', keyMsgFail => '__badRegexp__',
documentation => 'Adaptative authentication level rules', documentation => 'Adaptative authentication level rules',
flags => 'p', flags => 'p',
}, },
@ -3318,9 +3327,14 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
}, },
ldapTimeout => { ldapTimeout => {
type => 'int', type => 'int',
default => 120, default => 10,
documentation => 'LDAP connection timeout', documentation => 'LDAP connection timeout',
}, },
ldapIOTimeout => {
type => 'int',
default => 10,
documentation => 'LDAP operation timeout',
},
ldapVersion => { ldapVersion => {
type => 'int', type => 'int',
default => 3, default => 3,

View File

@ -268,9 +268,9 @@ sub tree {
'ldapServer', 'ldapPort', 'ldapServer', 'ldapPort',
'ldapVerify', 'ldapBase', 'ldapVerify', 'ldapBase',
'managerDn', 'managerPassword', 'managerDn', 'managerPassword',
'ldapTimeout', 'ldapVersion', 'ldapTimeout', 'ldapIOTimeout',
'ldapRaw', 'ldapCAFile', 'ldapVersion', 'ldapRaw',
'ldapCAPath', 'ldapCAFile', 'ldapCAPath',
] ]
}, },
{ {
@ -552,8 +552,10 @@ sub tree {
title => 'logParams', title => 'logParams',
help => 'logs.html', help => 'logs.html',
form => 'simpleInputContainer', form => 'simpleInputContainer',
nodes => nodes => [
[ 'whatToTrace', 'customToTrace', 'hiddenAttributes' ] 'whatToTrace', 'customToTrace',
'hiddenAttributes'
]
}, },
{ {
title => 'cookieParams', title => 'cookieParams',
@ -571,6 +573,7 @@ sub tree {
help => 'sessions.html', help => 'sessions.html',
nodes => [ nodes => [
'storePassword', 'storePassword',
'displaySessionId',
'timeout', 'timeout',
'timeoutActivity', 'timeoutActivity',
'timeoutActivityInterval', 'timeoutActivityInterval',
@ -615,9 +618,9 @@ sub tree {
nodes => [ nodes => [
'stayConnected', 'stayConnected',
'portalStatus', 'portalStatus',
'adaptativeAuthenticationLevelRules',
'upgradeSession', 'upgradeSession',
'refreshSessions', 'refreshSessions',
'adaptativeAuthenticationLevelRules',
{ {
title => 'portalServers', title => 'portalServers',
help => 'portalservers.html', help => 'portalservers.html',

View File

@ -301,6 +301,28 @@ sub tests {
); );
}, },
# Test support of timeouts for LDAPS connections
ldapsNoTimeout => sub {
# Skip test if no SMTP configuration
return (1) unless ( $conf->{ldapServer} );
if ( $conf->{ldapServer} =~ /ldaps:/ ) {
if ( eval "require IO::Socket::SSL; require IO::Socket::IP;" ) {
if ( IO::Socket::SSL->isa('IO::Socket::IP') ) {
unless ( eval { IO::Socket::IP->VERSION(0.31) } ) {
return ( 1,
"Your version of IO::Socket::IP is too old to enforce "
. "connection timeouts on ldaps:// URLs. Use ldap+tls:// instead"
);
}
}
}
}
return (1);
},
# Test SMTP connection and authentication (warning only) # Test SMTP connection and authentication (warning only)
smtpConfiguration => sub { smtpConfiguration => sub {
@ -380,7 +402,7 @@ sub tests {
&& $conf->{samlServicePublicKeySig} ); && $conf->{samlServicePublicKeySig} );
return 1; return 1;
}, },
samlSignatureOverrideNeedsCertificate => sub { samlSignatureOverrideNeedsCertificate => sub {
return 1 if $conf->{samlServicePublicKeySig} =~ /CERTIFICATE/; return 1 if $conf->{samlServicePublicKeySig} =~ /CERTIFICATE/;

View File

@ -5,6 +5,7 @@ use utf8;
use Mouse; use Mouse;
use JSON qw(from_json to_json); use JSON qw(from_json to_json);
use POSIX qw(strftime); use POSIX qw(strftime);
use MIME::Base64 qw(decode_base64);
use Lemonldap::NG::Common::Conf::Constants; use Lemonldap::NG::Common::Conf::Constants;
use Lemonldap::NG::Common::PSGI::Constants; use Lemonldap::NG::Common::PSGI::Constants;
@ -243,40 +244,56 @@ sub notifications {
} }
sub notification { sub notification {
my ( $self, $req, $id, $type, $uid, $ref ) = @_; my ( $self, $req, $id, $type ) = @_;
my $backend = $self->{notificationStorage};
$self->logger->debug("Notification storage: $backend");
if ( $type eq 'actives' ) { if ( $type eq 'actives' ) {
( $uid, $ref ) = ( $id =~ /([^_]+?)_(.+)/ ); my ( $uid, $ref ) = ( $id =~ /([^_]+?)_(.+)/ );
my $n = $self->notifAccess->get( $uid, $ref ); my $n = $self->notifAccess->get( $uid, $ref );
unless ($n) { unless ($n) {
$self->userLogger->notice( $self->userLogger->notice(
"Notification $ref not found for user $uid"); "Active notification $ref not found for user $uid");
return $self->sendJSONresponse( return $self->sendJSONresponse(
$req, $req,
{ {
result => 0, result => 0,
error => "Notification $ref not found for user $uid" error => "Active otification $ref not found for user $uid"
} }
); );
} }
$self->logger->debug("Active notification $ref found for user $uid");
return $self->sendJSONresponse( $req, return $self->sendJSONresponse( $req,
{ result => 1, count => 1, notifications => [ values %$n ] } ); { result => 1, count => 1, notifications => [ values %$n ] } );
} }
else { else {
my ( $date, $uid, $ref ) =
$backend eq 'File'
? ( $id =~ /([^_]+?)_(.+?)_(.+?)\.done/ )
: ( $id =~ /([^_]+?)_(.+?)_(.+)/ );
$ref = decode_base64($ref) if ( $backend eq 'File' );
my $n = $self->notifAccess->getAccepted( $uid, $ref ); my $n = $self->notifAccess->getAccepted( $uid, $ref );
unless ($n) { unless ($n) {
$self->userLogger->notice( $self->userLogger->notice(
"Notification $ref not found for user $uid"); "Done notification $ref not found for user $uid");
return $self->sendJSONresponse( return $self->sendJSONresponse(
$req, $req,
{ {
result => 0, result => 0,
error => "Notification $ref not found for user $uid" error => "Done notification $ref not found for user $uid"
} }
); );
} }
return $self->sendJSONresponse( $req, $self->logger->debug("Done notification $ref found for user $uid");
{ result => 1, count => 1, done => $id, notifications => [ values %$n ] } ); return $self->sendJSONresponse(
$req,
{
result => 1,
count => 1,
done => $id,
notifications => [ values %$n ]
}
);
} }
} }

View File

@ -55,7 +55,9 @@ sub init {
$self->{ipField} ||= 'ipAddr'; $self->{ipField} ||= 'ipAddr';
$self->{multiValuesSeparator} ||= '; '; $self->{multiValuesSeparator} ||= '; ';
$self->{impersonationPrefix} = $conf->{impersonationPrefix} || 'real_'; $self->{impersonationPrefix} = $conf->{impersonationPrefix} || 'real_';
$self->{hiddenAttributes} //= "_password"; $self->{hiddenAttributes} //= '_password';
$self->{hiddenAttributes} .= ' _session_id'
unless $conf->{displaySessionId};
return 1; return 1;
} }
@ -65,7 +67,7 @@ sub init {
sub delOIDCConsent { sub delOIDCConsent {
my ( $self, $req, $session, $skey ) = @_; my ( $self, $req ) = @_;
my $mod = $self->getMod($req) my $mod = $self->getMod($req)
or return $self->sendError( $req, undef, 400 ); or return $self->sendError( $req, undef, 400 );
@ -74,10 +76,15 @@ sub delOIDCConsent {
my $epoch = $params->{epoch}; my $epoch = $params->{epoch};
my $rp = $params->{rp}; my $rp = $params->{rp};
my $id = $req->params('sessionId')
or return $self->sendError( $req, 'sessionId is missing', 400 );
$req->parameters->set('sessionId', $self->_maybeDecryptSessionId($id));
if ( $rp =~ /\b[\w-]+\b/ and defined $epoch ) { if ( $rp =~ /\b[\w-]+\b/ and defined $epoch ) {
$self->logger->debug( $self->logger->debug(
"Call procedure deleteOIDCConsent with RP=$rp and epoch=$epoch"); "Call procedure deleteOIDCConsent with RP=$rp and epoch=$epoch");
return $self->deleteOIDCConsent( $req, $session, $skey ); return $self->deleteOIDCConsent( $req );
} }
else { else {
return $self->sendError( $req, undef, 400 ); return $self->sendError( $req, undef, 400 );
@ -241,8 +248,9 @@ sub sessions {
count => scalar( @{ $r->{$uid} } ), count => scalar( @{ $r->{$uid} } ),
sessions => [ sessions => [
map { { map { {
session => $_->{_sessionId}, session =>
date => $_->{_utime} $self->_maybeEncryptSessionId( $_->{_sessionId} ),
date => $_->{_utime}
} }
} @{ $r->{$uid} } } @{ $r->{$uid} }
] ]
@ -349,7 +357,7 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
elsif ( my $f = $req->params('orderBy') ) { elsif ( my $f = $req->params('orderBy') ) {
my @fields = split /,/, $f; my @fields = split /,/, $f;
my @r = map { my @r = map {
my $tmp = { session => $_ }; my $tmp = { session => $self->_maybeEncryptSessionId($_) };
foreach my $f (@fields) { foreach my $f (@fields) {
my $s = $f; my $s = $f;
$s =~ s/^net(?:4|6|)\(([\w:]+)\)$/$1/; $s =~ s/^net(?:4|6|)\(([\w:]+)\)$/$1/;
@ -390,7 +398,11 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
else { else {
$res = [ $res = [
sort { $a->{date} <=> $b->{date} } sort { $a->{date} <=> $b->{date} }
map { { session => $_, date => $res->{$_}->{_utime} } } map { {
session => $self->_maybeEncryptSessionId($_),
date => $res->{$_}->{_utime}
}
}
keys %$res keys %$res
]; ];
} }
@ -406,6 +418,45 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
); );
} }
sub session {
my ( $self, $req, $session, $skey ) = @_;
$session = $self->_maybeDecryptSessionId($session);
return $self->SUPER::session( $req, $session, $skey );
}
sub _maybeDecryptSessionId {
my ( $self, $session ) = @_;
if ( $self->{hiddenAttributes} =~ /\b_session_id\b/ ) {
$session =
Lemonldap::NG::Handler::Main->tsv->{cipher}->decryptHex($session);
}
return $session;
}
sub _maybeEncryptSessionId {
my ( $self, $session ) = @_;
if ( $self->{hiddenAttributes} =~ /\b_session_id\b/ ) {
$session =
Lemonldap::NG::Handler::Main->tsv->{cipher}->encryptHex($session);
}
return $session;
}
sub delSession {
my ( $self, $req ) = @_;
my $id = $req->params('sessionId')
or return $self->sendError( $req, 'sessionId is missing', 400 );
$req->parameters->set('sessionId', $self->_maybeDecryptSessionId($id));
return $self->SUPER::delSession( $req );
}
sub cmpIPv4 { sub cmpIPv4 {
my @a = split /\./, $_[0]; my @a = split /\./, $_[0];
my @b = split /\./, $_[1]; my @b = split /\./, $_[1];

View File

@ -108,7 +108,6 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
# Delete 2FA device # Delete 2FA device
$scope.delete2FA = (type, epoch) -> $scope.delete2FA = (type, epoch) ->
#item = angular.element(".data-#{epoch}")
items = document.querySelectorAll(".data-#{epoch}") items = document.querySelectorAll(".data-#{epoch}")
for e in items for e in items
e.remove() e.remove()

View File

@ -206,12 +206,10 @@ llapp.controller 'NotificationsExplorerCtrl', [ '$scope', '$translator', '$locat
$scope.currentScope = scope $scope.currentScope = scope
node = scope.$modelValue node = scope.$modelValue
notificationId = node.notification notificationId = node.notification
query = ''
if $scope.type == 'actives' if $scope.type == 'actives'
notificationId = "#{node.uid}_#{node.reference}" node.reference.replace(/#/, '_')
if $scope.type == 'done' notificationId = "#{node.uid}_" + node.reference.replace(/#/, '_')
query = "?uid=#{node.uid}&reference=#{node.reference}" $http.get("#{scriptname}notifications/#{$scope.type}/#{notificationId}").then (response) ->
$http.get("#{scriptname}notifications/#{$scope.type}/#{notificationId}#{query}").then (response) ->
$scope.currentNotification = $scope.currentNotification =
uid: node.uid uid: node.uid
reference: node.reference reference: node.reference

View File

@ -176,8 +176,9 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
# Delete RP Consent # Delete RP Consent
$scope.deleteOIDCConsent = (rp, epoch) -> $scope.deleteOIDCConsent = (rp, epoch) ->
item = angular.element(".data-#{epoch}") items = document.querySelectorAll(".data-#{epoch}")
item.remove() for e in items
e.remove()
$scope.waiting = true $scope.waiting = true
$http['delete']("#{scriptname}sessions/OIDCConsent/#{sessionType}/#{$scope.currentSession.id}?rp=#{rp}&epoch=#{epoch}").then (response) -> $http['delete']("#{scriptname}sessions/OIDCConsent/#{sessionType}/#{$scope.currentSession.id}?rp=#{rp}&epoch=#{epoch}").then (response) ->
$scope.waiting = false $scope.waiting = false
@ -225,7 +226,6 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
title: title title: title
nodes: tmp nodes: tmp
time = session._utime time = session._utime
id = session._session_id
# 1. Replace values if needed # 1. Replace values if needed
for key, value of session for key, value of session
@ -272,7 +272,7 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
delete session[attr] delete session[attr]
else if session[attr].toString().match(/"rp":\s*"[\w-]+"/) else if session[attr].toString().match(/"rp":\s*"[\w-]+"/)
subres.push subres.push
title: "rp" title: "RP"
value: "scope" value: "scope"
epoch: "date" epoch: "date"
td: "0" td: "0"
@ -375,7 +375,6 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
nodes: tmp nodes: tmp
return { return {
_utime: time _utime: time
id: id
nodes: res nodes: res
} }
@ -383,6 +382,7 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
sessionId = scope.$modelValue.session sessionId = scope.$modelValue.session
$http.get("#{scriptname}sessions/#{sessionType}/#{sessionId}").then (response) -> $http.get("#{scriptname}sessions/#{sessionType}/#{sessionId}").then (response) ->
$scope.currentSession = transformSession response.data $scope.currentSession = transformSession response.data
$scope.currentSession.id = sessionId
$scope.showT = false $scope.showT = false
$scope.localeDate = (s) -> $scope.localeDate = (s) ->

View File

@ -243,19 +243,16 @@
} }
}; };
$scope.displayNotification = function(scope) { $scope.displayNotification = function(scope) {
var node, notificationId, query; var node, notificationId;
$scope.waiting = true; $scope.waiting = true;
$scope.currentScope = scope; $scope.currentScope = scope;
node = scope.$modelValue; node = scope.$modelValue;
notificationId = node.notification; notificationId = node.notification;
query = '';
if ($scope.type === 'actives') { if ($scope.type === 'actives') {
notificationId = node.uid + "_" + node.reference; node.reference.replace(/#/, '_');
notificationId = (node.uid + "_") + node.reference.replace(/#/, '_');
} }
if ($scope.type === 'done') { $http.get(scriptname + "notifications/" + $scope.type + "/" + notificationId).then(function(response) {
query = "?uid=" + node.uid + "&reference=" + node.reference;
}
$http.get(scriptname + "notifications/" + $scope.type + "/" + notificationId + query).then(function(response) {
var e, notif; var e, notif;
$scope.currentNotification = { $scope.currentNotification = {
uid: node.uid, uid: node.uid,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -194,9 +194,12 @@
return $scope.showM = false; return $scope.showM = false;
}; };
$scope.deleteOIDCConsent = function(rp, epoch) { $scope.deleteOIDCConsent = function(rp, epoch) {
var item; var e, i, items, len;
item = angular.element(".data-" + epoch); items = document.querySelectorAll(".data-" + epoch);
item.remove(); for (i = 0, len = items.length; i < len; i++) {
e = items[i];
e.remove();
}
$scope.waiting = true; $scope.waiting = true;
$http['delete'](scriptname + "sessions/OIDCConsent/" + sessionType + "/" + $scope.currentSession.id + "?rp=" + rp + "&epoch=" + epoch).then(function(response) { $http['delete'](scriptname + "sessions/OIDCConsent/" + sessionType + "/" + $scope.currentSession.id + "?rp=" + rp + "&epoch=" + epoch).then(function(response) {
return $scope.waiting = false; return $scope.waiting = false;
@ -228,7 +231,7 @@
$scope.displaySession = function(scope) { $scope.displaySession = function(scope) {
var sessionId, transformSession; var sessionId, transformSession;
transformSession = function(session) { transformSession = function(session) {
var _insert, array, attr, attrs, category, cv, element, epoch, i, id, j, k, key, l, len, len1, len2, len3, len4, len5, m, name, o, oidcConsent, p, real, ref, ref1, res, sfDevice, spoof, subres, tab, time, title, tmp, value; var _insert, array, attr, attrs, category, cv, element, epoch, i, j, k, key, l, len, len1, len2, len3, len4, len5, m, name, o, oidcConsent, p, real, ref, ref1, res, sfDevice, spoof, subres, tab, time, title, tmp, value;
_insert = function(re, title) { _insert = function(re, title) {
var key, reg, tmp, value; var key, reg, tmp, value;
tmp = []; tmp = [];
@ -251,7 +254,6 @@
} }
}; };
time = session._utime; time = session._utime;
id = session._session_id;
for (key in session) { for (key in session) {
value = session[key]; value = session[key];
if (!value) { if (!value) {
@ -310,7 +312,7 @@
delete session[attr]; delete session[attr];
} else if (session[attr].toString().match(/"rp":\s*"[\w-]+"/)) { } else if (session[attr].toString().match(/"rp":\s*"[\w-]+"/)) {
subres.push({ subres.push({
title: "rp", title: "RP",
value: "scope", value: "scope",
epoch: "date", epoch: "date",
td: "0" td: "0"
@ -449,14 +451,14 @@
}); });
return { return {
_utime: time, _utime: time,
id: id,
nodes: res nodes: res
}; };
}; };
$scope.currentScope = scope; $scope.currentScope = scope;
sessionId = scope.$modelValue.session; sessionId = scope.$modelValue.session;
$http.get(scriptname + "sessions/" + sessionType + "/" + sessionId).then(function(response) { $http.get(scriptname + "sessions/" + sessionType + "/" + sessionId).then(function(response) {
return $scope.currentSession = transformSession(response.data); $scope.currentSession = transformSession(response.data);
return $scope.currentSession.id = sessionId;
}); });
return $scope.showT = false; return $scope.showT = 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

@ -79,6 +79,7 @@
"badDomainName":"اسم النطاق سيئ", "badDomainName":"اسم النطاق سيئ",
"badEncoding":"تشفير خاطئ", "badEncoding":"تشفير خاطئ",
"badExpression":"تعبير خاطئ", "badExpression":"تعبير خاطئ",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":" حقل الهيدر خاطئ", "badHeaderName":" حقل الهيدر خاطئ",
"badHostname":"اسم الخادم خاطئ", "badHostname":"اسم الخادم خاطئ",
"badLdapUri":"\n URI LDAP خاطئ", "badLdapUri":"\n URI LDAP خاطئ",
@ -279,6 +280,7 @@
"diffViewer":"المشاهد المختلف", "diffViewer":"المشاهد المختلف",
"diffWithPrevious":"الفرق مع السابق", "diffWithPrevious":"الفرق مع السابق",
"disabled":"معطلة", "disabled":"معطلة",
"displaySessionId":"Display session identifier",
"done":"تم", "done":"تم",
"dones":"تم", "dones":"تم",
"down":"Move down", "down":"Move down",
@ -447,7 +449,8 @@
"ldapSearchDeref":"الاسم المستعار", "ldapSearchDeref":"الاسم المستعار",
"ldapServer":"مضيف الخادم", "ldapServer":"مضيف الخادم",
"ldapSetPassword":"تعديل كلمة المرور مع عملية موسعة", "ldapSetPassword":"تعديل كلمة المرور مع عملية موسعة",
"ldapTimeout":"مهلة", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"استخدام سمة إعادة الضبط", "ldapUsePasswordResetAttribute":"استخدام سمة إعادة الضبط",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"الإصدار", "ldapVersion":"الإصدار",
@ -552,7 +555,7 @@
"notificationServerSentAttributes":"Notification parameters to send", "notificationServerSentAttributes":"Notification parameters to send",
"serverNotification":"Server", "serverNotification":"Server",
"notificationCreated":"تم إنشاء إشعار", "notificationCreated":"تم إنشاء إشعار",
"notificationDeleted":"تم حذف الإشعار", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"انتهى الإشعار", "notificationDone":"انتهى الإشعار",
"notificationsDone":"انتهت الإشعارات", "notificationsDone":"انتهت الإشعارات",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

View File

@ -79,6 +79,7 @@
"badDomainName":"Ungültiger Domainname", "badDomainName":"Ungültiger Domainname",
"badEncoding":"Ungültige Codierung", "badEncoding":"Ungültige Codierung",
"badExpression":"Bad expression", "badExpression":"Bad expression",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"Bad header name", "badHeaderName":"Bad header name",
"badHostname":"Ungültiger Hostname", "badHostname":"Ungültiger Hostname",
"badLdapUri":"Bad LDAP URI", "badLdapUri":"Bad LDAP URI",
@ -278,6 +279,7 @@
"diffViewer":"Difference viewer", "diffViewer":"Difference viewer",
"diffWithPrevious":"difference with previous", "diffWithPrevious":"difference with previous",
"disabled":"Disabled", "disabled":"Disabled",
"displaySessionId":"Display session identifier",
"done":"done", "done":"done",
"dones":"Done", "dones":"Done",
"down":"Move down", "down":"Move down",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Alias dereference", "ldapSearchDeref":"Alias dereference",
"ldapServer":"Server host", "ldapServer":"Server host",
"ldapSetPassword":"Password modify extended operation", "ldapSetPassword":"Password modify extended operation",
"ldapTimeout":"Timeout", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Use reset attribute", "ldapUsePasswordResetAttribute":"Use reset attribute",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"Version", "ldapVersion":"Version",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Notification parameters to send", "notificationServerSentAttributes":"Notification parameters to send",
"serverNotification":"Server", "serverNotification":"Server",
"notificationCreated":"Notification has been created", "notificationCreated":"Notification has been created",
"notificationDeleted":"Notification deleted", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"Notification done", "notificationDone":"Notification done",
"notificationsDone":"Notifications done", "notificationsDone":"Notifications done",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

View File

@ -79,6 +79,7 @@
"badDomainName":"Bad domain name", "badDomainName":"Bad domain name",
"badEncoding":"Bad encoding", "badEncoding":"Bad encoding",
"badExpression":"Bad expression", "badExpression":"Bad expression",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"Bad header name", "badHeaderName":"Bad header name",
"badHostname":"Bad hostname", "badHostname":"Bad hostname",
"badLdapUri":"Bad LDAP URI", "badLdapUri":"Bad LDAP URI",
@ -278,6 +279,7 @@
"diffViewer":"Difference viewer", "diffViewer":"Difference viewer",
"diffWithPrevious":"difference with previous", "diffWithPrevious":"difference with previous",
"disabled":"Disabled", "disabled":"Disabled",
"displaySessionId":"Display session identifier",
"done":"done", "done":"done",
"dones":"Done", "dones":"Done",
"down":"Move down", "down":"Move down",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Alias dereference", "ldapSearchDeref":"Alias dereference",
"ldapServer":"Server host", "ldapServer":"Server host",
"ldapSetPassword":"Password modify extended operation", "ldapSetPassword":"Password modify extended operation",
"ldapTimeout":"Timeout", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Use reset attribute", "ldapUsePasswordResetAttribute":"Use reset attribute",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"Version", "ldapVersion":"Version",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Notification parameters to send", "notificationServerSentAttributes":"Notification parameters to send",
"serverNotification":"Server", "serverNotification":"Server",
"notificationCreated":"Notification has been created", "notificationCreated":"Notification has been created",
"notificationDeleted":"Notification deleted", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"Notification done", "notificationDone":"Notification done",
"notificationsDone":"Notifications done", "notificationsDone":"Notifications done",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

View File

@ -79,6 +79,7 @@
"badDomainName":"Mauvais nom de domaine", "badDomainName":"Mauvais nom de domaine",
"badEncoding":"Mauvais encodage", "badEncoding":"Mauvais encodage",
"badExpression":"Mauvaise expression", "badExpression":"Mauvaise expression",
"badExpressionAssignment":"Expression contenant une affectation",
"badHeaderName":"Mauvais nom d'en-tête", "badHeaderName":"Mauvais nom d'en-tête",
"badHostname":"Mauvais nom d'hôte", "badHostname":"Mauvais nom d'hôte",
"badLdapUri":"Mauvaise URI LDAP", "badLdapUri":"Mauvaise URI LDAP",
@ -278,6 +279,7 @@
"diffViewer":"Visualisateur de différence", "diffViewer":"Visualisateur de différence",
"diffWithPrevious":"différence avec la précédente", "diffWithPrevious":"différence avec la précédente",
"disabled":"Désactivé", "disabled":"Désactivé",
"displaySessionId":"Afficher l'identifiant de session",
"done":"validée", "done":"validée",
"dones":"Validées", "dones":"Validées",
"down":"Descendre", "down":"Descendre",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Déréférence des alias", "ldapSearchDeref":"Déréférence des alias",
"ldapServer":"Hôte", "ldapServer":"Hôte",
"ldapSetPassword":"Opération étendue password modify", "ldapSetPassword":"Opération étendue password modify",
"ldapTimeout":"Temps maximum d'inactivité", "ldapTimeout":"Délai maximum de connexion",
"ldapIOTimeout": "Délai maximum d'opération",
"ldapUsePasswordResetAttribute":"Utiliser l'attribut de réinitialisation", "ldapUsePasswordResetAttribute":"Utiliser l'attribut de réinitialisation",
"ldapVerify":"Vérifier le certificat du serveur LDAP", "ldapVerify":"Vérifier le certificat du serveur LDAP",
"ldapVersion":"Version", "ldapVersion":"Version",

View File

@ -79,6 +79,7 @@
"badDomainName":"Nome di dominio errato", "badDomainName":"Nome di dominio errato",
"badEncoding":"Codifica errata", "badEncoding":"Codifica errata",
"badExpression":"Espressione errata", "badExpression":"Espressione errata",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"Nome intestazione errato", "badHeaderName":"Nome intestazione errato",
"badHostname":"Hostname errato", "badHostname":"Hostname errato",
"badLdapUri":"LDAP URI errata", "badLdapUri":"LDAP URI errata",
@ -278,6 +279,7 @@
"diffViewer":"Visualizzatore di differenza", "diffViewer":"Visualizzatore di differenza",
"diffWithPrevious":"differenza con il precedente", "diffWithPrevious":"differenza con il precedente",
"disabled":"Disabilitato", "disabled":"Disabilitato",
"displaySessionId":"Display session identifier",
"done":"fatto", "done":"fatto",
"dones":"Fatto", "dones":"Fatto",
"down":"Move down", "down":"Move down",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Alias dereference", "ldapSearchDeref":"Alias dereference",
"ldapServer":"Host del server", "ldapServer":"Host del server",
"ldapSetPassword":"Operazione prolungata di modifica password", "ldapSetPassword":"Operazione prolungata di modifica password",
"ldapTimeout":"Timeout", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Utilizza l'attributo di ripristino", "ldapUsePasswordResetAttribute":"Utilizza l'attributo di ripristino",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"Versione", "ldapVersion":"Versione",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Notification parameters to send", "notificationServerSentAttributes":"Notification parameters to send",
"serverNotification":"Server", "serverNotification":"Server",
"notificationCreated":"La notifica è stata creata", "notificationCreated":"La notifica è stata creata",
"notificationDeleted":"La notifica è stata cancellata", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"La notifica è stata effettuata", "notificationDone":"La notifica è stata effettuata",
"notificationsDone":"Notifiche effettuate", "notificationsDone":"Notifiche effettuate",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

View File

@ -79,6 +79,7 @@
"badDomainName":"Błędna nazwa domeny", "badDomainName":"Błędna nazwa domeny",
"badEncoding":"Błędne kodowanie", "badEncoding":"Błędne kodowanie",
"badExpression":"Błędne wyrażenie", "badExpression":"Błędne wyrażenie",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"Błędna nazwa nagłówka", "badHeaderName":"Błędna nazwa nagłówka",
"badHostname":"Błędna nazwa hosta", "badHostname":"Błędna nazwa hosta",
"badLdapUri":"Błędny identyfikator URI LDAP", "badLdapUri":"Błędny identyfikator URI LDAP",
@ -278,6 +279,7 @@
"diffViewer":"Przeglądarka różnic", "diffViewer":"Przeglądarka różnic",
"diffWithPrevious":"różnica w stosunku do poprzednich", "diffWithPrevious":"różnica w stosunku do poprzednich",
"disabled":"Wyłączone", "disabled":"Wyłączone",
"displaySessionId":"Display session identifier",
"done":"wykonane", "done":"wykonane",
"dones":"Wykonane", "dones":"Wykonane",
"down":"Move down", "down":"Move down",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Dereferencja aliasu", "ldapSearchDeref":"Dereferencja aliasu",
"ldapServer":"Host serwera", "ldapServer":"Host serwera",
"ldapSetPassword":"Rozszerzona operacja modyfikacji hasła", "ldapSetPassword":"Rozszerzona operacja modyfikacji hasła",
"ldapTimeout":"Limit czasu", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Użyj atrybutu reset", "ldapUsePasswordResetAttribute":"Użyj atrybutu reset",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"Wersja", "ldapVersion":"Wersja",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Parametry powiadomienia do wysłania", "notificationServerSentAttributes":"Parametry powiadomienia do wysłania",
"serverNotification":"Serwer", "serverNotification":"Serwer",
"notificationCreated":"Powiadomienie zostało utworzone", "notificationCreated":"Powiadomienie zostało utworzone",
"notificationDeleted":"Powiadomienie zostało usunięte", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"Powiadomienie wykonane", "notificationDone":"Powiadomienie wykonane",
"notificationsDone":"Powiadomienia wykonane", "notificationsDone":"Powiadomienia wykonane",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

View File

@ -28,7 +28,7 @@
"2ndFA":"İki Faktörlü Kimlik Doğrulama", "2ndFA":"İki Faktörlü Kimlik Doğrulama",
"actives":"Etkin", "actives":"Etkin",
"activeTimer":"Otomatik kabul süresi", "activeTimer":"Otomatik kabul süresi",
"adaptativeAuthenticationLevelRules":"Adaptative authentication rules", "adaptativeAuthenticationLevelRules":"Uyarlanabilir doğrulama kuralları",
"addAppCasPartner":"CAS uygulaması ekle", "addAppCasPartner":"CAS uygulaması ekle",
"addIDPSamlPartner":"SAML IDP ekle", "addIDPSamlPartner":"SAML IDP ekle",
"addOidcOp":"OpenID Connect Sağlayıcısı Ekle", "addOidcOp":"OpenID Connect Sağlayıcısı Ekle",
@ -79,6 +79,7 @@
"badDomainName":"Hatalı etki alanı adı", "badDomainName":"Hatalı etki alanı adı",
"badEncoding":"Hatalı kodlama", "badEncoding":"Hatalı kodlama",
"badExpression":"Hatalı ifade", "badExpression":"Hatalı ifade",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"Hatalı başlık adı", "badHeaderName":"Hatalı başlık adı",
"badHostname":"Hatalı konak adı", "badHostname":"Hatalı konak adı",
"badLdapUri":"Hatalı LDAP URI", "badLdapUri":"Hatalı LDAP URI",
@ -161,7 +162,7 @@
"certificateResetByMailValidityDelay":"Sona ermeden önceki minimum süre", "certificateResetByMailValidityDelay":"Sona ermeden önceki minimum süre",
"contentSecurityPolicy":"İçerik güvenlik ilkesi", "contentSecurityPolicy":"İçerik güvenlik ilkesi",
"contextSwitching":"İçeriği başka bir kullanıcıyla değiştir", "contextSwitching":"İçeriği başka bir kullanıcıyla değiştir",
"contextSwitchingAllowed2fModifications":"Allow 2FA modifications", "contextSwitchingAllowed2fModifications":"2FA modifikasyonlarına izin ver",
"contextSwitchingHiddenAttributes":"Gizli nitelikler", "contextSwitchingHiddenAttributes":"Gizli nitelikler",
"contextSwitchingIdRule":"Kimlik kullanım kuralı", "contextSwitchingIdRule":"Kimlik kullanım kuralı",
"contextSwitchingRule":"Kuralı kullan", "contextSwitchingRule":"Kuralı kullan",
@ -195,8 +196,8 @@
"checkUserIdRule":"Kimlik kullanım kuralı", "checkUserIdRule":"Kimlik kullanım kuralı",
"checkUserHiddenAttributes":"Gizli nitelikler", "checkUserHiddenAttributes":"Gizli nitelikler",
"checkUserUnrestrictedUsersRule":"Kısıtlamasız kullanıcı kuralı", "checkUserUnrestrictedUsersRule":"Kısıtlamasız kullanıcı kuralı",
"checkUserDisplayComputedSession":"Display computed sessions", "checkUserDisplayComputedSession":"Hesaplanan oturumu görüntüle",
"checkUserDisplayPersistentInfo":"Display persistent session data", "checkUserDisplayPersistentInfo":"Kalıcı oturum verisini görüntüle",
"checkUserDisplayEmptyHeaders":"Boş başlıkları görüntüle", "checkUserDisplayEmptyHeaders":"Boş başlıkları görüntüle",
"checkUserDisplayEmptyValues":"Boş değerleri görüntüle", "checkUserDisplayEmptyValues":"Boş değerleri görüntüle",
"checkUserSearchAttributes":"Arama oturumlarında kullanılan nitelikler", "checkUserSearchAttributes":"Arama oturumlarında kullanılan nitelikler",
@ -274,10 +275,11 @@
"demoExportedVars":"Dışa aktarılan değişkenler", "demoExportedVars":"Dışa aktarılan değişkenler",
"demoParams":"Gösterim parametreleri", "demoParams":"Gösterim parametreleri",
"description":"Açıklama", "description":"Açıklama",
"dest":"Recipient", "dest":"Alıcı",
"diffViewer":"Fark görüntüleyici", "diffViewer":"Fark görüntüleyici",
"diffWithPrevious":"önceki ile farkı", "diffWithPrevious":"önceki ile farkı",
"disabled":"Devre dışı", "disabled":"Devre dışı",
"displaySessionId":"Display session identifier",
"done":"tamam", "done":"tamam",
"dones":"Tamam", "dones":"Tamam",
"down":"Aşağı taşı", "down":"Aşağı taşı",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Takma ad yönlendirmeleri", "ldapSearchDeref":"Takma ad yönlendirmeleri",
"ldapServer":"Konak sunucu", "ldapServer":"Konak sunucu",
"ldapSetPassword":"Parola değiştirme işlemi genişletilmiş", "ldapSetPassword":"Parola değiştirme işlemi genişletilmiş",
"ldapTimeout":"Zaman aşımı", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Sıfırlama niteliklerini kullan", "ldapUsePasswordResetAttribute":"Sıfırlama niteliklerini kullan",
"ldapVerify":"LDAP sunucu sertifikasını doğrulayın", "ldapVerify":"LDAP sunucu sertifikasını doğrulayın",
"ldapVersion":"Sürüm", "ldapVersion":"Sürüm",
@ -518,7 +521,7 @@
"newApp":"Yeni uygulama", "newApp":"Yeni uygulama",
"newChain":"Yeni zincir", "newChain":"Yeni zincir",
"newCat":"Yeni kategori", "newCat":"Yeni kategori",
"newCertificate":"New certificate", "newCertificate":"Yeni sertifika",
"newCfgAvailable":"Yeni bir yapılandırma mevcut", "newCfgAvailable":"Yeni bir yapılandırma mevcut",
"newCmbMod":"Yeni modül", "newCmbMod":"Yeni modül",
"newCmbOver":"Yeni parametre", "newCmbOver":"Yeni parametre",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Gönderilecek bildirim parametreleri", "notificationServerSentAttributes":"Gönderilecek bildirim parametreleri",
"serverNotification":"Sunucu", "serverNotification":"Sunucu",
"notificationCreated":"Bildirim oluşturuldu", "notificationCreated":"Bildirim oluşturuldu",
"notificationDeleted":"Bildirim silindi", "notificationDeleted":"Bildirim tamamlandı olarak işaretlendi",
"notificationDone":"Bildirim tamamlandı", "notificationDone":"Bildirim tamamlandı",
"notificationsDone":"Bildirimler tamamlandı", "notificationsDone":"Bildirimler tamamlandı",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",
@ -847,8 +850,8 @@
"secondFactors":"İki faktörlü kimlik doğrulama", "secondFactors":"İki faktörlü kimlik doğrulama",
"securedCookie":"Güvenli Çerez (SSL)", "securedCookie":"Güvenli Çerez (SSL)",
"security":"Güvenlik", "security":"Güvenlik",
"sendTestMail":"Send test email", "sendTestMail":"Test e-postası gönder",
"sendTestMailSuccess":"Test email successfully sent", "sendTestMailSuccess":"Test e-postası başarıyla gönderildi",
"serverError":"Sunucu hatası", "serverError":"Sunucu hatası",
"session":"oturum", "session":"oturum",
"sessions":"Oturumlar", "sessions":"Oturumlar",

View File

@ -79,6 +79,7 @@
"badDomainName":"Tên miền không hợp lệ", "badDomainName":"Tên miền không hợp lệ",
"badEncoding":"Mã hoá không hợp lệ", "badEncoding":"Mã hoá không hợp lệ",
"badExpression":"Biểu thức không hợp lệ", "badExpression":"Biểu thức không hợp lệ",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"Tên tiêu đề không hợp lệ", "badHeaderName":"Tên tiêu đề không hợp lệ",
"badHostname":"Tên máy chủ không hợp lệ", "badHostname":"Tên máy chủ không hợp lệ",
"badLdapUri":"URI LDAP không đúng", "badLdapUri":"URI LDAP không đúng",
@ -278,6 +279,7 @@
"diffViewer":"Người xem khác ", "diffViewer":"Người xem khác ",
"diffWithPrevious":"khác biệt với cái trước", "diffWithPrevious":"khác biệt với cái trước",
"disabled":"Tắt", "disabled":"Tắt",
"displaySessionId":"Display session identifier",
"done":"Hoàn thành", "done":"Hoàn thành",
"dones":"Hoàn thành", "dones":"Hoàn thành",
"down":"Move down", "down":"Move down",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Bí danh ngoại tham chiếu ", "ldapSearchDeref":"Bí danh ngoại tham chiếu ",
"ldapServer":"Máy chủ lưu trữ", "ldapServer":"Máy chủ lưu trữ",
"ldapSetPassword":"Mật khẩu sửa đổi hoạt động mở rộng", "ldapSetPassword":"Mật khẩu sửa đổi hoạt động mở rộng",
"ldapTimeout":"Thời gian chờ", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Sử dụng thuộc tính đặt lại", "ldapUsePasswordResetAttribute":"Sử dụng thuộc tính đặt lại",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"Phiên bản", "ldapVersion":"Phiên bản",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Notification parameters to send", "notificationServerSentAttributes":"Notification parameters to send",
"serverNotification":"Server", "serverNotification":"Server",
"notificationCreated":"Thông báo đã được tạo ra", "notificationCreated":"Thông báo đã được tạo ra",
"notificationDeleted":"Thông báo đã xoá", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"Thông báo được thực hiện", "notificationDone":"Thông báo được thực hiện",
"notificationsDone":"Thông báo đã hoàn tất", "notificationsDone":"Thông báo đã hoàn tất",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

View File

@ -79,6 +79,7 @@
"badDomainName":"无效的域名", "badDomainName":"无效的域名",
"badEncoding":"无效的编码", "badEncoding":"无效的编码",
"badExpression":"无效的表达式", "badExpression":"无效的表达式",
"badExpressionAssignment":"Expression containing an assignment",
"badHeaderName":"无效的头部名称", "badHeaderName":"无效的头部名称",
"badHostname":"无效的主机名", "badHostname":"无效的主机名",
"badLdapUri":"无效的 LDAP URI ", "badLdapUri":"无效的 LDAP URI ",
@ -278,6 +279,7 @@
"diffViewer":"Difference viewer", "diffViewer":"Difference viewer",
"diffWithPrevious":"difference with previous", "diffWithPrevious":"difference with previous",
"disabled":"Disabled", "disabled":"Disabled",
"displaySessionId":"Display session identifier",
"done":"完成", "done":"完成",
"dones":"完成", "dones":"完成",
"down":"Move down", "down":"Move down",
@ -446,7 +448,8 @@
"ldapSearchDeref":"Alias dereference", "ldapSearchDeref":"Alias dereference",
"ldapServer":"Server host", "ldapServer":"Server host",
"ldapSetPassword":"Password modify extended operation", "ldapSetPassword":"Password modify extended operation",
"ldapTimeout":"Timeout", "ldapTimeout":"Connection timeout",
"ldapIOTimeout": "Operation timeout",
"ldapUsePasswordResetAttribute":"Use reset attribute", "ldapUsePasswordResetAttribute":"Use reset attribute",
"ldapVerify":"Verify LDAP server certificate", "ldapVerify":"Verify LDAP server certificate",
"ldapVersion":"版本", "ldapVersion":"版本",
@ -551,7 +554,7 @@
"notificationServerSentAttributes":"Notification parameters to send", "notificationServerSentAttributes":"Notification parameters to send",
"serverNotification":"Server", "serverNotification":"Server",
"notificationCreated":"Notification has been created", "notificationCreated":"Notification has been created",
"notificationDeleted":"Notification deleted", "notificationDeleted":"Notification has been marked as done",
"notificationDone":"Notification done", "notificationDone":"Notification done",
"notificationsDone":"Notifications done", "notificationsDone":"Notifications done",
"notificationsExplorer":"Explorer", "notificationsExplorer":"Explorer",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -43,16 +43,9 @@ foreach my $i ( 0 .. 2 ) {
} }
count(4); count(4);
ok( ok(
@{ $resBody->{details}->{__needConfirmation__} } == 1, @{ $resBody->{details}->{__needConfirmation__} } == 2,
'JSON response contains 1 needConfirmation' 'JSON response contains 2 needConfirmation'
) or print STDERR Dumper($resBody); ) or print STDERR Dumper($resBody);
ok(
$resBody->{details}->{__needConfirmation__}->[0]->{message} =~
/\bplugin is enabled without CSRF Token neither Captcha required\b/,
"Warning with confirmation needed found"
) or print STDERR Dumper($resBody);
ok( ok(
@{ $resBody->{details}->{__changes__} } == 23, @{ $resBody->{details}->{__changes__} } == 23,
'JSON response contains 23 changes' 'JSON response contains 23 changes'
@ -65,9 +58,9 @@ ok(
), ),
"Request succeed" "Request succeed"
); );
ok( -f $confFiles->[1], 'File is created' ); ok( -f $confFiles->[1], 'File is created' );
count(5); count(4);
my @changes = @{&changes}; my @changes = @{&changes};
my @cmsg = @{ $resBody->{details}->{__changes__} }; my @cmsg = @{ $resBody->{details}->{__changes__} };
my $bug; my $bug;

View File

@ -66,6 +66,12 @@ SKIP: {
$notif = $notif =
'{"date":"2099-12-31","uid":"dwho","reference":"Test","xml":"{\"title\":\"Test\"}"}'; '{"date":"2099-12-31","uid":"dwho","reference":"Test","xml":"{\"title\":\"Test\"}"}';
$res =
$client->jsonPostResponse( 'notifications/actives', '',
IO::String->new($notif),
'application/json', length($notif) );
$notif =
'{"date":"2099-12-31","uid":"dwho","reference":"Test2","xml":"{\"title\":\"Test\"}"}';
$res = $res =
$client->jsonPostResponse( 'notifications/actives', '', $client->jsonPostResponse( 'notifications/actives', '',
IO::String->new($notif), IO::String->new($notif),
@ -89,20 +95,17 @@ SKIP: {
$res = $res =
$client->jsonResponse( 'notifications/actives', 'groupBy=substr(uid,1)' ); $client->jsonResponse( 'notifications/actives', 'groupBy=substr(uid,1)' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 0, 'Count = 0' ); ok( $res->{count} == 1, 'Count = 1' );
# Test "done" notifications display # Test "done" notifications display
displayTests('done'); displayTests('done');
# Delete notification # Delete notification
$res = $res = $client->_del('notifications/done/dwho_Test_20991231');
$client->_del('notifications/done/dwho_Test_20991231_dwho_VGVzdA==.done');
$res = $res =
$client->jsonResponse( 'notifications/done', 'groupBy=substr(uid,1)' ); $client->jsonResponse( 'notifications/done', 'groupBy=substr(uid,1)' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 0, 'Count = 0' ) or diag Dumper($res); ok( $res->{count} == 0, 'Count = 0' ) or diag Dumper($res);
#print STDERR Dumper($res);
} }
eval { unlink $file }; eval { unlink $file };
@ -110,35 +113,37 @@ count($maintests);
done_testing( count() ); done_testing( count() );
sub displayTests { sub displayTests {
my $type = shift; my $type = shift;
my $count = $type eq 'actives' ? 2 : 1;
$res = $res =
$client->jsonResponse( "notifications/$type", 'groupBy=substr(uid,1)' ); $client->jsonResponse( "notifications/$type", 'groupBy=substr(uid,1)' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 1, 'Count = 1' ); ok( $res->{count} == $count, "Count = $count" );
ok( $res->{values}->[0]->{value} eq 'd', 'Value is "d"' ); ok( $res->{values}->[0]->{value} eq 'd', 'Value is "d"' );
count(3); count(3);
$res = $client->jsonResponse( "notifications/$type", 'groupBy=uid' ); $res = $client->jsonResponse( "notifications/$type", 'groupBy=uid' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 1, 'Count = 1' ); ok( $res->{count} == $count, "Count = $count" );
ok( $res->{values}->[0]->{value} eq 'dwho', 'Value is "dwho"' ); ok( $res->{values}->[0]->{value} eq 'dwho', 'Value is "dwho"' );
count(3); count(3);
$res = $client->jsonResponse( "notifications/$type", 'uid=d*&groupBy=uid' ); $res = $client->jsonResponse( "notifications/$type", 'uid=d*&groupBy=uid' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 1, 'Count = 1' ); ok( $res->{count} == $count, "Count = $count" );
ok( $res->{values}->[0]->{value} eq 'dwho', 'Value is "dwho"' ); ok( $res->{values}->[0]->{value} eq 'dwho', 'Value is "dwho"' );
count(3); count(3);
$res = $client->jsonResponse( "notifications/$type", 'uid=d*' ); $res = $client->jsonResponse( "notifications/$type", 'uid=d*' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 1, 'Count = 1' ); ok( $res->{count} == $count, "Count = $count" );
ok( $res->{values}->[0]->{uid} eq 'dwho', 'Value is "dwho"' ); ok( $res->{values}->[0]->{uid} eq 'dwho', 'Value is "dwho"' );
count(3); count(3);
$res = $client->jsonResponse( "notifications/$type", 'uid=dwho' ); $res = $client->jsonResponse( "notifications/$type", 'uid=dwho' );
ok( $res->{result} == 1, 'Result = 1' ); ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 1, 'Count = 1' ); ok( $res->{count} == $count, "Count = $count" );
ok( $res->{values}->[0]->{uid} eq 'dwho', 'Value is "dwho"' ); ok( $res->{values}->[0]->{uid} eq 'dwho', 'Value is "dwho"' );
count(3); count(3);
@ -161,8 +166,8 @@ sub displayTests {
) or diag Dumper($res); ) or diag Dumper($res);
my $internal_ref = $res->{values}->[0]->{notification}; my $internal_ref = $res->{values}->[0]->{notification};
my $ref = $res->{values}->[0]->{reference}; my $ref = $res->{values}->[0]->{reference};
$res = $client->jsonResponse( "notifications/$type/$internal_ref", $internal_ref =~ s/#/_/g; # Fix 2353
"uid=dwho&reference=$ref" ) $res = $client->jsonResponse("notifications/$type/$internal_ref")
or diag Dumper($res); or diag Dumper($res);
ok( $res = eval { from_json( $res->{notifications}->[0] ) }, ok( $res = eval { from_json( $res->{notifications}->[0] ) },
'Response is JSON' ) 'Response is JSON' )
@ -175,12 +180,6 @@ sub displayTests {
or diag Dumper($res); or diag Dumper($res);
ok( $res->{uid} eq 'dwho', 'uid found' ) ok( $res->{uid} eq 'dwho', 'uid found' )
or diag Dumper($res); or diag Dumper($res);
$res = $client->jsonResponse( "notifications/$type/$internal_ref", count(6);
"uid=davros&reference=$ref" )
or diag Dumper($res);
ok( $res->{error} eq 'Notification Test not found for user davros',
'error found' )
or diag Dumper($res);
count(7);
} }
} }

View File

@ -137,8 +137,7 @@ sub displayTests {
) or diag Dumper($res); ) or diag Dumper($res);
my $internal_ref = $res->{values}->[0]->{notification}; my $internal_ref = $res->{values}->[0]->{notification};
my $ref = $res->{values}->[0]->{reference}; my $ref = $res->{values}->[0]->{reference};
$res = &client->jsonResponse( "notifications/$type/$internal_ref", $res = &client->jsonResponse( "notifications/$type/$internal_ref" );
"uid=dwho&reference=$ref" );
ok( $res->{done} eq $internal_ref, 'Internal reference found' ) ok( $res->{done} eq $internal_ref, 'Internal reference found' )
or diag Dumper($res); or diag Dumper($res);
ok( $res = eval { from_json( $res->{notifications}->[0] ) }, ok( $res = eval { from_json( $res->{notifications}->[0] ) },

View File

@ -1859,7 +1859,7 @@
"data": "logout_sso", "data": "logout_sso",
"re": "^/logout" "re": "^/logout"
}, { }, {
"data": "accept", "data": "$uid = 1",
"re": "default", "re": "default",
"title": "default", "title": "default",
"comment": "", "comment": "",

View File

@ -11,12 +11,13 @@ package Lemonldap::NG::Portal::2F::Engines::Default;
use strict; use strict;
use Mouse; use Mouse;
use MIME::Base64 qw(encode_base64);
use JSON qw(from_json to_json); use JSON qw(from_json to_json);
use POSIX qw(strftime); use POSIX qw(strftime);
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_ERROR PE_ERROR
PE_NOTOKEN PE_NOTOKEN
PE_OK
PE_SENDRESPONSE PE_SENDRESPONSE
PE_TOKENEXPIRED PE_TOKENEXPIRED
PE_NO_SECOND_FACTORS PE_NO_SECOND_FACTORS
@ -192,8 +193,9 @@ sub init {
# run() is called at each authentication, just after sessionInfo populated # run() is called at each authentication, just after sessionInfo populated
sub run { sub run {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
my $spoofId = $req->param('spoofId') || ''; my $stayconnected = $req->param('stayconnected');
my $spoofId = $req->param('spoofId') || '';
$self->logger->debug("2F checkLogins set") if ($checkLogins); $self->logger->debug("2F checkLogins set") if ($checkLogins);
# Skip 2F unless a module has been registered # Skip 2F unless a module has been registered
@ -358,11 +360,15 @@ sub run {
$req, $req,
'2fchoice', '2fchoice',
params => { params => {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req), SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages}, LANGS => $self->conf->{showLanguages},
TOKEN => $token, CHECKLOGINS => $checkLogins,
MODULES => [ STAYCONNECTED => $stayconnected,
TOKEN => $token,
MSG => $self->canUpdateSfa($req) || 'choose2f',
ALERT => ( $self->canUpdateSfa($req) ? 'warning' : 'positive' ),
MODULES => [
map { { map { {
CODE => $_->prefix, CODE => $_->prefix,
LOGO => $_->logo, LOGO => $_->logo,
@ -370,7 +376,6 @@ sub run {
} }
} @am } @am
], ],
CHECKLOGINS => $checkLogins
} }
); );
$req->response($tpl); $req->response($tpl);
@ -457,6 +462,8 @@ sub _displayRegister {
params => { params => {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
LANGS => $self->conf->{showLanguages}, LANGS => $self->conf->{showLanguages},
MSG => $self->canUpdateSfa($req) || $m->{m}->welcome,
ALERT => ( $self->canUpdateSfa($req) ? 'warning' : 'positive' ),
} }
); );
} }
@ -485,7 +492,7 @@ sub _displayRegister {
# Retrieve user all second factors # Retrieve user all second factors
my $_2fDevices = []; my $_2fDevices = [];
if ( $self->allowedUpdateSfa($req) ) { unless ( $self->canUpdateSfa($req) ) {
$_2fDevices = $req->userData->{_2fDevices} $_2fDevices = $req->userData->{_2fDevices}
? eval { ? eval {
from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } ); from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } );
@ -500,8 +507,9 @@ sub _displayRegister {
$self->userLogger->warn("Do not diplay 2F Devices!"); $self->userLogger->warn("Do not diplay 2F Devices!");
} }
# Parse second factors to display delete button if allowed # Parse second factors to display delete button if allowed and upgrade button
my $action = ''; my $displayUpgBtn = 0;
my $action = '';
foreach foreach
my $type ( split /,\s*/, $self->conf->{available2FSelfRegistration} ) my $type ( split /,\s*/, $self->conf->{available2FSelfRegistration} )
{ {
@ -511,15 +519,22 @@ sub _displayRegister {
my $t = lc($type); my $t = lc($type);
$t =~ s/2f$//i; $t =~ s/2f$//i;
# Display delete button
$_->{delAllowed} = $_->{delAllowed} =
$self->conf->{ $t . '2fActivation' } $self->conf->{ $t . '2fActivation' }
&& $self->conf->{ $t . '2fUserCanRemoveKey' } && $self->conf->{ $t . '2fUserCanRemoveKey' }
&& $self->conf->{ $t . '2fSelfRegistration' }; && $self->conf->{ $t . '2fSelfRegistration' };
# Display upgrade button
$displayUpgBtn ||= $self->conf->{ $t . '2fAuthnLevel' }
&& $self->conf->{ $t . '2fAuthnLevel' } >
$req->userData->{authenticationLevel};
} }
$action ||= $_->{delAllowed}; $action ||= $_->{delAllowed};
$_->{type} =~ s/^Yubikey$/UBK/; $_->{type} =~ s/^Yubikey$/UBK/;
} }
} }
$displayUpgBtn = 0 unless $self->conf->{upgradeSession};
# Display template # Display template
return $self->p->sendHtml( return $self->p->sendHtml(
@ -533,6 +548,11 @@ sub _displayRegister {
SFDEVICES => $_2fDevices, SFDEVICES => $_2fDevices,
ACTION => $action, ACTION => $action,
REG_REQUIRED => $req->data->{sfRegRequired}, REG_REQUIRED => $req->data->{sfRegRequired},
DISPLAY_UPG => $displayUpgBtn,
MSG => $self->canUpdateSfa($req) || 'choose2f',
ALERT => ( $self->canUpdateSfa($req) ? 'warning' : 'positive' ),
SFREGISTERS_URL =>
encode_base64( "$self->{conf}->{portal}2fregisters", '' )
} }
); );
} }

View File

@ -3,10 +3,10 @@ package Lemonldap::NG::Portal::2F::Ext2F;
use strict; use strict;
use Mouse; use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADOTP
PE_ERROR
PE_FORMEMPTY
PE_OK PE_OK
PE_ERROR
PE_BADOTP
PE_FORMEMPTY
PE_SENDRESPONSE PE_SENDRESPONSE
); );
@ -51,7 +51,10 @@ sub run {
my ( $self, $req, $token ) = @_; my ( $self, $req, $token ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("Ext2F checkLogins set") if ($checkLogins); $self->logger->debug("Ext2F: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("Ext2F: stayconnected set") if $stayconnected;
# Generate Code to send # Generate Code to send
my $code; my $code;
@ -87,7 +90,8 @@ sub run {
. $self->prefix . $self->prefix
. '2fcheck?skin=' . '2fcheck?skin='
. $self->p->getSkin($req), . $self->p->getSkin($req),
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );
$self->logger->debug("Prepare external 2F verification"); $self->logger->debug("Prepare external 2F verification");

View File

@ -3,18 +3,20 @@ package Lemonldap::NG::Portal::2F::Mail2F;
use strict; use strict;
use Mouse; use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADOTP
PE_ERROR
PE_FORMEMPTY
PE_OK PE_OK
PE_ERROR
PE_BADOTP
PE_FORMEMPTY
PE_SENDRESPONSE PE_SENDRESPONSE
PE_MUSTHAVEMAIL PE_MUSTHAVEMAIL
); );
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::SecondFactor', extends qw(
'Lemonldap::NG::Portal::Lib::SMTP'; Lemonldap::NG::Portal::Main::SecondFactor
Lemonldap::NG::Portal::Lib::SMTP
);
# INITIALIZATION # INITIALIZATION
@ -54,6 +56,10 @@ sub run {
my ( $self, $req, $token ) = @_; my ( $self, $req, $token ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("Mail2F: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("Mail2F: stayconnected set") if $stayconnected;
my $code = $self->random->randregex( $self->conf->{mail2fCodeRegex} ); my $code = $self->random->randregex( $self->conf->{mail2fCodeRegex} );
$self->logger->debug("Generated two-factor code: $code"); $self->logger->debug("Generated two-factor code: $code");
@ -117,8 +123,9 @@ sub run {
. $self->prefix . $self->prefix
. '2fcheck?skin=' . '2fcheck?skin='
. $self->p->getSkin($req), . $self->p->getSkin($req),
LEGEND => 'enterMail2fCode', LEGEND => 'enterMail2fCode',
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );
$req->response($tmp); $req->response($tmp);

View File

@ -12,15 +12,15 @@ use Lemonldap::NG::Portal::Main::Constants qw(
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::SecondFactor', extends qw(
'Lemonldap::NG::Portal::Lib::REST'; Lemonldap::NG::Portal::Main::SecondFactor
Lemonldap::NG::Portal::Lib::REST
);
# INITIALIZATION # INITIALIZATION
has prefix => ( is => 'rw', default => 'rest' ); has prefix => ( is => 'rw', default => 'rest' );
has initAttrs => ( is => 'rw', default => sub { {} } ); has initAttrs => ( is => 'rw', default => sub { {} } );
has vrfyAttrs => ( is => 'rw', default => sub { {} } ); has vrfyAttrs => ( is => 'rw', default => sub { {} } );
sub init { sub init {
@ -58,7 +58,10 @@ sub run {
my ( $self, $req, $token ) = @_; my ( $self, $req, $token ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("REST2F checkLogins set") if ($checkLogins); $self->logger->debug("REST2F: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("REST2F: stayconnected set") if $stayconnected;
if ( $self->conf->{rest2fInitUrl} ) { if ( $self->conf->{rest2fInitUrl} ) {
@ -98,8 +101,9 @@ sub run {
. $self->prefix . $self->prefix
. '2fcheck?skin=' . '2fcheck?skin='
. $self->p->getSkin($req), . $self->p->getSkin($req),
LEGEND => 'enterRest2fCode', LEGEND => 'enterRest2fCode',
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );
$self->logger->debug("Prepare external REST verification"); $self->logger->debug("Prepare external REST verification");

View File

@ -17,7 +17,6 @@ extends 'Lemonldap::NG::Portal::Main::SecondFactor';
# INITIALIZATION # INITIALIZATION
has prefix => ( is => 'rw', default => 'radius' ); has prefix => ( is => 'rw', default => 'radius' );
has radius => ( is => 'rw' ); has radius => ( is => 'rw' );
sub init { sub init {
@ -56,7 +55,10 @@ sub run {
my ( $self, $req, $token ) = @_; my ( $self, $req, $token ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("Radius2F checkLogins set") if ($checkLogins); $self->logger->debug("Radius2F: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("Radius2F: stayconnected set") if $stayconnected;
# Prepare form # Prepare form
my $tmp = $self->p->sendHtml( my $tmp = $self->p->sendHtml(
@ -71,8 +73,9 @@ sub run {
. $self->prefix . $self->prefix
. '2fcheck?skin=' . '2fcheck?skin='
. $self->p->getSkin($req), . $self->p->getSkin($req),
LEGEND => 'enterRadius2fCode', LEGEND => 'enterRadius2fCode',
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );
$self->logger->debug("Prepare Radius 2F verification"); $self->logger->debug("Prepare Radius 2F verification");

View File

@ -7,12 +7,16 @@ use JSON qw(from_json to_json);
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Plugin', 'Lemonldap::NG::Common::TOTP'; extends qw(
Lemonldap::NG::Portal::Main::Plugin
Lemonldap::NG::Common::TOTP
);
# INITIALIZATION # INITIALIZATION
has prefix => ( is => 'rw', default => 'totp' ); has prefix => ( is => 'rw', default => 'totp' );
has template => ( is => 'ro', default => 'totp2fregister' ); has template => ( is => 'ro', default => 'totp2fregister' );
has welcome => ( is => 'ro', default => 'yourNewTotpKey' );
has logo => ( is => 'rw', default => 'totp.png' ); has logo => ( is => 'rw', default => 'totp.png' );
has ott => ( has ott => (
is => 'rw', is => 'rw',
@ -37,8 +41,8 @@ sub run {
unless $user; unless $user;
# Check if TOTP can be updated # Check if TOTP can be updated
return $self->p->sendError( $req, 'notAuthorized', 400 ) my $msg = $self->canUpdateSfa( $req, $action );
unless $self->allowedUpdateSfa( $req, $action ); return $self->p->sendError( $req, $msg, 400 ) if $msg;
# Verification that user has a valid TOTP app # Verification that user has a valid TOTP app
if ( $action eq 'verify' ) { if ( $action eq 'verify' ) {

View File

@ -7,13 +7,16 @@ use JSON qw(from_json to_json);
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Plugin', extends qw(
'Lemonldap::NG::Portal::Lib::U2F'; Lemonldap::NG::Portal::Main::Plugin
Lemonldap::NG::Portal::Lib::U2F
);
# INITIALIZATION # INITIALIZATION
has prefix => ( is => 'rw', default => 'u' ); has prefix => ( is => 'rw', default => 'u' );
has template => ( is => 'ro', default => 'u2fregister' ); has template => ( is => 'ro', default => 'u2fregister' );
has welcome => ( is => 'ro', default => 'u2fWelcome' );
has logo => ( is => 'rw', default => 'u2f.png' ); has logo => ( is => 'rw', default => 'u2f.png' );
sub init { sub init {
@ -34,8 +37,8 @@ sub run {
unless $user; unless $user;
# Check if U2F key can be updated # Check if U2F key can be updated
return $self->p->sendError( $req, 'notAuthorized', 400 ) my $msg = $self->canUpdateSfa( $req, $action );
unless $self->allowedUpdateSfa( $req, $action ); return $self->p->sendError( $req, $msg, 400 ) if $msg;
if ( $action eq 'register' ) { if ( $action eq 'register' ) {

View File

@ -17,6 +17,7 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
has prefix => ( is => 'rw', default => 'yubikey' ); has prefix => ( is => 'rw', default => 'yubikey' );
has template => ( is => 'ro', default => 'yubikey2fregister' ); has template => ( is => 'ro', default => 'yubikey2fregister' );
has welcome => ( is => 'ro', default => 'clickOnYubikey' );
has logo => ( is => 'rw', default => 'yubikey.png' ); has logo => ( is => 'rw', default => 'yubikey.png' );
sub init { sub init {
@ -35,14 +36,15 @@ sub run {
unless $user; unless $user;
# Check if UBK key can be updated # Check if UBK key can be updated
my $msg = $self->canUpdateSfa( $req, $action );
return $self->p->sendHtml( return $self->p->sendHtml(
$req, 'error', $req, 'error',
params => { params => {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
RAW_ERROR => 'notAuthorized', RAW_ERROR => 'notAuthorizedAuthLevel',
AUTH_ERROR_TYPE => 'warning', AUTH_ERROR_TYPE => 'warning',
} }
) unless $self->allowedUpdateSfa( $req, $action ); ) if $msg;
if ( $action eq 'register' ) { if ( $action eq 'register' ) {
my $otp = $req->param('otp'); my $otp = $req->param('otp');

View File

@ -8,22 +8,24 @@ use strict;
use Mouse; use Mouse;
use JSON qw(from_json to_json); use JSON qw(from_json to_json);
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADOTP
PE_ERROR
PE_FORMEMPTY
PE_OK PE_OK
PE_ERROR
PE_BADOTP
PE_FORMEMPTY
PE_SENDRESPONSE PE_SENDRESPONSE
); );
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::SecondFactor', extends qw(
'Lemonldap::NG::Common::TOTP'; Lemonldap::NG::Portal::Main::SecondFactor
Lemonldap::NG::Common::TOTP
);
# INITIALIZATION # INITIALIZATION
has prefix => ( is => 'ro', default => 'totp' ); has prefix => ( is => 'ro', default => 'totp' );
has logo => ( is => 'rw', default => 'totp.png' ); has logo => ( is => 'rw', default => 'totp.png' );
sub init { sub init {
my ($self) = @_; my ($self) = @_;
@ -46,17 +48,21 @@ sub run {
$self->logger->debug('Generate TOTP form'); $self->logger->debug('Generate TOTP form');
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("TOTP checkLogins set") if ($checkLogins); $self->logger->debug("TOTP: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("TOTP: stayconnected set") if $stayconnected;
# Prepare form # Prepare form
my $tmp = $self->p->sendHtml( my $tmp = $self->p->sendHtml(
$req, $req,
'totp2fcheck', 'totp2fcheck',
params => { params => {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req), SKIN => $self->p->getSkin($req),
TOKEN => $token, TOKEN => $token,
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );
$self->logger->debug("Prepare TOTP 2F verification"); $self->logger->debug("Prepare TOTP 2F verification");

View File

@ -4,28 +4,29 @@
# have registered their U2F key # have registered their U2F key
package Lemonldap::NG::Portal::2F::U2F; package Lemonldap::NG::Portal::2F::U2F;
#use 5.16.0;
use strict; use strict;
use Mouse; use Mouse;
use JSON qw(from_json to_json); use JSON qw(from_json to_json);
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADCREDENTIALS
PE_ERROR
PE_OK PE_OK
PE_SENDRESPONSE PE_ERROR
PE_U2FFAILED PE_U2FFAILED
PE_SENDRESPONSE
PE_BADCREDENTIALS
); );
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::SecondFactor', extends qw(
'Lemonldap::NG::Portal::Lib::U2F'; Lemonldap::NG::Portal::Main::SecondFactor
Lemonldap::NG::Portal::Lib::U2F
);
# INITIALIZATION # INITIALIZATION
has rule => ( is => 'rw' ); has rule => ( is => 'rw' );
has prefix => ( is => 'ro', default => 'u' ); has prefix => ( is => 'ro', default => 'u' );
has logo => ( is => 'rw', default => 'u2f.png' ); has logo => ( is => 'rw', default => 'u2f.png' );
sub init { sub init {
my ($self) = @_; my ($self) = @_;
@ -52,7 +53,10 @@ sub run {
my ( $self, $req, $token ) = @_; my ( $self, $req, $token ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("U2F checkLogins set") if ($checkLogins); $self->logger->debug("U2F: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("U2F: stayconnected set") if $stayconnected;
# Check if user is registered # Check if user is registered
if ( my $res = $self->loadUser( $req, $req->sessionInfo ) ) { if ( my $res = $self->loadUser( $req, $req->sessionInfo ) ) {
@ -91,11 +95,12 @@ sub run {
$req, $req,
'u2fcheck', 'u2fcheck',
params => { params => {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req), SKIN => $self->p->getSkin($req),
DATA => $data, DATA => $data,
TOKEN => $token, TOKEN => $token,
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );

View File

@ -13,17 +13,14 @@ extends 'Lemonldap::NG::Portal::Main::SecondFactor';
# INITIALIZATION # INITIALIZATION
has prefix => ( is => 'ro', default => 'utotp' ); has prefix => ( is => 'ro', default => 'utotp' );
has logo => ( is => 'rw', default => 'utotp.png' );
has logo => ( is => 'rw', default => 'utotp.png' ); has u2f => ( is => 'rw' );
has totp => ( is => 'rw' );
has u2f => ( is => 'rw' );
has totp => ( is => 'rw' );
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_ERROR PE_ERROR
PE_FORMEMPTY PE_FORMEMPTY
PE_OK
PE_SENDRESPONSE PE_SENDRESPONSE
); );
@ -61,13 +58,17 @@ sub run {
$self->logger->debug('Generate TOTP form'); $self->logger->debug('Generate TOTP form');
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("UTOTP checkLogins set") if ($checkLogins); $self->logger->debug("UTOTP: checkLogins set") if $checkLogins;
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("UTOTP: stayconnected set") if $stayconnected;
my %tplPrms = ( my %tplPrms = (
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req), SKIN => $self->p->getSkin($req),
TOKEN => $token, TOKEN => $token,
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
); );
if ( my $res = $self->u2f->loadUser( $req, $req->sessionInfo ) ) { if ( my $res = $self->u2f->loadUser( $req, $req->sessionInfo ) ) {

View File

@ -8,10 +8,10 @@ use strict;
use Mouse; use Mouse;
use JSON qw(from_json to_json); use JSON qw(from_json to_json);
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_ERROR PE_ERROR
PE_BADOTP PE_BADOTP
PE_FORMEMPTY PE_FORMEMPTY
PE_OK
PE_SENDRESPONSE PE_SENDRESPONSE
); );
@ -121,7 +121,10 @@ sub run {
my ( $self, $req, $token, $_2fDevices ) = @_; my ( $self, $req, $token, $_2fDevices ) = @_;
my $checkLogins = $req->param('checkLogins'); my $checkLogins = $req->param('checkLogins');
$self->logger->debug("Yubikey checkLogins set") if ($checkLogins); $self->logger->debug("Yubikey; checkLogins set") if ($checkLogins);
my $stayconnected = $req->param('stayconnected');
$self->logger->debug("Yubikey: stayconnected set") if $stayconnected;
my $yubikey = $self->_findYubikey( $req, $req->sessionInfo ); my $yubikey = $self->_findYubikey( $req, $req->sessionInfo );
@ -144,7 +147,8 @@ sub run {
TARGET => '/yubikey2fcheck?skin=' . $self->p->getSkin($req), TARGET => '/yubikey2fcheck?skin=' . $self->p->getSkin($req),
INPUTLOGO => 'yubikey.png', INPUTLOGO => 'yubikey.png',
LEGEND => 'clickOnYubikey', LEGEND => 'clickOnYubikey',
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins,
STAYCONNECTED => $stayconnected
} }
); );
$self->logger->debug("Display Yubikey form"); $self->logger->debug("Display Yubikey form");

View File

@ -5,14 +5,14 @@ use JSON qw(from_json to_json);
use Mouse; use Mouse;
use Lemonldap::NG::Common::FormEncode; use Lemonldap::NG::Common::FormEncode;
use Lemonldap::NG::Portal::Main::Constants qw( use Lemonldap::NG::Portal::Main::Constants qw(
PE_BADURL
PE_BADCREDENTIALS
PE_CONFIRM
PE_ERROR
PE_LOGOUT_OK
PE_REDIRECT
PE_OK PE_OK
PE_ERROR
PE_BADURL
PE_CONFIRM
PE_REDIRECT
PE_LOGOUT_OK
PE_PASSWORD_OK PE_PASSWORD_OK
PE_BADCREDENTIALS
PE_UNAUTHORIZEDPARTNER PE_UNAUTHORIZEDPARTNER
PE_OIDC_SERVICE_NOT_ALLOWED PE_OIDC_SERVICE_NOT_ALLOWED
); );
@ -988,7 +988,12 @@ sub run {
return PE_CONFIRM; return PE_CONFIRM;
} }
} }
$self->logger->error("Unknown OIDC endpoint $path, skipping");
$self->logger->error(
$path
? "Unknown OIDC endpoint: $path, skipping"
: 'No OIDC endpoint found, aborting'
);
return PE_ERROR; return PE_ERROR;
} }
@ -998,10 +1003,7 @@ sub token {
$self->logger->debug("URL detected as an OpenID Connect TOKEN URL"); $self->logger->debug("URL detected as an OpenID Connect TOKEN URL");
my $rp = $self->checkEndPointAuthenticationCredentials($req); my $rp = $self->checkEndPointAuthenticationCredentials($req);
return $self->p->sendError( $req, 'invalid_request', 400 ) unless ($rp);
unless ($rp) {
return $self->p->sendError( $req, 'invalid_request', 400 );
}
my $grant_type = $req->param('grant_type'); my $grant_type = $req->param('grant_type');
@ -1032,8 +1034,8 @@ sub token {
else { else {
$self->userLogger->error( $self->userLogger->error(
$grant_type $grant_type
? "Missing grant_type parameter" ? "Unknown grant type: $grant_type"
: "Unknown grant type: $grant_type" : "Missing grant_type parameter"
); );
return $self->p->sendError( $req, 'unsupported_grant_type', 400 ); return $self->p->sendError( $req, 'unsupported_grant_type', 400 );
} }
@ -1042,12 +1044,10 @@ sub token {
sub _handlePasswordGrant { sub _handlePasswordGrant {
my ( $self, $req, $rp ) = @_; my ( $self, $req, $rp ) = @_;
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID}; my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
my $scope = $req->param('scope') || 'openid'; my $scope = $req->param('scope') || 'openid';
my $username = $req->param('username');
my $username = $req->param('username'); my $password = $req->param('password');
my $password = $req->param('password');
unless ( $username and $password ) { unless ( $username and $password ) {
$self->logger->error("Missing username or password"); $self->logger->error("Missing username or password");
@ -1080,9 +1080,8 @@ sub _handlePasswordGrant {
if $result; if $result;
## Make sure we returned successfuly from the process AND we were able to create a session ## Make sure we returned successfuly from the process AND we were able to create a session
unless ( $result == PE_OK and $req->id and $req->user ) { return $self->p->sendError( $req, 'invalid_grant', 400 )
return $self->p->sendError( $req, 'invalid_grant', 400 ); unless ( $result == PE_OK and $req->id and $req->user );
}
## Make sure the current user is allowed to use this RP ## Make sure the current user is allowed to use this RP
if ( my $rule = $self->spRules->{$rp} ) { if ( my $rule = $self->spRules->{$rp} ) {
@ -1169,10 +1168,8 @@ sub _handlePasswordGrant {
sub _handleAuthorizationCodeGrant { sub _handleAuthorizationCodeGrant {
my ( $self, $req, $rp ) = @_; my ( $self, $req, $rp ) = @_;
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID}; my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
my $code = $req->param('code');
my $code = $req->param('code');
unless ($code) { unless ($code) {
$self->logger->error("No code found on token endpoint"); $self->logger->error("No code found on token endpoint");
@ -1180,7 +1177,6 @@ sub _handleAuthorizationCodeGrant {
} }
my $codeSession = $self->getAuthorizationCode($code); my $codeSession = $self->getAuthorizationCode($code);
unless ($codeSession) { unless ($codeSession) {
$self->logger->error("Unable to find OIDC session $code"); $self->logger->error("Unable to find OIDC session $code");
return $self->p->sendError( $req, 'invalid_request', 400 ); return $self->p->sendError( $req, 'invalid_request', 400 );
@ -1402,9 +1398,7 @@ sub _handleAuthorizationCodeGrant {
} }
sub _handleRefreshTokenGrant { sub _handleRefreshTokenGrant {
my ( $self, $req, $rp ) = @_; my ( $self, $req, $rp ) = @_;
my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID}; my $client_id = $self->oidcRPList->{$rp}->{oidcRPMetaDataOptionsClientID};
my $refresh_token = $req->param('refresh_token'); my $refresh_token = $req->param('refresh_token');
@ -1660,10 +1654,8 @@ sub userInfo {
my $userinfo_response = my $userinfo_response =
$self->buildUserInfoResponse( $req, $scope, $rp, $session ); $self->buildUserInfoResponse( $req, $scope, $rp, $session );
unless ($userinfo_response) { return $self->returnBearerError( 'invalid_request', 'Invalid request', 401 )
return $self->returnBearerError( 'invalid_request', unless ($userinfo_response);
'Invalid request', 401 );
}
my $userinfo_sign_alg = $self->conf->{oidcRPMetaDataOptions}->{$rp} my $userinfo_sign_alg = $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsUserInfoSignAlg}; ->{oidcRPMetaDataOptionsUserInfoSignAlg};
@ -1695,18 +1687,14 @@ sub _getSessionFromAccessTokenData {
# Get user identifier # Get user identifier
$session = $self->p->getApacheSession( $tokenData->{user_session_id} ); $session = $self->p->getApacheSession( $tokenData->{user_session_id} );
$self->logger->error("Unable to find user session") unless ($session);
unless ($session) {
$self->logger->error("Unable to find user session");
}
} }
else { else {
my $offline_session_id = $tokenData->{offline_session_id}; my $offline_session_id = $tokenData->{offline_session_id};
if ($offline_session_id) { if ($offline_session_id) {
$session = $self->getRefreshToken($offline_session_id); $session = $self->getRefreshToken($offline_session_id);
unless ($session) { $self->logger->error("Unable to find refresh session")
$self->logger->error("Unable to find refresh session"); unless ($session);
}
} }
} }
return $session; return $session;
@ -1717,10 +1705,7 @@ sub introspection {
$self->logger->debug("URL detected as an OpenID Connect INTROSPECTION URL"); $self->logger->debug("URL detected as an OpenID Connect INTROSPECTION URL");
my $rp = $self->checkEndPointAuthenticationCredentials($req); my $rp = $self->checkEndPointAuthenticationCredentials($req);
return $self->p->sendError( $req, 'invalid_client', 401 ) unless ($rp);
unless ($rp) {
return $self->p->sendError( $req, 'invalid_client', 401 );
}
if ( $self->conf->{oidcRPMetaDataOptions}->{$rp} if ( $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsPublic} ) ->{oidcRPMetaDataOptionsPublic} )
@ -1732,9 +1717,7 @@ sub introspection {
} }
my $token = $req->param('token'); my $token = $req->param('token');
unless ($token) { return $self->p->sendError( $req, 'invalid_request', 400 ) unless ($token);
return $self->p->sendError( $req, 'invalid_request', 400 );
}
my $response = { active => JSON::false }; my $response = { active => JSON::false };
my $oidcSession = $self->getOpenIDConnectSession($token); my $oidcSession = $self->getOpenIDConnectSession($token);
@ -1806,9 +1789,8 @@ sub registration {
# Get client metadata # Get client metadata
my $client_metadata_json = $req->content; my $client_metadata_json = $req->content;
unless ($client_metadata_json) { return $self->p->sendError( $req, 'Missing POST data', 400 )
return $self->p->sendError( $req, 'Missing POST data', 400 ); unless ($client_metadata_json);
}
$self->logger->debug("Client metadata received: $client_metadata_json"); $self->logger->debug("Client metadata received: $client_metadata_json");

View File

@ -10,6 +10,7 @@ use Lemonldap::NG::Portal::Main::Constants ':all';
use Encode; use Encode;
use Unicode::String qw(utf8); use Unicode::String qw(utf8);
use Scalar::Util 'weaken'; use Scalar::Util 'weaken';
use IO::Socket::Timeout;
use utf8; use utf8;
our $VERSION = '2.1.0'; our $VERSION = '2.1.0';
@ -76,6 +77,13 @@ sub new {
} }
} }
bless $self, $class; bless $self, $class;
# Set socket timeouts
my $socket = $self->socket;
IO::Socket::Timeout->enable_timeouts_on($socket);
$socket->read_timeout( $conf->{ldapIOTimeout} );
$socket->write_timeout( $conf->{ldapIOTimeout} );
if ($useTls) { if ($useTls) {
my %h = split( /[&=]/, $tlsParam ); my %h = split( /[&=]/, $tlsParam );
$h{cafile} ||= $conf->{ldapCAFile} if ( $conf->{ldapCAFile} ); $h{cafile} ||= $conf->{ldapCAFile} if ( $conf->{ldapCAFile} );

View File

@ -124,8 +124,9 @@ sub display {
CHOICE_VALUE => $req->data->{_authChoice}, CHOICE_VALUE => $req->data->{_authChoice},
CHECK_LOGINS => $self->conf->{portalCheckLogins} CHECK_LOGINS => $self->conf->{portalCheckLogins}
&& $req->data->{login}, && $req->data->{login},
ASK_LOGINS => $req->param('checkLogins') || 0, ASK_LOGINS => $req->param('checkLogins') || 0,
CONFIRMKEY => $self->stamp(), ASK_STAYCONNECTED => $req->param('stayconnected') || 0,
CONFIRMKEY => $self->stamp(),
( (
$req->data->{customScript} $req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
@ -150,9 +151,10 @@ sub display {
CHOICE_VALUE => $req->data->{_authChoice}, CHOICE_VALUE => $req->data->{_authChoice},
CHECK_LOGINS => $self->conf->{portalCheckLogins} CHECK_LOGINS => $self->conf->{portalCheckLogins}
&& $req->data->{login}, && $req->data->{login},
ASK_LOGINS => $req->param('checkLogins') || 0, ASK_LOGINS => $req->param('checkLogins') || 0,
CONFIRMKEY => $self->stamp(), ASK_STAYCONNECTED => $req->param('stayconnected') || 0,
LIST => $req->data->{list} || [], CONFIRMKEY => $self->stamp(),
LIST => $req->data->{list} || [],
( (
$req->data->{customScript} $req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
@ -382,6 +384,7 @@ sub display {
DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword}, DONT_STORE_PASSWORD => $self->conf->{browsersDontStorePassword},
CHECK_LOGINS => $self->conf->{portalCheckLogins}, 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_RESETPASSWORD => $self->conf->{portalDisplayResetPassword},
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister}, DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
DISPLAY_UPDATECERTIF => DISPLAY_UPDATECERTIF =>

View File

@ -104,10 +104,10 @@ sub createNotification {
} }
} }
sub allowedUpdateSfa { sub canUpdateSfa {
my ( $self, $req, $action ) = @_; my ( $self, $req, $action ) = @_;
my $user = $req->userData->{ $self->conf->{whatToTrace} }; my $user = $req->userData->{ $self->conf->{whatToTrace} };
my $res = 1; my $msg = undef;
# Test action # Test action
if ( $action && $action eq 'delete' ) { if ( $action && $action eq 'delete' ) {
@ -125,12 +125,12 @@ sub allowedUpdateSfa {
$self->logger->debug( $self->logger->debug(
"authLevel: $req->{userData}->{authenticationLevel} < requiredLevel: " "authLevel: $req->{userData}->{authenticationLevel} < requiredLevel: "
. $self->{conf}->{"${module}2fAuthnLevel"} ); . $self->{conf}->{"${module}2fAuthnLevel"} );
undef $res; $msg = 'notAuthorizedAuthLevel';
} }
} }
# Test if impersonation is in progress # Test if impersonation is in progress
if ( $res && $self->conf->{impersonationRule} ) { if ( !$msg && $self->conf->{impersonationRule} ) {
$self->logger->debug('Impersonation plugin is enabled'); $self->logger->debug('Impersonation plugin is enabled');
if ( $req->userData->{"$self->{conf}->{impersonationPrefix}_user"} if ( $req->userData->{"$self->{conf}->{impersonationPrefix}_user"}
&& $req->userData->{"$self->{conf}->{impersonationPrefix}_user"} ne && $req->userData->{"$self->{conf}->{impersonationPrefix}_user"} ne
@ -139,12 +139,12 @@ sub allowedUpdateSfa {
$self->userLogger->warn( $self->userLogger->warn(
"Impersonation in progress! $user is not allowed to update 2FA." "Impersonation in progress! $user is not allowed to update 2FA."
); );
undef $res; $msg = 'notAuthorized';
} }
} }
# Test if contextSwitching is in progress # Test if contextSwitching is in progress
if ( $res && $self->conf->{contextSwitchingRule} ) { if ( !$msg && $self->conf->{contextSwitchingRule} ) {
$self->logger->debug('ContextSwitching plugin is enabled'); $self->logger->debug('ContextSwitching plugin is enabled');
if ( if (
$req->userData->{ $req->userData->{
@ -154,11 +154,11 @@ sub allowedUpdateSfa {
$self->userLogger->warn( $self->userLogger->warn(
"ContextSwitching in progress! $user is not allowed to update 2FA." "ContextSwitching in progress! $user is not allowed to update 2FA."
); );
undef $res; $msg = 'notAuthorized';
} }
} }
$self->userLogger->info("$user is allowed to update 2FA") if $res; $self->userLogger->info("$user is allowed to update 2FA") unless $msg;
return $res; return $msg;
} }
1; 1;

View File

@ -19,8 +19,8 @@ our @pList = (
portalStatus => '::Plugins::Status', portalStatus => '::Plugins::Status',
cda => '::Plugins::CDA', cda => '::Plugins::CDA',
notification => '::Plugins::Notifications', notification => '::Plugins::Notifications',
portalCheckLogins => '::Plugins::History',
stayConnected => '::Plugins::StayConnected', stayConnected => '::Plugins::StayConnected',
portalCheckLogins => '::Plugins::History',
bruteForceProtection => '::Plugins::BruteForceProtection', bruteForceProtection => '::Plugins::BruteForceProtection',
grantSessionRules => '::Plugins::GrantSession', grantSessionRules => '::Plugins::GrantSession',
upgradeSession => '::Plugins::Upgrade', upgradeSession => '::Plugins::Upgrade',

View File

@ -56,9 +56,17 @@ sub init {
sub newDevice { sub newDevice {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $checkLogins = $req->param('checkLogins');
$self->logger->debug("StayConnected: checkLogins set") if $checkLogins;
if ( $req->param('stayconnected') ) { if ( $req->param('stayconnected') ) {
my $token = $self->ott->createToken( { my $token = $self->ott->createToken( {
name => $req->sessionInfo->{ $self->conf->{whatToTrace} } name => $req->sessionInfo->{ $self->conf->{whatToTrace} },
(
$checkLogins
? ( history => $req->sessionInfo->{_loginHistory} )
: ()
)
} }
); );
$req->response( $req->response(
@ -66,9 +74,10 @@ sub newDevice {
$req, $req,
'../common/registerBrowser', '../common/registerBrowser',
params => { params => {
URL => $req->urldc, URL => $req->urldc,
TOKEN => $token, TOKEN => $token,
ACTION => '/registerbrowser', ACTION => '/registerbrowser',
CHECKLOGINS => $checkLogins
} }
) )
); );
@ -109,6 +118,7 @@ sub storeBrowser {
max_age => 2592000, max_age => 2592000,
) )
); );
$req->sessionInfo->{_loginHistory} = $tmp->{history} if exists $tmp->{history};
} }
else { else {
$self->logger->warn("Browser hasn't return fingerprint"); $self->logger->warn("Browser hasn't return fingerprint");
@ -128,8 +138,8 @@ sub storeBrowser {
$self->userLogger->error('StayConnected called without token'); $self->userLogger->error('StayConnected called without token');
} }
# Deliver cookie llngbrowser # Return cookie llngconnexion
return $self->p->do( $req, [ sub { PE_OK } ] ); return $self->p->do( $req, [ @{ $self->p->endAuth }, sub { PE_OK } ] );
} }
# Check for: # Check for:

View File

@ -65,14 +65,18 @@ sub confirmRenew {
# RUNNING METHOD # RUNNING METHOD
sub ask { sub ask {
my ( $self, $req, $url, $message, $buttonlabel ) = @_; my ( $self, $req, $form_action, $message, $buttonlabel ) = @_;
# Check if auth is already running # Check if auth is already running
if ( $req->param('upgrading') or $req->param('kerberos') ) { # and verify token
return $self->confirm($req)
if ( $req->param('upgrading') or $req->param('kerberos') );
# verify token my $url = $req->param('url') || '';
return $self->confirm($req); my $action = ( $message =~ /^askTo(\w+)$/ )[0];
} $self->logger->debug(" -> $action required");
$self->logger->debug(" -> Skip confirmation is enabled")
if $self->conf->{"skip${action}Confirmation"};
# Display form # Display form
return $self->p->sendHtml( return $self->p->sendHtml(
@ -81,13 +85,20 @@ sub ask {
params => { params => {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
LANGS => $self->conf->{showLanguages}, LANGS => $self->conf->{showLanguages},
FORMACTION => $url, FORMACTION => $form_action,
PORTALBUTTON => 1, PORTALBUTTON => 1,
MSG => $message, MSG => $message,
BUTTON => $buttonlabel, BUTTON => $buttonlabel,
CONFIRMKEY => $self->p->stamp, CONFIRMKEY => $self->p->stamp,
PORTAL => $self->conf->{portal}, PORTAL => $self->conf->{portal},
URL => $req->param('url'), URL => $url,
(
$self->conf->{"skip${action}Confirmation"}
? ( CUSTOM_SCRIPT =>
qq'<script type="text/javascript" src="$self->{p}->{staticPrefix}/common/js/autoRenew.min.js"></script>'
)
: ()
)
} }
); );
} }

View File

@ -174,4 +174,10 @@ input.key {
/*font-style: normal;*/ /*font-style: normal;*/
/*font-weight: 400;*/ /*font-weight: 400;*/
src: url(/static/common/fonts/password.ttf); src: url(/static/common/fonts/password.ttf);
} }
.info.table caption {
color: black;
text-align: center;
caption-side: bottom;
}

View File

@ -1 +1 @@
html,body{height:100%;background:radial-gradient(circle at 50% 0,#fff 0,#ddd 100%) no-repeat scroll 0 0 #ddd}#wrap{min-height:100%;height:auto;margin:0 auto -80px;padding:20px 0 80px}#footer{height:80px;background-color:#fff;background-color:rgba(255,255,255,0.9);text-align:center;padding-top:10px;overflow:hidden}#header img{background-color:#fff;background-color:rgba(255,255,255,0.8);margin-bottom:20px}.card,.navbar-light{background-color:#fff;background-color:rgba(255,255,255,0.9);background-image:none}.login,.password{text-align:center;padding:20px}div.form{margin:0 auto;max-width:330px}div.actions{margin:10px 0 0 0}div.actions a{margin-top:10px}.buttons{text-align:center;margin:10px 0 0 0;cursor:pointer}.btn{white-space:normal}.btn span.fa{padding-right:8px}li.ui-state-active{background-color:#fafafa;background-color:rgba(250,250,250,0.9)}#appslist,#password,#loginHistory,#logout,#oidcConsents{margin-top:20px}div.category{margin:10px 0;cursor:grab}div.application{margin:5px 0;overflow:hidden}div.application a,div.application a:hover{text-decoration:none}p.notifCheck label{margin-left:5px;margin-top:3px;display:inline-block}img.langicon{cursor:pointer}button.idploop{max-width:300px}button.idploop img{max-height:30px}div.oidc_consent_message>ul{text-align:left;list-style:circle}@media(min-width:768px){div.application{height:80px}div.application h4.appname{margin:0}#wrap{margin:0 auto -60px}#footer{height:60px}}.hiddenFrame{border:0;display:hidden;margin:0}.noborder{border:0}.max{width:100%}.link{cursor:pointer}.nodecor:hover,.nodecor:active.nodecor:focus{text-decoration:none}.fa.icon-blue{color:blue}.progress-bar-animated{width:100%}input.key{font-family:'password';width:100px}@font-face{font-family:'password';src:url(/static/common/fonts/password.ttf)} html,body{height:100%;background:radial-gradient(circle at 50% 0,#fff 0,#ddd 100%) no-repeat scroll 0 0 #ddd}#wrap{min-height:100%;height:auto;margin:0 auto -80px;padding:20px 0 80px}#footer{height:80px;background-color:#fff;background-color:rgba(255,255,255,0.9);text-align:center;padding-top:10px;overflow:hidden}#header img{background-color:#fff;background-color:rgba(255,255,255,0.8);margin-bottom:20px}.card,.navbar-light{background-color:#fff;background-color:rgba(255,255,255,0.9);background-image:none}.login,.password{text-align:center;padding:20px}div.form{margin:0 auto;max-width:330px}div.actions{margin:10px 0 0 0}div.actions a{margin-top:10px}.buttons{text-align:center;margin:10px 0 0 0;cursor:pointer}.btn{white-space:normal}.btn span.fa{padding-right:8px}li.ui-state-active{background-color:#fafafa;background-color:rgba(250,250,250,0.9)}#appslist,#password,#loginHistory,#logout,#oidcConsents{margin-top:20px}div.category{margin:10px 0;cursor:grab}div.application{margin:5px 0;overflow:hidden}div.application a,div.application a:hover{text-decoration:none}p.notifCheck label{margin-left:5px;margin-top:3px;display:inline-block}img.langicon{cursor:pointer}button.idploop{max-width:300px}button.idploop img{max-height:30px}div.oidc_consent_message>ul{text-align:left;list-style:circle}@media(min-width:768px){div.application{height:80px}div.application h4.appname{margin:0}#wrap{margin:0 auto -60px}#footer{height:60px}}.hiddenFrame{border:0;display:hidden;margin:0}.noborder{border:0}.max{width:100%}.link{cursor:pointer}.nodecor:hover,.nodecor:active.nodecor:focus{text-decoration:none}.fa.icon-blue{color:blue}.progress-bar-animated{width:100%}input.key{font-family:'password';width:100px}@font-face{font-family:'password';src:url(/static/common/fonts/password.ttf)}.info.table caption{color:black;text-align:center;caption-side:bottom}

View File

@ -1 +1 @@
(function(){var a=function(e,r){return $("#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),a(o,"warning")},t="",e=function(e){return a("yourTotpKey","warning"),$.ajax({type:"POST",url:portal+"/2fregisters/totp/getkey",dataType:"json",data:{newkey:e},error:r,success:function(e){var r;return e.error?(e.error.match(/totpExistingKey/)&&$("#divToHide").hide(),a(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}),$("#serialized").text(r),e.newkey?a("yourNewTotpKey","warning"):a("yourTotpKey","success"),t=e.token):a("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)/)?a(e.error,"warning"):a(e.error,"danger"):a("yourKeyIsRegistered","success")}}):a("fillTheForm","warning")};$(document).ready(function(){return e(0),$("#changekey").on("click",function(){return e(1)}),$("#verify").on("click",o)})}).call(this); (function(){var r,e,n,t,o;n=function(e,r){return $("#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),n(o,"warning")},t="",e=function(e){return n("yourTotpKey","warning"),$.ajax({type:"POST",url:portal+"/2fregisters/totp/getkey",dataType:"json",data:{newkey:e},error:r,success:function(e){var r;return e.error?(e.error.match(/totpExistingKey/)&&$("#divToHide").hide(),n(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}),$("#serialized").text(r),e.newkey?n("yourNewTotpKey","warning"):n("yourTotpKey","success"),t=e.token):n("PE24","danger")}})},o=function(){var e;return(e=$("#code").val())?$.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)/)?n(e.error,"warning"):n(e.error,"danger"):n("yourKeyIsRegistered","success")}}):n("fillTheForm","warning")},$(document).ready(function(){return e(0),$("#changekey").on("click",function(){return e(1)}),$("#verify").on("click",function(){return o()})})}).call(this);

View File

@ -1 +1 @@
{"version":3,"sources":["totpregistration.js"],"names":["setMsg","msg","level","$","html","window","translate","removeClass","addClass","displayError","j","status","err","res","console","log","JSON","parse","responseText","error","replace","token","getKey","reset","ajax","type","url","portal","dataType","data","newkey","success","s","match","hide","user","secret","show","escape","digits","interval","QRious","element","document","getElementById","value","size","text","verify","val","code","TOTPName","ready","on","call","this"],"mappings":"CAMA,WACE,IAEAA,EAAS,SAASC,EAAKC,GAOrB,OANAC,EAAE,QAAQC,KAAKC,OAAOC,UAAUL,IAChCE,EAAE,UAAUI,YAAY,4FACxBJ,EAAE,UAAUK,SAAS,WAAaN,GACpB,aAAVA,IACFA,EAAQ,WAEHC,EAAE,UAAUK,SAAS,SAAWN,IAGzCO,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,GACvBb,EAAOa,EAAK,YAIvBQ,EAAQ,GAERC,EAAS,SAASC,GAEhB,OADAvB,EAAO,cAAe,WACfG,EAAEqB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVC,KAAM,CACJC,OAAQP,GAEVJ,MAAOV,EACPsB,QAAS,SAASF,GAChB,IAAQG,EACR,OAAIH,EAAKV,OACHU,EAAKV,MAAMc,MAAM,oBACnB9B,EAAE,cAAc+B,OAEXlC,EAAO6B,EAAKV,MAAO,YAEtBU,EAAKF,QAAUE,EAAKM,MAAQN,EAAKO,QAGvCjC,EAAE,cAAckC,OAChBL,EAAI,kBAAqBM,OAAOT,EAAKF,QAAW,IAAOW,OAAOT,EAAKM,MAAS,WAAaN,EAAKO,OAAS,WAAcE,OAAOT,EAAKF,QAC7G,IAAhBE,EAAKU,SACPP,GAAK,WAAaH,EAAKU,QAEH,KAAlBV,EAAKW,WACPR,GAAK,WAAaH,EAAKW,UAEpB,IAAIC,OAAO,CACdC,QAASC,SAASC,eAAe,MACjCC,MAAOb,EACPc,KAAM,MAER3C,EAAE,eAAe4C,KAAKf,GAClBH,EAAKC,OACP9B,EAAO,iBAAkB,WAEzBA,EAAO,cAAe,WAEjBqB,EAAQQ,EAAKR,OArBXrB,EAAO,OAAQ,cA0B9BgD,EAAS,WACP,IACAC,EAAM9C,EAAE,SAAS8C,MACjB,OAAKA,EAGI9C,EAAEqB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVC,KAAM,CACJR,MAAOA,EACP6B,KAAMD,EACNE,SAAUhD,EAAE,aAAa8C,OAE3B9B,MAAOV,EACPsB,QAAS,SAASF,GAChB,OAAIA,EAAKV,MACHU,EAAKV,MAAMc,MAAM,kBACZjC,EAAO6B,EAAKV,MAAO,WAEnBnB,EAAO6B,EAAKV,MAAO,UAGrBnB,EAAO,sBAAuB,cApBpCA,EAAO,cAAe,YA2BjCG,EAAEwC,UAAUS,MAAM,WAKhB,OAJA9B,EAAO,GACPnB,EAAE,cAAckD,GAAG,QAAS,WAC1B,OAAO/B,EAAO,KAETnB,EAAE,WAAWkD,GAAG,QACdL,OAIVM,KAAKC"} {"version":3,"sources":["totpregistration.js"],"names":["displayError","getKey","setMsg","token","verify","msg","level","$","html","window","translate","removeClass","addClass","j","status","err","res","console","log","JSON","parse","responseText","error","replace","reset","ajax","type","url","portal","dataType","data","newkey","success","s","match","hide","user","secret","show","escape","digits","interval","QRious","element","document","getElementById","value","size","text","val","code","TOTPName","ready","on","call","this"],"mappings":"CAMA,WACE,IAAIA,EAAcC,EAAQC,EAAQC,EAAOC,EAEzCF,EAAS,SAASG,EAAKC,GAOrB,OANAC,EAAE,QAAQC,KAAKC,OAAOC,UAAUL,IAChCE,EAAE,UAAUI,YAAY,4FACxBJ,EAAE,UAAUK,SAAS,WAAaN,GACpB,aAAVA,IACFA,EAAQ,WAEHC,EAAE,UAAUK,SAAS,SAAWN,IAGzCN,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,YAIvBb,EAAQ,GAERF,EAAS,SAASuB,GAEhB,OADAtB,EAAO,cAAe,WACfK,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVC,KAAM,CACJC,OAAQP,GAEVF,MAAOtB,EACPgC,QAAS,SAASF,GAChB,IAAQG,EACR,OAAIH,EAAKR,OACHQ,EAAKR,MAAMY,MAAM,oBACnB3B,EAAE,cAAc4B,OAEXjC,EAAO4B,EAAKR,MAAO,YAEtBQ,EAAKF,QAAUE,EAAKM,MAAQN,EAAKO,QAGvC9B,EAAE,cAAc+B,OAChBL,EAAI,kBAAqBM,OAAOT,EAAKF,QAAW,IAAOW,OAAOT,EAAKM,MAAS,WAAaN,EAAKO,OAAS,WAAcE,OAAOT,EAAKF,QAC7G,IAAhBE,EAAKU,SACPP,GAAK,WAAaH,EAAKU,QAEH,KAAlBV,EAAKW,WACPR,GAAK,WAAaH,EAAKW,UAEpB,IAAIC,OAAO,CACdC,QAASC,SAASC,eAAe,MACjCC,MAAOb,EACPc,KAAM,MAERxC,EAAE,eAAeyC,KAAKf,GAClBH,EAAKC,OACP7B,EAAO,iBAAkB,WAEzBA,EAAO,cAAe,WAEjBC,EAAQ2B,EAAK3B,OArBXD,EAAO,OAAQ,cA0B9BE,EAAS,WACP,IAAI6C,EAEJ,OADAA,EAAM1C,EAAE,SAAS0C,OAIR1C,EAAEkB,KAAK,CACZC,KAAM,OACNC,IAAKC,OAAS,2BACdC,SAAU,OACVC,KAAM,CACJ3B,MAAOA,EACP+C,KAAMD,EACNE,SAAU5C,EAAE,aAAa0C,OAE3B3B,MAAOtB,EACPgC,QAAS,SAASF,GAChB,OAAIA,EAAKR,MACHQ,EAAKR,MAAMY,MAAM,kBACZhC,EAAO4B,EAAKR,MAAO,WAEnBpB,EAAO4B,EAAKR,MAAO,UAGrBpB,EAAO,sBAAuB,cApBpCA,EAAO,cAAe,YA2BjCK,EAAEqC,UAAUQ,MAAM,WAKhB,OAJAnD,EAAO,GACPM,EAAE,cAAc8C,GAAG,QAAS,WAC1B,OAAOpD,EAAO,KAETM,EAAE,WAAW8C,GAAG,QAAS,WAC9B,OAAOjD,UAIVkD,KAAKC"}

View File

@ -181,7 +181,9 @@
"ipAddr":"عنوان الأي بي", "ipAddr":"عنوان الأي بي",
"key":"المفتاح", "key":"المفتاح",
"lastFailedLogins":"عمليات تسجيل الدخول الأخيرة الغير الناجحة", "lastFailedLogins":"عمليات تسجيل الدخول الأخيرة الغير الناجحة",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"آخر تسجيلات دخول", "lastLogins":"آخر تسجيلات دخول",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"اسم العائلة", "lastName":"اسم العائلة",
"linkValidUntil":"تحتوي هذه الرسالة على رابط لإعادة تعيين كلمة المرور، وهذا الرابط صالح حتى", "linkValidUntil":"تحتوي هذه الرسالة على رابط لإعادة تعيين كلمة المرور، وهذا الرابط صالح حتى",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -208,6 +210,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"لم يتم العثور: محاولة الدخول إلى صفحة غير متوفرة", "notFound":"لم يتم العثور: محاولة الدخول إلى صفحة غير متوفرة",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP address", "ipAddr":"IP address",
"key":"Key", "key":"Key",
"lastFailedLogins":"Letzte fehlgeschlagene Anmeldungen", "lastFailedLogins":"Letzte fehlgeschlagene Anmeldungen",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Letzte Anmeldungen", "lastLogins":"Letzte Anmeldungen",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Nachname", "lastName":"Nachname",
"linkValidUntil":"Diese Nachricht enthält einen Link zum Zurücksetzen deines Passworts. Dieser Link ist gültig bis", "linkValidUntil":"Diese Nachricht enthält einen Link zum Zurücksetzen deines Passworts. Dieser Link ist gültig bis",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"Du bist nicht dazu berechtigt", "notAuthorized":"Du bist nicht dazu berechtigt",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Nicht gefunden: Du versuchst, auf eine nicht verfügbare Seite zuzugreifen", "notFound":"Nicht gefunden: Du versuchst, auf eine nicht verfügbare Seite zuzugreifen",
"noTOTPFound":"Kein TOTP gefunden", "noTOTPFound":"Kein TOTP gefunden",
"noU2FKeyFound":"Kein U2F Schlüssel gefunden", "noU2FKeyFound":"Kein U2F Schlüssel gefunden",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP address", "ipAddr":"IP address",
"key":"Key", "key":"Key",
"lastFailedLogins":"Last failed logins", "lastFailedLogins":"Last failed logins",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Last logins", "lastLogins":"Last logins",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Last name", "lastName":"Last name",
"linkValidUntil":"This message contains a link to reset your password, this link is valid until ", "linkValidUntil":"This message contains a link to reset your password, this link is valid until ",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Not found: you try to access to an unavailable page", "notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -180,7 +180,9 @@
"ipAddr":"Dirección IP", "ipAddr":"Dirección IP",
"key":"Llave", "key":"Llave",
"lastFailedLogins":"Últimas conexiones fallidas", "lastFailedLogins":"Últimas conexiones fallidas",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Últimas conexiones", "lastLogins":"Últimas conexiones",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Apellido(s)", "lastName":"Apellido(s)",
"linkValidUntil":"Este mensaje contiene un enlace para reiniciar su contraseña, este enlace es válido hasta", "linkValidUntil":"Este mensaje contiene un enlace para reiniciar su contraseña, este enlace es válido hasta",
"linkValidUntilCertif":"Este mensaje contiene un link para reiniciar su certificado. Este link is válido hasta", "linkValidUntilCertif":"Este mensaje contiene un link para reiniciar su certificado. Este link is válido hasta",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"No es un valor encriptado", "notAnEncryptedValue":"No es un valor encriptado",
"notAuthorized":"Usted no está autorizado a hacer esto", "notAuthorized":"Usted no está autorizado a hacer esto",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"No encontrado: página no disponible", "notFound":"No encontrado: página no disponible",
"noTOTPFound":"TOTP no encontrado", "noTOTPFound":"TOTP no encontrado",
"noU2FKeyFound":"Llave U2F no encontrada", "noU2FKeyFound":"Llave U2F no encontrada",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP-osoite", "ipAddr":"IP-osoite",
"key":"Key", "key":"Key",
"lastFailedLogins":"Viimeiset virheelliset kirjautumiset", "lastFailedLogins":"Viimeiset virheelliset kirjautumiset",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Viimeisimmät kirjautumiset", "lastLogins":"Viimeisimmät kirjautumiset",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Sukunimi", "lastName":"Sukunimi",
"linkValidUntil":"Tämä viesti sisältää linkin salasanan nollaamiseen, linkki on voimassa", "linkValidUntil":"Tämä viesti sisältää linkin salasanan nollaamiseen, linkki on voimassa",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Not found: you try to access to an unavailable page", "notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -180,7 +180,9 @@
"ipAddr":"Adresse IP", "ipAddr":"Adresse IP",
"key":"Clef", "key":"Clef",
"lastFailedLogins":"Dernières connexions refusées", "lastFailedLogins":"Dernières connexions refusées",
"lastFailedLoginsCaptionLabel":"Dernières connexions refusées",
"lastLogins":"Dernières connexions", "lastLogins":"Dernières connexions",
"lastLoginsCaptionLabel":"Dernières connexions",
"lastName":"Nom", "lastName":"Nom",
"linkValidUntil":"Ce message contient un lien pour réinitialiser votre mot de passe, ce lien est valide jusqu'au ", "linkValidUntil":"Ce message contient un lien pour réinitialiser votre mot de passe, ce lien est valide jusqu'au ",
"linkValidUntilCertif":"Ce message contient un lien pour réinitialiser votre certificat, ce lien est valide jusqu'à ", "linkValidUntilCertif":"Ce message contient un lien pour réinitialiser votre certificat, ce lien est valide jusqu'à ",
@ -207,6 +209,7 @@
"noNotification":"Aucune notification acceptée trouvée", "noNotification":"Aucune notification acceptée trouvée",
"notAnEncryptedValue":"Ce n'est pas une valeur cryptée", "notAnEncryptedValue":"Ce n'est pas une valeur cryptée",
"notAuthorized":"Vous n'êtes pas autorisé à faire cette requête", "notAuthorized":"Vous n'êtes pas autorisé à faire cette requête",
"notAuthorizedAuthLevel":"Cette action requiert un niveau d'authentification supérieur",
"notFound": "Non trouvé : vous tentez d'accéder à une page non disponible", "notFound": "Non trouvé : vous tentez d'accéder à une page non disponible",
"noTOTPFound":"Aucun secret TOTP trouvé", "noTOTPFound":"Aucun secret TOTP trouvé",
"noU2FKeyFound": "Aucune clef U2F trouvée", "noU2FKeyFound": "Aucune clef U2F trouvée",

View File

@ -180,7 +180,9 @@
"ipAddr":"Indirizzo IP", "ipAddr":"Indirizzo IP",
"key":"Chiave", "key":"Chiave",
"lastFailedLogins":"Ultimi login non riusciti", "lastFailedLogins":"Ultimi login non riusciti",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Ultimi accessi", "lastLogins":"Ultimi accessi",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Cognome", "lastName":"Cognome",
"linkValidUntil":"Questo messaggio contiene un link per reimpostare la password, questo link è valido fino al", "linkValidUntil":"Questo messaggio contiene un link per reimpostare la password, questo link è valido fino al",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"Non sei autorizzato a farlo", "notAuthorized":"Non sei autorizzato a farlo",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Non trovato: si tenta di accedere ad una pagina non disponibile", "notFound":"Non trovato: si tenta di accedere ad una pagina non disponibile",
"noTOTPFound":"Nessun TOTP trovato", "noTOTPFound":"Nessun TOTP trovato",
"noU2FKeyFound":"Nessuna chiave U2F trovata", "noU2FKeyFound":"Nessuna chiave U2F trovata",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP address", "ipAddr":"IP address",
"key":"Key", "key":"Key",
"lastFailedLogins":"Last failed logins", "lastFailedLogins":"Last failed logins",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Last logins", "lastLogins":"Last logins",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Last name", "lastName":"Last name",
"linkValidUntil":"This message contains a link to reset your password, this link is valid until ", "linkValidUntil":"This message contains a link to reset your password, this link is valid until ",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Not found: you try to access to an unavailable page", "notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -180,7 +180,9 @@
"ipAddr":"Adres IP", "ipAddr":"Adres IP",
"key":"Klucz", "key":"Klucz",
"lastFailedLogins":"Ostatnie nieudane logowania", "lastFailedLogins":"Ostatnie nieudane logowania",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Ostatnie logowania", "lastLogins":"Ostatnie logowania",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Nazwisko", "lastName":"Nazwisko",
"linkValidUntil":"Ta wiadomość zawiera link do zresetowania hasła, ten link jest ważny do ", "linkValidUntil":"Ta wiadomość zawiera link do zresetowania hasła, ten link jest ważny do ",
"linkValidUntilCertif":"Ta wiadomość zawiera link do zresetowania certyfikatu, ten link jest ważny do ", "linkValidUntilCertif":"Ta wiadomość zawiera link do zresetowania certyfikatu, ten link jest ważny do ",
@ -207,6 +209,7 @@
"noNotification":"Nie znaleziono zaakceptowanego powiadomienia", "noNotification":"Nie znaleziono zaakceptowanego powiadomienia",
"notAnEncryptedValue":"To nie jest zaszyfrowana wartość", "notAnEncryptedValue":"To nie jest zaszyfrowana wartość",
"notAuthorized":"Nie masz do tego uprawnień", "notAuthorized":"Nie masz do tego uprawnień",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Nie znaleziono: próbujesz uzyskać dostęp do niedostępnej strony", "notFound":"Nie znaleziono: próbujesz uzyskać dostęp do niedostępnej strony",
"noTOTPFound":"Nie znaleziono TOTP", "noTOTPFound":"Nie znaleziono TOTP",
"noU2FKeyFound":"Nie znaleziono klucza U2F", "noU2FKeyFound":"Nie znaleziono klucza U2F",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP address", "ipAddr":"IP address",
"key":"Key", "key":"Key",
"lastFailedLogins":"Last failed logins", "lastFailedLogins":"Last failed logins",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Last logins", "lastLogins":"Last logins",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Last name", "lastName":"Last name",
"linkValidUntil":"This message contains a link to reset your password, this link is valid until ", "linkValidUntil":"This message contains a link to reset your password, this link is valid until ",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Not found: you try to access to an unavailable page", "notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP address", "ipAddr":"IP address",
"key":"Key", "key":"Key",
"lastFailedLogins":"Last failed logins", "lastFailedLogins":"Last failed logins",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Last logins", "lastLogins":"Last logins",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Last name", "lastName":"Last name",
"linkValidUntil":"This message contains a link to reset your password, this link is valid until ", "linkValidUntil":"This message contains a link to reset your password, this link is valid until ",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Not found: you try to access to an unavailable page", "notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -93,7 +93,7 @@
"PE101":"Parola izin verilmeyen karakterler içeriyor", "PE101":"Parola izin verilmeyen karakterler içeriyor",
"PE102":"Oturum yükseltilmeli", "PE102":"Oturum yükseltilmeli",
"PE103":"Hesabınız için ikinci faktör kullanılabilir değil", "PE103":"Hesabınız için ikinci faktör kullanılabilir değil",
"2FDeviceNotFound":"2F device not found", "2FDeviceNotFound":"2F cihazı bulunamadı",
"2fRegRequired":"Bu servis iki adımlı kimlik doğrulama gerektiriyor. Şimdi bir cihaz ekleyin ve ardından portala geri dönün", "2fRegRequired":"Bu servis iki adımlı kimlik doğrulama gerektiriyor. Şimdi bir cihaz ekleyin ve ardından portala geri dönün",
"accept":"Kabul Et", "accept":"Kabul Et",
"accessDenied":"Bu uygulamaya erişim yetkiniz yok", "accessDenied":"Bu uygulamaya erişim yetkiniz yok",
@ -124,7 +124,7 @@
"changePwd":"Parolanı değiştir", "changePwd":"Parolanı değiştir",
"checkLastLogins":"Son girişlerimi kontrol et", "checkLastLogins":"Son girişlerimi kontrol et",
"checkUser":"Kullanıcı TOA profilini kontrol et", "checkUser":"Kullanıcı TOA profilini kontrol et",
"checkUserComputedSession":"No SSO session found. Computed data!", "checkUserComputedSession":"TOA oturumu bulunamadı. Hesaplanan veri!",
"checkUserMerged":"Kullanıcı TOA profilini kontrol et. Bazı Gerçek ve Sahte TOA grupları birleştirildi!", "checkUserMerged":"Kullanıcı TOA profilini kontrol et. Bazı Gerçek ve Sahte TOA grupları birleştirildi!",
"checkUserComputeSession":"Hesaplanan oturum verisi!", "checkUserComputeSession":"Hesaplanan oturum verisi!",
"certificateReset":"Reset my certificate", "certificateReset":"Reset my certificate",
@ -181,7 +181,9 @@
"ipAddr":"IP adresi", "ipAddr":"IP adresi",
"key":"Anahtar", "key":"Anahtar",
"lastFailedLogins":"Son başarısız giriş denemeleri", "lastFailedLogins":"Son başarısız giriş denemeleri",
"lastFailedLoginsCaptionLabel":"Son başarısız girişler",
"lastLogins":"Son girişler", "lastLogins":"Son girişler",
"lastLoginsCaptionLabel":"Son girişler",
"lastName":"Soyad", "lastName":"Soyad",
"linkValidUntil":"Bu mesaj parolanızı sıfırlamak için bir bağlantı içerir, bu bağlantı şu zamana kadar geçerlidir", "linkValidUntil":"Bu mesaj parolanızı sıfırlamak için bir bağlantı içerir, bu bağlantı şu zamana kadar geçerlidir",
"linkValidUntilCertif":"Bu mesaj sertifikanızı sıfırlamak için bir bağlantı içerir, bu bağlantı şu zamana kadar geçerlidir", "linkValidUntilCertif":"Bu mesaj sertifikanızı sıfırlamak için bir bağlantı içerir, bu bağlantı şu zamana kadar geçerlidir",
@ -208,6 +210,7 @@
"noNotification":"Kabul edilen bildirim bulunamadı", "noNotification":"Kabul edilen bildirim bulunamadı",
"notAnEncryptedValue":"Bu şifrelenmiş bir değer değil", "notAnEncryptedValue":"Bu şifrelenmiş bir değer değil",
"notAuthorized":"Bunu yapmak için yetkili değilsiniz", "notAuthorized":"Bunu yapmak için yetkili değilsiniz",
"notAuthorizedAuthLevel":"Bu eylem daha yüksek bir doğrulama seviyesi gerektirir",
"notFound":"Bulunamadı: mevcut olmayan bir sayfaya erişmeyi deniyorsunuz", "notFound":"Bulunamadı: mevcut olmayan bir sayfaya erişmeyi deniyorsunuz",
"noTOTPFound":"TOTP bulunamadi", "noTOTPFound":"TOTP bulunamadi",
"noU2FKeyFound":"U2F anahtarı bulunamadı", "noU2FKeyFound":"U2F anahtarı bulunamadı",

View File

@ -180,7 +180,9 @@
"ipAddr":"Địa chỉ IP", "ipAddr":"Địa chỉ IP",
"key":"Khóa", "key":"Khóa",
"lastFailedLogins":"Lần cuối đăng nhập thất bại", "lastFailedLogins":"Lần cuối đăng nhập thất bại",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"Đăng nhập lần cuối", "lastLogins":"Đăng nhập lần cuối",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"Họ", "lastName":"Họ",
"linkValidUntil":"Thông báo này có chứa liên kết để đặt lại mật khẩu của bạn, liên kết này hợp lệ cho đến khi", "linkValidUntil":"Thông báo này có chứa liên kết để đặt lại mật khẩu của bạn, liên kết này hợp lệ cho đến khi",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this", "notAuthorized":"You're not authorized to do this",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"Không tìm thấy: bạn cố gắng truy cập vào một trang không có sẵn", "notFound":"Không tìm thấy: bạn cố gắng truy cập vào một trang không có sẵn",
"noTOTPFound":"Đăng xuất khỏi các ứng dụng khác", "noTOTPFound":"Đăng xuất khỏi các ứng dụng khác",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -180,7 +180,9 @@
"ipAddr":"IP 地址", "ipAddr":"IP 地址",
"key":"Key", "key":"Key",
"lastFailedLogins":"上次失败的认证", "lastFailedLogins":"上次失败的认证",
"lastFailedLoginsCaptionLabel":"Last failed logins",
"lastLogins":"上次登陆", "lastLogins":"上次登陆",
"lastLoginsCaptionLabel":"Last logins",
"lastName":"姓氏", "lastName":"姓氏",
"linkValidUntil":"此消息包含重置您密码的链接,该链接有效期截至", "linkValidUntil":"此消息包含重置您密码的链接,该链接有效期截至",
"linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ", "linkValidUntilCertif":"This message contains a link to reset your certificate, this link is valid until ",
@ -207,6 +209,7 @@
"noNotification":"None accepted notification found", "noNotification":"None accepted notification found",
"notAnEncryptedValue":"It is not an encrypted value", "notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"您没有权限进行该项操作", "notAuthorized":"您没有权限进行该项操作",
"notAuthorizedAuthLevel":"This action requires a higher authentication level",
"notFound":"无法找到:您请求的网页不存在。", "notFound":"无法找到:您请求的网页不存在。",
"noTOTPFound":"No TOTP found", "noTOTPFound":"No TOTP found",
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",

View File

@ -1,11 +1,12 @@
<TMPL_INCLUDE NAME="header.tpl"> <TMPL_INCLUDE NAME="header.tpl">
<div class="container"> <div class="container">
<div class="message message-positive alert" trspan="choose2f"></div> <div class="message message-<TMPL_VAR NAME="ALERT"> alert" trspan="<TMPL_VAR NAME="MSG">"></div>
<div class="buttons"> <div class="buttons">
<form action="/2fchoice" method="POST"> <form action="/2fchoice" method="POST">
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" /> <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">"> <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
<input type="hidden" id="stayconnected" name="stayconnected" value="<TMPL_VAR NAME="STAYCONNECTED">" />
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" /> <input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
<TMPL_LOOP NAME="MODULES"> <TMPL_LOOP NAME="MODULES">
<button type="submit" name="sf" value="<TMPL_VAR NAME="CODE">" class="mx-3 btn btn-light" role="button"> <button type="submit" name="sf" value="<TMPL_VAR NAME="CODE">" class="mx-3 btn btn-light" role="button">

View File

@ -1,11 +1,11 @@
<TMPL_INCLUDE NAME="header.tpl"> <TMPL_INCLUDE NAME="header.tpl">
<div class="container"> <div class="container">
<div id="color" class="message message-positive alert"> <div id="color" class="message message-<TMPL_VAR NAME="ALERT"> alert">
<TMPL_IF NAME="REG_REQUIRED"> <TMPL_IF NAME="REG_REQUIRED">
<span trspan="2fRegRequired"></span> <span trspan="2fRegRequired"></span>
<TMPL_ELSE> <TMPL_ELSE>
<span id="msg" trspan="choose2f"></span> <span id="msg" trspan="<TMPL_VAR NAME="MSG">"></span>
</TMPL_IF> </TMPL_IF>
</div> </div>
<TMPL_IF NAME="SFDEVICES"> <TMPL_IF NAME="SFDEVICES">
@ -64,6 +64,12 @@
</div> </div>
<div class="buttons"> <div class="buttons">
<TMPL_IF NAME="DISPLAY_UPG">
<a href="<TMPL_VAR NAME="PORTAL_URL">upgradesession?url=<TMPL_VAR NAME="SFREGISTERS_URL">" class="btn btn-success" role="button">
<span class="fa fa-sign-in"></span>
<span trspan="upgradeSession">Upgrade session</span>
</a>
</TMPL_IF>
<a href="<TMPL_VAR NAME="PORTAL_URL">?cancel=1&skin=<TMPL_VAR NAME="SKIN">" class="btn btn-primary" role="button"> <a href="<TMPL_VAR NAME="PORTAL_URL">?cancel=1&skin=<TMPL_VAR NAME="SKIN">" class="btn btn-primary" role="button">
<span class="fa fa-home"></span> <span class="fa fa-home"></span>
<span trspan="goToPortal">Go to portal</span> <span trspan="goToPortal">Go to portal</span>

View File

@ -15,7 +15,7 @@
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<div class="input-group-text"> <div class="input-group-text">
<input type="checkbox" id="stayconnected" name="stayconnected" aria-describedby="stayConnectedLabel" /> <input type="checkbox" id="stayconnected" name="stayconnected" aria-describedby="stayConnectedLabel" <TMPL_IF NAME="ASK_STAYCONNECTED">checked</TMPL_IF> />
</div> </div>
</div> </div>
<p class="form-control"> <p class="form-control">

View File

@ -10,6 +10,7 @@
<div class="form"> <div class="form">
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" /> <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" /> <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
<input type="hidden" id="stayconnected" name="stayconnected" value="<TMPL_VAR NAME="STAYCONNECTED">" />
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" /> <input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">

View File

@ -23,9 +23,9 @@
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><label for="mailfield" class="mb-0"><i class="fa fa-envelope"></i></label></span> <span class="input-group-text"><label for="mail" class="mb-0"><i class="fa fa-envelope"></i></label></span>
</div> </div>
<input id="mailfield" name="mail" type="text" value="<TMPL_VAR NAME="MAIL">" class="form-control" trplaceholder="mail" required /> <input id="mail" name="mail" type="text" value="<TMPL_VAR NAME="MAIL">" class="form-control" trplaceholder="mail" required />
</div> </div>
<TMPL_IF NAME=CAPTCHA_SRC> <TMPL_IF NAME=CAPTCHA_SRC>
@ -118,16 +118,16 @@
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><label for="newpasswordfield" class="mb-0"><i class="fa fa-lock"></i></label></span> <span class="input-group-text"><label for="newpassword" class="mb-0"><i class="fa fa-lock"></i></label></span>
</div> </div>
<input id="newpasswordfield" name="newpassword" type="password" class="form-control" trplaceholder="newPassword" /> <input id="newpassword" name="newpassword" type="password" class="form-control" trplaceholder="newPassword" />
</div> </div>
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><label for="confirmpasswordfield" class="mb-0"><i class="fa fa-lock"></i></label></span> <span class="input-group-text"><label for="confirmpassword" class="mb-0"><i class="fa fa-lock"></i></label></span>
</div> </div>
<input id="confirmpasswordfield" name="confirmpassword" type="password" class="form-control" trplaceholder="confirmPwd" /> <input id="confirmpassword" name="confirmpassword" type="password" class="form-control" trplaceholder="confirmPwd" />
</div> </div>
<TMPL_IF NAME="DISPLAY_GENERATE_PASSWORD"> <TMPL_IF NAME="DISPLAY_GENERATE_PASSWORD">

View File

@ -223,7 +223,7 @@
<div class="col-3"> <div class="col-3">
<img src="<TMPL_VAR NAME="STATIC_PREFIX">common/apps/<TMPL_VAR NAME="applogo">" <img src="<TMPL_VAR NAME="STATIC_PREFIX">common/apps/<TMPL_VAR NAME="applogo">"
class="applogo <TMPL_VAR NAME="appid"> img-fluid" class="applogo <TMPL_VAR NAME="appid"> img-fluid"
alt="<TMPL_VAR NAME="appname">" /> alt="" />
</div> </div>
<div class="col-9"> <div class="col-9">
<TMPL_ELSE> <TMPL_ELSE>

View File

@ -2,6 +2,11 @@
<h3 trspan="<TMPL_VAR NAME="title">"></h3> <h3 trspan="<TMPL_VAR NAME="title">"></h3>
</TMPL_IF> </TMPL_IF>
<table class="info"> <table class="info">
<TMPL_IF NAME="displayError">
<caption trspan="lastFailedLoginsCaptionLabel">Last failed logins</caption>
<TMPL_ELSE>
<caption trspan="lastLoginsCaptionLabel">Last logins</caption>
</TMPL_IF>
<thead> <thead>
<tr> <tr>
<TMPL_IF NAME="displayUser"> <TMPL_IF NAME="displayUser">

View File

@ -10,6 +10,7 @@
<div class="form"> <div class="form">
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" /> <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" /> <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
<input type="hidden" id="stayconnected" name="stayconnected" value="<TMPL_VAR NAME="STAYCONNECTED">" />
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" /> <input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
<div class="input-group mb-3"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">

View File

@ -2,7 +2,7 @@
<main id="menucontent" class="container"> <main id="menucontent" class="container">
<div id="color" class="message message-positive alert"><span id="msg" trspan="yourNewTotpKey"></span></div> <div id="color" class="message message-<TMPL_VAR NAME="ALERT"> alert"><span id="msg" trspan="<TMPL_VAR NAME="MSG">"></span></div>
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">

View File

@ -8,10 +8,11 @@
<TMPL_IF NAME="DATA"> <TMPL_IF NAME="DATA">
<div class="message message-positive alert"><span trspan="touchU2fDevice"></span></div> <div class="message message-positive alert"><span trspan="touchU2fDevice"></span></div>
<form id="verify-form" action="/u2fcheck" method="post"> <form id="verify-form" action="/u2fcheck" method="post">
<input type="hidden" id="verify-data" name="signature" value=""> <input type="hidden" id="verify-data" name="signature" value="" />
<input type="hidden" id="verify-challenge" name="challenge" value=""> <input type="hidden" id="verify-challenge" name="challenge" value="" />
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">"> <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">"> <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
<input type="hidden" id="stayconnected" name="stayconnected" value="<TMPL_VAR NAME="STAYCONNECTED">" />
<input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" /> <input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
</form> </form>
<script type="application/init"> <script type="application/init">

View File

@ -2,7 +2,7 @@
<main id="menucontent" class="container"> <main id="menucontent" class="container">
<div id="color" class="message message-positive alert"><span id="msg" trspan="u2fWelcome"></span></div> <div id="color" class="message message-<TMPL_VAR NAME="ALERT"> alert"><span id="msg" trspan="<TMPL_VAR NAME="MSG">"></span></div>
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">

View File

@ -21,14 +21,15 @@
</div> </div>
<TMPL_ELSE> <TMPL_ELSE>
<form id="verify-form" action="/utotp2fcheck" method="post"> <form id="verify-form" action="/utotp2fcheck" method="post">
<input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">"> <input type="hidden" id="token" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">"> <input type="hidden" id="checkLogins" name="checkLogins" value="<TMPL_VAR NAME="CHECKLOGINS">" />
<input type="hidden" id="stayconnected" name="stayconnected" value="<TMPL_VAR NAME="STAYCONNECTED">" />
<TMPL_IF NAME="DATA"> <TMPL_IF NAME="DATA">
<div class="message message-positive alert"> <div class="message message-positive alert">
<span trspan="touchU2fDeviceOrEnterTotp"></span> <span trspan="touchU2fDeviceOrEnterTotp"></span>
</div> </div>
<input type="hidden" id="verify-data" name="signature" value=""> <input type="hidden" id="verify-data" name="signature" value="" />
<input type="hidden" id="verify-challenge" name="challenge" value=""> <input type="hidden" id="verify-challenge" name="challenge" value="" />
<script type="application/init"> <script type="application/init">
<TMPL_VAR NAME="DATA"> <TMPL_VAR NAME="DATA">
</script> </script>

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