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

192 lines
5.0 KiB
Perl

##@file
# Web form authentication backend file
##@class
# Web form authentication backend class
package Lemonldap::NG::Portal::Auth::_WebForm;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_NOTOKEN
PE_FORMEMPTY
PE_FIRSTACCESS
PE_CAPTCHAEMPTY
PE_CAPTCHAERROR
PE_TOKENEXPIRED
PE_MALFORMEDUSER
PE_PASSWORDFORMEMPTY
);
our $VERSION = '2.0.14';
extends qw(
Lemonldap::NG::Portal::Main::Auth
Lemonldap::NG::Portal::Lib::_tokenRule
);
has authnLevel => (
is => 'rw',
lazy => 1,
builder => sub {
my $conf = $_[0]->{conf};
return ( $conf->{portal} =~ /^https/ ? 2 : 1 );
},
);
has captcha => ( is => 'rw' );
has ott => ( is => 'rw' );
# INITIALIZATION
sub init {
my $self = shift;
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} );
}
return 1;
}
# RUNNING METHODS
# Read username and password from POST data
sub extractFormInfo {
my ( $self, $req ) = @_;
if ( $req->param('user') ) {
unless ( $req->param('user') =~ /$self->{conf}->{userControl}/o ) {
$self->setSecurity($req);
return PE_MALFORMEDUSER;
}
}
# 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
# _pwdCheck is a workaround to make CheckUser work while using a GET
unless ( $defUser
and ( uc( $req->method ) eq "POST" or $req->data->{_pwdCheck} ) )
{
$res = PE_FIRSTACCESS;
}
# 2. If user and password defined -> login form
elsif ( $defUser and $defPassword ) {
$res = PE_FORMEMPTY
unless ( ( $req->{user} = $req->param('user') )
&& ( $req->data->{password} = $req->param('password') ) );
}
# 3. If user and oldpassword defined -> password form
elsif ( $defUser and $defOldPassword ) {
$res = PE_PASSWORDFORMEMPTY
unless (
( $req->{user} = $req->param('user') )
&& ( $req->data->{oldpassword} = $req->param('oldpassword') )
&& ( $req->data->{newpassword} = $req->param('newpassword') )
&& ( $req->data->{confirmpassword} =
$req->param('confirmpassword') )
);
}
# If form seems empty
if ( $res != PE_OK ) {
$self->setSecurity($req);
return $res;
}
# Security: check for captcha or token
if ( not $req->data->{'skipToken'}
and ( $self->captcha or $self->ottRule->( $req, {} ) ) )
{
my $token;
unless ( $token = $req->param('token') or $self->captcha ) {
$self->userLogger->error('Authentication tried without token');
$self->ott->setToken($req);
return PE_NOTOKEN;
}
if ( $self->captcha ) {
my $code = $req->param('captcha');
unless ($code) {
$self->captcha->setCaptcha($req);
return PE_CAPTCHAEMPTY;
}
unless ( $self->captcha->validateCaptcha( $token, $code ) ) {
$self->captcha->setCaptcha($req);
$self->userLogger->warn(
"Captcha failed: wrong or expired code");
return PE_CAPTCHAERROR;
}
$self->logger->debug("Captcha code verified");
}
elsif ( $self->ottRule->( $req, {} ) ) {
unless ( $req->data->{tokenVerified}
or $self->ott->getToken($token) )
{
$self->ott->setToken($req);
$self->userLogger->warn('Token expired');
return PE_TOKENEXPIRED;
}
$req->data->{tokenVerified} = 1;
}
}
# Other parameters
$req->data->{timezone} = $req->param('timezone');
return PE_OK;
}
# Set password in session data if wanted.
sub setAuthSessionInfo {
my ( $self, $req ) = @_;
# authenticationLevel
$req->{sessionInfo}->{authenticationLevel} = $self->authnLevel;
# Store submitted password if set in configuration
# WARNING: it can be a security hole
if ( $self->conf->{storePassword} ) {
$req->{sessionInfo}->{'_password'} = $req->data->{'newpassword'}
|| $req->data->{'password'};
}
# Store user timezone
$req->{sessionInfo}->{'_timezone'} = $self->{'timezone'};
return PE_OK;
}
# @return display type
sub getDisplayType {
return "standardform";
}
sub setSecurity {
my ( $self, $req ) = @_;
return if $req->data->{skipToken};
# If captcha is enable, prepare it
if ( $self->captcha ) {
$self->captcha->setCaptcha($req);
}
# Else get token
elsif ( $self->ottRule->( $req, {} ) ) {
$self->ott->setToken($req);
}
}
1;