Captcha and token in progress (#1140)
This commit is contained in:
parent
81b47b7988
commit
234551387f
|
@ -23,9 +23,9 @@ use constant HANDLERSECTION => "handler";
|
|||
use constant MANAGERSECTION => "manager";
|
||||
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
|
||||
use constant APPLYSECTION => "apply";
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va))r|ca(?:s(?:StorageOption|Attribute)|ptchaStorageOption)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|re(?:moteGlobalStorageOption|loadUrl)|CAS_proxiedService|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:uthChoiceModules|pplicationList)|v(?:hostOptions|irtualHost))$/;
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va))r|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|re(?:moteGlobalStorageOption|loadUrl)|cas(?:StorageOption|Attribute)|CAS_proxiedService|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:uthChoiceModules|pplicationList)|v(?:hostOptions|irtualHost))$/;
|
||||
|
||||
our @sessionTypes = ( 'captcha', 'remoteGlobal', 'cas', 'global', 'localSession', 'persistent', 'saml', 'oidc' );
|
||||
our @sessionTypes = ( 'remoteGlobal', 'cas', 'global', 'localSession', 'persistent', 'saml', 'oidc' );
|
||||
|
||||
sub NO {qr/^(?:off|no|0)?$/i}
|
||||
|
||||
|
|
|
@ -20,25 +20,21 @@ sub defaultValues {
|
|||
'browserIdAuthnLevel' => 1,
|
||||
'captcha_register_enabled' => 1,
|
||||
'captcha_size' => 6,
|
||||
'captchaStorage' => 'Apache::Session::File',
|
||||
'captchaStorageOptions' => {
|
||||
'Directory' => '/var/lib/lemonldap-ng/captcha/'
|
||||
},
|
||||
'CAS_authnLevel' => 1,
|
||||
'CAS_pgtFile' => '/tmp/pgt.txt',
|
||||
'casAccessControlPolicy' => 'none',
|
||||
'checkXSS' => 1,
|
||||
'confirmFormMethod' => 'post',
|
||||
'cookieName' => 'lemonldap',
|
||||
'cspConnect' => '\'self\'',
|
||||
'cspDefault' => '\'self\'',
|
||||
'cspFont' => '\'self\'',
|
||||
'cspImg' => '\'self\'',
|
||||
'cspScript' => '\'self\'',
|
||||
'cspStyle' => '\'self\'',
|
||||
'dbiAuthnLevel' => 2,
|
||||
'dbiExportedVars' => {},
|
||||
'demoExportedVars' => {
|
||||
'CAS_authnLevel' => 1,
|
||||
'CAS_pgtFile' => '/tmp/pgt.txt',
|
||||
'casAccessControlPolicy' => 'none',
|
||||
'checkXSS' => 1,
|
||||
'confirmFormMethod' => 'post',
|
||||
'cookieName' => 'lemonldap',
|
||||
'cspConnect' => '\'self\'',
|
||||
'cspDefault' => '\'self\'',
|
||||
'cspFont' => '\'self\'',
|
||||
'cspImg' => '\'self\'',
|
||||
'cspScript' => '\'self\'',
|
||||
'cspStyle' => '\'self\'',
|
||||
'dbiAuthnLevel' => 2,
|
||||
'dbiExportedVars' => {},
|
||||
'demoExportedVars' => {
|
||||
'cn' => 'cn',
|
||||
'mail' => 'mail',
|
||||
'uid' => 'uid'
|
||||
|
@ -50,6 +46,7 @@ sub defaultValues {
|
|||
'facebookAuthnLevel' => 1,
|
||||
'facebookExportedVars' => {},
|
||||
'failedLoginNumber' => 5,
|
||||
'formTimeout' => 120,
|
||||
'globalStorage' => 'Apache::Session::File',
|
||||
'globalStorageOptions' => {
|
||||
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
||||
|
@ -182,6 +179,7 @@ sub defaultValues {
|
|||
'http://auth.example.com/Lemonldap/NG/Common/CGI/SOAPService',
|
||||
'proxy' => 'http://auth.example.com/index.pl/sessions'
|
||||
},
|
||||
'requireToken' => 1,
|
||||
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' =>
|
||||
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
|
||||
'samlAuthnContextMapKerberos' => 4,
|
||||
|
|
|
@ -20,7 +20,7 @@ our $specialNodeHash = {
|
|||
};
|
||||
|
||||
our $doubleHashKeys = 'issuerDBGetParameters';
|
||||
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wpSslOpt)|ca(?:s(?:StorageOption|Attribute)|ptchaStorageOption)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|re(?:moteGlobalStorageOption|loadUrl)|CAS_proxiedService|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember)|a(?:uthChoiceModules|pplicationList))';
|
||||
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wpSslOpt)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|re(?:moteGlobalStorageOption|loadUrl)|cas(?:StorageOption|Attribute)|CAS_proxiedService|macro)s|o(?:idcS(?:erviceMetaDataAuthnContext|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember)|a(?:uthChoiceModules|pplicationList))';
|
||||
our $specialNodeKeys = '(?:(?:saml(?:ID|S)|oidc[OR])PMetaDataNode|virtualHost)s';
|
||||
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|S(?:toreIDToken|cope)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
|
||||
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|(?:RedirectUri|ExtraClaim)s|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|UserIDAttr)|ExportedVars)';
|
||||
|
|
|
@ -599,16 +599,6 @@ sub attributes {
|
|||
'default' => 6,
|
||||
'type' => 'int'
|
||||
},
|
||||
'captchaStorage' => {
|
||||
'default' => 'Apache::Session::File',
|
||||
'type' => 'PerlModule'
|
||||
},
|
||||
'captchaStorageOptions' => {
|
||||
'default' => {
|
||||
'Directory' => '/var/lib/lemonldap-ng/captcha/'
|
||||
},
|
||||
'type' => 'keyTextContainer'
|
||||
},
|
||||
'CAS_authnLevel' => {
|
||||
'default' => 1,
|
||||
'type' => 'int'
|
||||
|
@ -883,6 +873,10 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
|
|||
'default' => 5,
|
||||
'type' => 'int'
|
||||
},
|
||||
'formTimeout' => {
|
||||
'default' => 120,
|
||||
'type' => 'int'
|
||||
},
|
||||
'globalStorage' => {
|
||||
'default' => 'Apache::Session::File',
|
||||
'type' => 'PerlModule'
|
||||
|
@ -2097,6 +2091,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'remotePortal' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'requireToken' => {
|
||||
'default' => 1,
|
||||
'type' => 'bool'
|
||||
},
|
||||
'restConfigServer' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
|
|
|
@ -425,6 +425,16 @@ sub attributes {
|
|||
},
|
||||
|
||||
# Security
|
||||
formTimeout => {
|
||||
default => 120,
|
||||
type => 'int',
|
||||
documentation => 'Token timeout for forms',
|
||||
},
|
||||
requireToken => {
|
||||
default => 1,
|
||||
type => 'bool',
|
||||
documentation => 'Enable token for forms',
|
||||
},
|
||||
cda => {
|
||||
default => 0,
|
||||
type => 'bool',
|
||||
|
@ -694,19 +704,6 @@ sub attributes {
|
|||
documentation => 'Captcha size',
|
||||
},
|
||||
|
||||
#captcha_data
|
||||
#captcha_output
|
||||
captchaStorage => {
|
||||
type => 'PerlModule',
|
||||
default => 'Apache::Session::File',
|
||||
documentation => 'Captcha backend module',
|
||||
},
|
||||
captchaStorageOptions => {
|
||||
type => 'keyTextContainer',
|
||||
default => { 'Directory' => '/var/lib/lemonldap-ng/captcha/', },
|
||||
documentation => 'Captcha backend module options',
|
||||
},
|
||||
|
||||
# Variables
|
||||
exportedVars => {
|
||||
type => 'keyTextContainer',
|
||||
|
|
|
@ -91,8 +91,6 @@ sub tree {
|
|||
'captcha_mail_enabled',
|
||||
'captcha_register_enabled',
|
||||
'captcha_size',
|
||||
'captchaStorage',
|
||||
'captchaStorageOptions'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -615,7 +613,9 @@ sub tree {
|
|||
'cspScript', 'cspStyle',
|
||||
'cspConnect', 'cspFont',
|
||||
]
|
||||
}
|
||||
},
|
||||
'requireToken',
|
||||
'formTimeout',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -93,8 +93,6 @@
|
|||
"captcha_mail_enabled": "Activation in password reset by mail form",
|
||||
"captcha_register_enabled": "Activation in register form",
|
||||
"captcha_size": "Size",
|
||||
"captchaStorage": "Captcha module name",
|
||||
"captchaStorageOptions": "Captcha module options",
|
||||
"CAS_authnLevel": "Authentication level",
|
||||
"CAS_CAFile": "CA file",
|
||||
"CAS_gateway": "Gateway authentication",
|
||||
|
@ -202,6 +200,7 @@
|
|||
"forceSave": "Force save",
|
||||
"format": "Format",
|
||||
"formReplay": "Form replay",
|
||||
"formTimeout": "Form timeout",
|
||||
"forms": "Forms",
|
||||
"friendlyName": "Friendly name",
|
||||
"generalParameters": "General Parameters",
|
||||
|
@ -556,6 +555,7 @@
|
|||
"remoteParams": "Remote parameters",
|
||||
"remotePortal": "Portal URL",
|
||||
"replaceByFile": "Replace by file",
|
||||
"requireToken": "Require token for forms",
|
||||
"restConfigServer": "REST configuration server",
|
||||
"restSessionServer": "REST session server",
|
||||
"restore": "Restore",
|
||||
|
|
|
@ -93,8 +93,6 @@
|
|||
"captcha_mail_enabled": "Activation dans le formulaire de réinitialisation par mail",
|
||||
"captcha_register_enabled": "Activation dans le formulaire de création de compte",
|
||||
"captcha_size": "Taille",
|
||||
"captchaStorage": "Nom du module de stockage",
|
||||
"captchaStorageOptions": "Options du module de stockage",
|
||||
"CAS_authnLevel": "Niveau d'authentification",
|
||||
"CAS_CAFile": "Fichier d'AC",
|
||||
"CAS_gateway": "Authentification transparente",
|
||||
|
@ -202,6 +200,7 @@
|
|||
"forceSave": "Forcer la sauvegarde",
|
||||
"format": "Format",
|
||||
"formReplay": "Rejeu de formulaires",
|
||||
"formTimeout": "Délai de validation pour les formulaires",
|
||||
"forms": "Formulaires",
|
||||
"friendlyName": "Nom alternatif",
|
||||
"generalParameters": "Paramètres généraux",
|
||||
|
@ -556,6 +555,7 @@
|
|||
"remoteParams": "Paramètres Remote",
|
||||
"remotePortal": "URL du portail",
|
||||
"replaceByFile": "Remplacer par le fichier",
|
||||
"requireToken": "Exige un jeton pour les formulaires",
|
||||
"restConfigServer": "Serveur de configurations REST",
|
||||
"restSessionServer": "Serveur de sessions REST",
|
||||
"restore": "Restaurer",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -7,8 +7,16 @@ package Lemonldap::NG::Portal::Auth::_WebForm;
|
|||
|
||||
use strict;
|
||||
use Mouse;
|
||||
use Lemonldap::NG::Portal::Main::Constants
|
||||
qw(PE_OK PE_FIRSTACCESS PE_FORMEMPTY PE_PASSWORDFORMEMPTY PE_CAPTCHAEMPTY PE_CAPTCHAERROR);
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||
PE_CAPTCHAEMPTY
|
||||
PE_CAPTCHAERROR
|
||||
PE_FIRSTACCESS
|
||||
PE_FORMEMPTY
|
||||
PE_NOTOKEN
|
||||
PE_OK
|
||||
PE_PASSWORDFORMEMPTY
|
||||
PE_TOKENEXPIRED
|
||||
);
|
||||
|
||||
our $VERSION = '2.0.0';
|
||||
|
||||
|
@ -22,10 +30,24 @@ has authnLevel => (
|
|||
},
|
||||
);
|
||||
|
||||
has captcha => ( is => 'rw' );
|
||||
has ott => ( is => 'rw' );
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
sub init {
|
||||
1;
|
||||
if ( $_[0]->{conf}->{captcha_login_enabled} ) {
|
||||
$_[0]->captcha(
|
||||
$_[0]->p->loadModule('Lemonldap::NG::Portal::Lib::Captcha') )
|
||||
or return 0;
|
||||
}
|
||||
elsif ( $_[0]->{conf}->{requireToken} ) {
|
||||
$_[0]->ott(
|
||||
$_[0]->p->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken') )
|
||||
or return 0;
|
||||
$_[0]->ott->timeout( $_[0]->conf->{formTimeout} );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# RUNNING METHODS
|
||||
|
@ -34,30 +56,27 @@ sub init {
|
|||
sub extractFormInfo {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
# Init captcha
|
||||
if ( $self->conf->{captcha_login_enabled} ) {
|
||||
eval { $self->initCaptcha(); };
|
||||
$self->lmLog( "Can't init captcha: $@", "error" ) if $@;
|
||||
}
|
||||
|
||||
# Detect first access and empty forms
|
||||
my $defUser = defined $req->param('user');
|
||||
my $defPassword = defined $req->param('password');
|
||||
my $defOldPassword = defined $req->param('oldpassword');
|
||||
my $res = PE_OK;
|
||||
|
||||
# 1. No user defined at all -> first access
|
||||
return PE_FIRSTACCESS unless $defUser;
|
||||
unless ($defUser) {
|
||||
$res = PE_FIRSTACCESS;
|
||||
}
|
||||
|
||||
# 2. If user and password defined -> login form
|
||||
if ( $defUser && $defPassword ) {
|
||||
return PE_FORMEMPTY
|
||||
elsif ( $defUser && $defPassword ) {
|
||||
$res = PE_FORMEMPTY
|
||||
unless ( ( $req->{user} = $req->param('user') )
|
||||
&& ( $req->datas->{password} = $req->param('password') ) );
|
||||
}
|
||||
|
||||
# 3. If user and oldpassword defined -> password form
|
||||
if ( $defUser && $defOldPassword ) {
|
||||
return PE_PASSWORDFORMEMPTY
|
||||
elsif ( $defUser && $defOldPassword ) {
|
||||
$res = PE_PASSWORDFORMEMPTY
|
||||
unless ( ( $req->{user} = $req->param('user') )
|
||||
&& ( $req->datas->{oldpassword} = $req->param('oldpassword') )
|
||||
&& ( $req->datas->{newpassword} = $req->param('newpassword') )
|
||||
|
@ -65,49 +84,48 @@ sub extractFormInfo {
|
|||
$req->param('confirmpassword') ) );
|
||||
}
|
||||
|
||||
# 4. Captcha for login form
|
||||
if ( $self->conf->{captcha_login_enabled} && $defUser && $defPassword ) {
|
||||
$req->datas->{captcha_user_code} = $req->param('captcha_user_code');
|
||||
$req->datas->{captcha_check_code} = $req->param('captcha_code');
|
||||
# If form seems empty
|
||||
if ( $res != PE_OK ) {
|
||||
|
||||
unless ( $req->datas->{captcha_user_code}
|
||||
&& $req->datas->{captcha_check_code} )
|
||||
{
|
||||
$self->lmLog( "Captcha not filled", 'warn' );
|
||||
return PE_CAPTCHAEMPTY;
|
||||
# If captcha is enable, prepare it
|
||||
if ( $self->captcha ) {
|
||||
$self->setCaptcha($req);
|
||||
}
|
||||
|
||||
$self->lmLog(
|
||||
"Captcha data received: "
|
||||
. $req->datas->{captcha_user_code} . " and "
|
||||
. $req->datas->{captcha_check_code},
|
||||
'debug'
|
||||
);
|
||||
# Else get token
|
||||
elsif ( $self->ott ) {
|
||||
$self->setToken($req);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
# Check captcha
|
||||
my $captcha_result = $self->checkCaptcha(
|
||||
$req->datas->{captcha_user_code},
|
||||
$req->datas->{captcha_check_code}
|
||||
);
|
||||
|
||||
if ( $captcha_result != 1 ) {
|
||||
if ( $captcha_result == -3
|
||||
or $captcha_result == -2 )
|
||||
{
|
||||
$self->lmLog( "Captcha failed: wrong code", 'warn' );
|
||||
# Security: check for captcha or token
|
||||
if ( $self->captcha or $self->ott ) {
|
||||
my $token;
|
||||
unless ( $token = $req->param('token') ) {
|
||||
$self->p->userError('Authentication tried without token');
|
||||
return PE_NOTOKEN;
|
||||
}
|
||||
if ( $self->captcha ) {
|
||||
my $code = $req->param('captcha');
|
||||
unless ($code) {
|
||||
$self->setCaptcha($req);
|
||||
return PE_CAPTCHAEMPTY;
|
||||
}
|
||||
unless ( $self->captcha->validateCaptcha( $token, $code ) ) {
|
||||
$self->setCaptcha($req);
|
||||
$self->p->userNotice("Captcha failed: wrong or expired code");
|
||||
return PE_CAPTCHAERROR;
|
||||
}
|
||||
elsif ( $captcha_result == 0 ) {
|
||||
$self->lmLog( "Captcha failed: code not checked (file error)",
|
||||
'warn' );
|
||||
return PE_CAPTCHAERROR;
|
||||
}
|
||||
elsif ( $captcha_result == -1 ) {
|
||||
$self->lmLog( "Captcha failed: code has expired", 'warn' );
|
||||
return PE_CAPTCHAERROR;
|
||||
$self->lmLog( "Captcha code verified", 'debug' );
|
||||
}
|
||||
elsif ( $self->ott ) {
|
||||
unless ( $self->ott->getToken($token) ) {
|
||||
$self->setToken($req);
|
||||
$self->p->userNotice('Token expired');
|
||||
return PE_TOKENEXPIRED;
|
||||
}
|
||||
}
|
||||
$self->lmLog( "Captcha code verified", 'debug' );
|
||||
}
|
||||
|
||||
# Other parameters
|
||||
|
@ -141,4 +159,18 @@ sub getDisplayType {
|
|||
return "standardform";
|
||||
}
|
||||
|
||||
sub setCaptcha {
|
||||
my ( $self, $req ) = @_;
|
||||
my ( $token, $image ) = $self->captcha->getCaptcha;
|
||||
$self->lmLog( 'Prepare captcha', 'debug' );
|
||||
$req->token($token);
|
||||
$req->captcha($image);
|
||||
}
|
||||
|
||||
sub setToken {
|
||||
my ( $self, $req ) = @_;
|
||||
$self->lmLog( 'Prepare token', 'debug' );
|
||||
$req->token( $self->ott->createToken );
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -83,6 +83,8 @@ use constant {
|
|||
PE_REGISTERFIRSTACCESS => 78,
|
||||
PE_REGISTERFORMEMPTY => 79,
|
||||
PE_REGISTERALREADYEXISTS => 80,
|
||||
PE_NOTOKEN => 81,
|
||||
PE_TOKENEXPIRED => 82,
|
||||
};
|
||||
|
||||
# EXPORTER PARAMETERS
|
||||
|
@ -107,7 +109,7 @@ our @EXPORT_OK = qw( PE_SENDRESPONSE PE_INFO PE_REDIRECT PE_DONE PE_OK
|
|||
PE_MAILNOTFOUND PE_PASSWORDFIRSTACCESS PE_MAILCONFIRMOK
|
||||
PE_MUST_SUPPLY_OLD_PASSWORD PE_FORBIDDENIP PE_CAPTCHAERROR PE_CAPTCHAEMPTY
|
||||
PE_REGISTERFIRSTACCESS PE_REGISTERFORMEMPTY PE_REGISTERALREADYEXISTS
|
||||
HANDLER
|
||||
PE_NOTOKEN PE_TOKENEXPIRED HANDLER
|
||||
);
|
||||
our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK, 'import' ], );
|
||||
|
||||
|
|
|
@ -56,6 +56,14 @@ has menuError => ( is => 'rw' );
|
|||
# Frame flag (used by Run to not send Content-Security-Policy header)
|
||||
has frame => ( is => 'rw' );
|
||||
|
||||
# Security
|
||||
#
|
||||
# Captcha
|
||||
has captcha => ( is => 'rw' );
|
||||
|
||||
# Token
|
||||
has token => ( is => 'rw' );
|
||||
|
||||
# Error type
|
||||
sub error_type {
|
||||
my $req = shift;
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
"generateModule": "Lemonldap::NG::Common::Apache::Session::Generate::SHA256"
|
||||
},
|
||||
"reloadUrls": {},
|
||||
"requireToken": 0,
|
||||
"userDB": "Demo",
|
||||
"whatToTrace": "_whatToTrace"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user