Dancer2-Plugin-Auth-YARBAC
view release on metacpan or search on metacpan
lib/Dancer2/Plugin/Auth/YARBAC/Provider/Base.pm view on Meta::CPAN
package Dancer2::Plugin::Auth::YARBAC::Provider::Base;
use strict;
use warnings;
use Moo;
use namespace::clean;
use Crypt::PBKDF2;
use Data::Dumper;
our $VERSION = '0.011';
has dsl => ( is => 'ro' );
has app => ( is => 'ro' );
has settings => ( is => 'ro' );
has pw_min_length => ( is => 'ro', default => \&_pw_min_length, lazy => 1 );
has pw_max_length => ( is => 'ro', default => \&_pw_max_length, lazy => 1 );
has pw_special_characters => ( is => 'ro', default => \&_pw_special_characters, lazy => 1 );
has pw_control_characters => ( is => 'ro', default => \&_pw_control_characters, lazy => 1 );
has pw_no_repeating => ( is => 'ro', default => \&_pw_no_repeating, lazy => 1 );
has pw_upper_case => ( is => 'ro', default => \&_pw_upper_case, lazy => 1 );
has pw_lower_case => ( is => 'ro', default => \&_pw_lower_case, lazy => 1 );
has pw_numbers => ( is => 'ro', default => \&_pw_numbers, lazy => 1 );
has pw_required_score => ( is => 'ro', default => \&_pw_required_score, lazy => 1 );
has pw_truncate => ( is => 'ro', default => \&_pw_truncate, lazy => 1 );
has hash_class => ( is => 'ro', default => sub { 'HMACSHA2' } );
has hash_args => ( is => 'ro', default => sub { { sha_size => 512, } } );
has iterations => ( is => 'ro', default => \&_iterations, lazy => 1 );
has output_len => ( is => 'ro', default => \&_output_len, lazy => 1 );
has salt_len => ( is => 'ro', default => \&_salt_len, lazy => 1 );
has pbkdf2 => ( is => 'ro', default => \&_pbkdf2, lazy => 1 );
sub _pw_min_length
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{min_length}
&& $self->settings->{password_strength}->{min_length} =~ m{^\d$} )
? $self->settings->{password_strength}->{min_length}
: 6;
}
sub _pw_max_length
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{max_length}
&& $self->settings->{password_strength}->{max_length} =~ m{^\d$} )
? $self->settings->{password_strength}->{max_length}
: 32;
}
sub _pw_special_characters
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{special_characters}
&& $self->settings->{password_strength}->{special_characters} =~ m{^\d$} )
? $self->settings->{password_strength}->{special_characters}
: 1;
}
sub _pw_control_characters
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{control_characters}
&& $self->settings->{password_strength}->{control_characters} =~ m{^\d$} )
? $self->settings->{password_strength}->{control_characters}
: 1;
}
sub _pw_no_repeating
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{no_repeating}
&& $self->settings->{password_strength}->{no_repeating} =~ m{^\d$} )
? $self->settings->{password_strength}->{no_repeating}
: 1;
}
sub _pw_upper_case
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{upper_case}
&& $self->settings->{password_strength}->{upper_case} =~ m{^\d$} )
? $self->settings->{password_strength}->{upper_case}
: 1;
}
sub _pw_lower_case
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{lower_case}
&& $self->settings->{password_strength}->{lower_case} =~ m{^\d$} )
? $self->settings->{password_strength}->{lower_case}
: 1;
}
sub _pw_numbers
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{numbers}
&& $self->settings->{password_strength}->{numbers} =~ m{^\d$} )
? $self->settings->{password_strength}->{numbers}
: 1;
}
sub _pw_required_score
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{required_score}
&& $self->settings->{password_strength}->{required_score} =~ m{^\d$} )
? $self->settings->{password_strength}->{required_score}
: 25;
}
sub _pw_truncate
{
my $self = shift;
return ( defined $self->settings->{password_strength}->{truncate}
&& $self->settings->{password_strength}->{truncate} =~ m{^\d$} )
? $self->settings->{password_strength}->{truncate}
: 1;
}
sub _iterations
{
my $self = shift;
return ( defined $self->settings->{PBKDF2}->{iterations}
&& $self->settings->{PBKDF2}->{iterations} =~ m{^\d^} )
? $self->settings->{PBKDF2}->{iterations}
: 4000;
}
sub _output_len
{
my $self = shift;
return ( defined $self->settings->{PBKDF2}->{output_len}
&& $self->settings->{PBKDF2}->{output_len} =~ m{^\d$} )
? $self->settings->{PBKDF2}->{output_len}
: 64;
}
sub _salt_len
{
my $self = shift;
return ( defined $self->settings->{PBKDF2}->{salt_len}
&& $self->settings->{PBKDF2}->{salt_len} =~ m{^\d$} )
? $self->settings->{PBKDF2}->{salt_len}
: 24;
}
sub _pbkdf2
{
my $self = shift;
return Crypt::PBKDF2->new(
hash_class => $self->hash_class,
hash_args => $self->hash_args,
iterations => $self->iterations,
output_len => $self->output_len,
salt_len => $self->salt_len,
);
}
sub generate_hash
{
my $self = shift;
my $params = shift;
my $opts = shift;
return if ( ! defined $params->{password} );
if ( $params->{password} =~ m/^{X-PBKDF2}HMACSHA2.+/ )
{
return $params->{password};
}
else
{
$params->{password} = $self->truncate_password( $params );
return $self->pbkdf2->generate( $params->{password} );
}
}
sub validate_password
{
my $self = shift;
my $params = shift;
my $opts = shift;
return if ( ! defined $params->{hash} || ! defined $params->{password} );
$params->{password} = $self->truncate_password( $params );
return ( $self->pbkdf2->validate( $params->{hash}, $params->{password} ) ) ? 1 : undef;
}
sub truncate_password
{
# Enforcing the truncating of long passwords to avoid DDOS attacks.
my $self = shift;
my $params = shift;
my $opts = shift;
return if ( ! defined $params->{password} );
return ( $self->pw_truncate ) ? substr( $params->{password}, 0, $self->pw_max_length ) : $params->{password};
}
sub password_strength
{
my $self = shift;
my $params = shift;
my $opts = shift;
my $password = $params->{password};
my $pw_length = ( defined $password ) ? length $password : 0;
my @errors;
if ( ! defined $password )
( run in 0.793 second using v1.01-cache-2.11-cpan-71847e10f99 )