lemonldap-ng/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/_WebForm.pm

192 lines
5.0 KiB
Perl
Raw Normal View History

2016-03-30 07:47:38 +02:00
##@file
# Web form authentication backend file
##@class
# Web form authentication backend class
package Lemonldap::NG::Portal::Auth::_WebForm;
use strict;
use Mouse;
2017-01-24 23:05:07 +01:00
use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_NOTOKEN
PE_FORMEMPTY
PE_FIRSTACCESS
2019-03-07 18:22:16 +01:00
PE_CAPTCHAEMPTY
PE_CAPTCHAERROR
PE_TOKENEXPIRED
PE_MALFORMEDUSER
PE_PASSWORDFORMEMPTY
2017-01-24 23:05:07 +01:00
);
2016-03-30 07:47:38 +02:00
2022-02-01 16:33:08 +01:00
our $VERSION = '2.0.14';
2016-03-30 07:47:38 +02:00
extends qw(
Lemonldap::NG::Portal::Main::Auth
Lemonldap::NG::Portal::Lib::_tokenRule
);
2016-03-30 07:47:38 +02:00
2016-12-01 23:25:05 +01:00
has authnLevel => (
is => 'rw',
lazy => 1,
2016-12-01 23:25:05 +01:00
builder => sub {
my $conf = $_[0]->{conf};
return ( $conf->{portal} =~ /^https/ ? 2 : 1 );
},
);
2017-01-24 23:05:07 +01:00
has captcha => ( is => 'rw' );
has ott => ( is => 'rw' );
2016-06-09 20:40:20 +02:00
# INITIALIZATION
2016-03-30 07:47:38 +02:00
sub init {
2019-04-05 17:24:07 +02:00
my $self = shift;
2019-04-03 23:28:45 +02:00
if ( $self->{conf}->{captcha_login_enabled} ) {
$self->captcha( $self->p->loadModule('::Lib::Captcha') ) or return 0;
}
else {
$self->ott( $self->p->loadModule('::Lib::OneTimeToken') ) or return 0;
$self->ott->timeout( $self->conf->{formTimeout} );
2017-01-24 23:05:07 +01:00
}
return 1;
2016-03-30 07:47:38 +02:00
}
2016-06-09 20:40:20 +02:00
# RUNNING METHODS
# Read username and password from POST data
2016-03-30 07:47:38 +02:00
sub extractFormInfo {
2016-04-29 09:27:26 +02:00
my ( $self, $req ) = @_;
2019-03-07 18:22:16 +01:00
2019-03-06 23:08:22 +01:00
if ( $req->param('user') ) {
unless ( $req->param('user') =~ /$self->{conf}->{userControl}/o ) {
$self->setSecurity($req);
return PE_MALFORMEDUSER;
}
}
2016-03-30 07:47:38 +02:00
# Detect first access and empty forms
my $defUser = defined $req->param('user');
my $defPassword = defined $req->param('password');
my $defOldPassword = defined $req->param('oldpassword');
2017-01-24 23:05:07 +01:00
my $res = PE_OK;
2016-03-30 07:47:38 +02:00
# 1. No user defined at all -> first access
# _pwdCheck is a workaround to make CheckUser work while using a GET
unless ( $defUser
and ( uc( $req->method ) eq "POST" or $req->data->{_pwdCheck} ) )
{
2017-01-24 23:05:07 +01:00
$res = PE_FIRSTACCESS;
}
2016-03-30 07:47:38 +02:00
# 2. If user and password defined -> login form
elsif ( $defUser and $defPassword ) {
2017-01-24 23:05:07 +01:00
$res = PE_FORMEMPTY
2019-03-07 18:22:16 +01:00
unless ( ( $req->{user} = $req->param('user') )
&& ( $req->data->{password} = $req->param('password') ) );
2016-03-30 07:47:38 +02:00
}
# 3. If user and oldpassword defined -> password form
elsif ( $defUser and $defOldPassword ) {
2017-01-24 23:05:07 +01:00
$res = PE_PASSWORDFORMEMPTY
2022-02-16 17:43:29 +01:00
unless (
( $req->{user} = $req->param('user') )
&& ( $req->data->{oldpassword} = $req->param('oldpassword') )
&& ( $req->data->{newpassword} = $req->param('newpassword') )
2019-03-07 18:22:16 +01:00
&& ( $req->data->{confirmpassword} =
2022-02-16 17:43:29 +01:00
$req->param('confirmpassword') )
);
2016-03-30 07:47:38 +02:00
}
2017-01-24 23:05:07 +01:00
# If form seems empty
if ( $res != PE_OK ) {
$self->setSecurity($req);
2017-01-24 23:05:07 +01:00
return $res;
}
# Security: check for captcha or token
if ( not $req->data->{'skipToken'}
and ( $self->captcha or $self->ottRule->( $req, {} ) ) )
{
2017-01-24 23:05:07 +01:00
my $token;
unless ( $token = $req->param('token') or $self->captcha ) {
$self->userLogger->error('Authentication tried without token');
$self->ott->setToken($req);
2017-01-24 23:05:07 +01:00
return PE_NOTOKEN;
}
2019-04-03 23:28:45 +02:00
2017-01-24 23:05:07 +01:00
if ( $self->captcha ) {
my $code = $req->param('captcha');
unless ($code) {
2017-01-26 22:42:42 +01:00
$self->captcha->setCaptcha($req);
2017-01-24 23:05:07 +01:00
return PE_CAPTCHAEMPTY;
2016-03-30 07:47:38 +02:00
}
2017-01-24 23:05:07 +01:00
unless ( $self->captcha->validateCaptcha( $token, $code ) ) {
2017-01-26 22:42:42 +01:00
$self->captcha->setCaptcha($req);
2017-02-19 12:51:58 +01:00
$self->userLogger->warn(
"Captcha failed: wrong or expired code");
2016-03-30 07:47:38 +02:00
return PE_CAPTCHAERROR;
}
2017-02-15 07:41:50 +01:00
$self->logger->debug("Captcha code verified");
2017-01-24 23:05:07 +01:00
}
2019-04-05 17:24:07 +02:00
elsif ( $self->ottRule->( $req, {} ) ) {
unless ( $req->data->{tokenVerified}
or $self->ott->getToken($token) )
{
2017-01-26 22:42:42 +01:00
$self->ott->setToken($req);
$self->userLogger->warn('Token expired');
2017-01-24 23:05:07 +01:00
return PE_TOKENEXPIRED;
2016-03-30 07:47:38 +02:00
}
$req->data->{tokenVerified} = 1;
2016-03-30 07:47:38 +02:00
}
}
# Other parameters
$req->data->{timezone} = $req->param('timezone');
2016-03-30 07:47:38 +02:00
return PE_OK;
2016-03-30 07:47:38 +02:00
}
# Set password in session data if wanted.
2016-03-30 07:47:38 +02:00
sub setAuthSessionInfo {
2016-05-04 13:38:49 +02:00
my ( $self, $req ) = @_;
2016-03-30 07:47:38 +02:00
# authenticationLevel
2016-12-02 06:47:38 +01:00
$req->{sessionInfo}->{authenticationLevel} = $self->authnLevel;
2016-03-30 07:47:38 +02:00
# Store submitted password if set in configuration
# WARNING: it can be a security hole
if ( $self->conf->{storePassword} ) {
$req->{sessionInfo}->{'_password'} = $req->data->{'newpassword'}
2019-03-07 18:22:16 +01:00
|| $req->data->{'password'};
2016-03-30 07:47:38 +02:00
}
# Store user timezone
2016-12-02 06:47:38 +01:00
$req->{sessionInfo}->{'_timezone'} = $self->{'timezone'};
2016-03-30 07:47:38 +02:00
return PE_OK;
2016-03-30 07:47:38 +02:00
}
2016-05-02 12:30:23 +02:00
# @return display type
sub getDisplayType {
return "standardform";
}
sub setSecurity {
my ( $self, $req ) = @_;
2021-09-10 12:22:30 +02:00
return if $req->data->{skipToken};
# If captcha is enable, prepare it
if ( $self->captcha ) {
$self->captcha->setCaptcha($req);
}
# Else get token
2019-04-05 17:24:07 +02:00
elsif ( $self->ottRule->( $req, {} ) ) {
$self->ott->setToken($req);
}
}
2016-03-30 07:47:38 +02:00
1;