_WebForm.pm 4.6 KB
Newer Older
Yadd's avatar
Yadd committed
1 2 3 4 5 6 7 8 9
##@file
# Web form authentication backend file

##@class
# Web form authentication backend class
package Lemonldap::NG::Portal::Auth::_WebForm;

use strict;
use Mouse;
Yadd's avatar
Yadd committed
10 11 12 13 14 15 16 17 18 19
use Lemonldap::NG::Portal::Main::Constants qw(
  PE_CAPTCHAEMPTY
  PE_CAPTCHAERROR
  PE_FIRSTACCESS
  PE_FORMEMPTY
  PE_NOTOKEN
  PE_OK
  PE_PASSWORDFORMEMPTY
  PE_TOKENEXPIRED
);
Yadd's avatar
Yadd committed
20 21 22

our $VERSION = '2.0.0';

Yadd's avatar
Yadd committed
23
extends 'Lemonldap::NG::Portal::Auth::Base';
Yadd's avatar
Yadd committed
24

Yadd's avatar
Yadd committed
25 26 27 28 29 30 31 32
has authnLevel => (
    is      => 'rw',
    builder => sub {
        my $conf = $_[0]->{conf};
        return ( $conf->{portal} =~ /^https/ ? 2 : 1 );
    },
);

Yadd's avatar
Yadd committed
33 34 35
has captcha => ( is => 'rw' );
has ott     => ( is => 'rw' );

Yadd's avatar
Yadd committed
36 37
# INITIALIZATION

Yadd's avatar
Yadd committed
38
sub init {
Yadd's avatar
Yadd committed
39 40 41 42 43 44 45 46 47 48 49 50
    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;
Yadd's avatar
Yadd committed
51 52
}

Yadd's avatar
Yadd committed
53 54
# RUNNING METHODS

Yadd's avatar
Yadd committed
55 56
# Read username and password from POST datas
sub extractFormInfo {
Yadd's avatar
Tidy  
Yadd committed
57
    my ( $self, $req ) = @_;
Yadd's avatar
Yadd committed
58 59 60 61 62

    # Detect first access and empty forms
    my $defUser        = defined $req->param('user');
    my $defPassword    = defined $req->param('password');
    my $defOldPassword = defined $req->param('oldpassword');
Yadd's avatar
Yadd committed
63
    my $res            = PE_OK;
Yadd's avatar
Yadd committed
64 65

    # 1. No user defined at all -> first access
Yadd's avatar
Yadd committed
66 67 68
    unless ($defUser) {
        $res = PE_FIRSTACCESS;
    }
Yadd's avatar
Yadd committed
69 70

    # 2. If user and password defined -> login form
Yadd's avatar
Yadd committed
71 72
    elsif ( $defUser && $defPassword ) {
        $res = PE_FORMEMPTY
Yadd's avatar
Yadd committed
73
          unless ( ( $req->{user} = $req->param('user') )
Yadd's avatar
Yadd committed
74
            && ( $req->datas->{password} = $req->param('password') ) );
Yadd's avatar
Yadd committed
75 76 77
    }

    # 3. If user and oldpassword defined -> password form
Yadd's avatar
Yadd committed
78 79
    elsif ( $defUser && $defOldPassword ) {
        $res = PE_PASSWORDFORMEMPTY
Yadd's avatar
Yadd committed
80
          unless ( ( $req->{user} = $req->param('user') )
Yadd's avatar
Yadd committed
81 82 83 84
            && ( $req->datas->{oldpassword} = $req->param('oldpassword') )
            && ( $req->datas->{newpassword} = $req->param('newpassword') )
            && ( $req->datas->{confirmpassword} =
                $req->param('confirmpassword') ) );
Yadd's avatar
Yadd committed
85 86
    }

Yadd's avatar
Yadd committed
87 88
    # If form seems empty
    if ( $res != PE_OK ) {
Yadd's avatar
Yadd committed
89

Yadd's avatar
Yadd committed
90 91 92
        # If captcha is enable, prepare it
        if ( $self->captcha ) {
            $self->setCaptcha($req);
Yadd's avatar
Yadd committed
93 94
        }

Yadd's avatar
Yadd committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        # Else get token
        elsif ( $self->ott ) {
            $self->setToken($req);
        }
        return $res;
    }

    # 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;
Yadd's avatar
Yadd committed
114
            }
Yadd's avatar
Yadd committed
115 116 117
            unless ( $self->captcha->validateCaptcha( $token, $code ) ) {
                $self->setCaptcha($req);
                $self->p->userNotice("Captcha failed: wrong or expired code");
Yadd's avatar
Yadd committed
118 119
                return PE_CAPTCHAERROR;
            }
Yadd's avatar
Yadd committed
120 121 122 123 124 125 126
            $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;
Yadd's avatar
Yadd committed
127 128 129 130 131
            }
        }
    }

    # Other parameters
Yadd's avatar
Yadd committed
132
    $req->datas->{timezone} = $req->param('timezone');
Yadd's avatar
Yadd committed
133 134 135 136 137 138

    PE_OK;
}

# Set password in session datas if wanted.
sub setAuthSessionInfo {
Yadd's avatar
Yadd committed
139
    my ( $self, $req ) = @_;
Yadd's avatar
Yadd committed
140 141

    # authenticationLevel
Yadd's avatar
Yadd committed
142
    $req->{sessionInfo}->{authenticationLevel} = $self->authnLevel;
Yadd's avatar
Yadd committed
143 144 145 146

    # Store submitted password if set in configuration
    # WARNING: it can be a security hole
    if ( $self->conf->{storePassword} ) {
Yadd's avatar
Yadd committed
147
        $req->{sessionInfo}->{'_password'} = $req->datas->{'newpassword'}
Yadd's avatar
Yadd committed
148
          || $req->datas->{'password'};
Yadd's avatar
Yadd committed
149 150 151
    }

    # Store user timezone
Yadd's avatar
Yadd committed
152
    $req->{sessionInfo}->{'_timezone'} = $self->{'timezone'};
Yadd's avatar
Yadd committed
153 154 155 156

    PE_OK;
}

Yadd's avatar
Yadd committed
157 158 159 160 161
# @return display type
sub getDisplayType {
    return "standardform";
}

Yadd's avatar
Yadd committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175
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 );
}

Yadd's avatar
Yadd committed
176
1;