File Coverage

blib/lib/Authen/NZRealMe/LogonStrength.pm
Criterion Covered Total %
statement 50 50 100.0
branch 16 18 88.8
condition 8 9 88.8
subroutine 12 12 100.0
pod 4 4 100.0
total 90 93 96.7


line stmt bran cond sub pod time code
1             package Authen::NZRealMe::LogonStrength;
2             {
3             $Authen::NZRealMe::LogonStrength::VERSION = '1.15';
4             }
5              
6 1     1   5 use strict;
  1         2  
  1         30  
7 1     1   6 use warnings;
  1         2  
  1         21  
8 1     1   4 use Carp;
  1         2  
  1         78  
9              
10 1     1   5 use constant URN_PREFIX => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:';
  1         1  
  1         68  
11              
12 1     1   11 use constant STRENGTH_LOW => URN_PREFIX . 'LowStrength';
  1         2  
  1         55  
13 1     1   5 use constant STRENGTH_MODERATE => URN_PREFIX . 'ModStrength';
  1         2  
  1         63  
14 1     1   4 use constant STRENGTH_MODERATE_SID => URN_PREFIX . 'ModStrength::OTP:Token:SID';
  1         2  
  1         52  
15 1     1   4 use constant STRENGTH_MODERATE_SMS => URN_PREFIX . 'ModStrength::OTP:Token:SMS';
  1         2  
  1         452  
16              
17              
18             my %word_to_urn = (
19             low => STRENGTH_LOW,
20             mod => STRENGTH_MODERATE,
21             moderate => STRENGTH_MODERATE,
22             );
23              
24             my %strength_score = (
25             &STRENGTH_LOW => 10,
26             &STRENGTH_MODERATE => 20,
27             &STRENGTH_MODERATE_SID => 20,
28             &STRENGTH_MODERATE_SMS => 20,
29             );
30              
31              
32             sub new {
33 34     34 1 3118 my $class = shift;
34 34   100     551 my $urn = shift || 'low';
35              
36 34 100       85 $urn = $word_to_urn{$urn} if $word_to_urn{$urn};
37              
38 34 100       76 if(not exists $strength_score{$urn}) {
39 15         238 my @match = grep /\Q$urn\E$/i, keys %strength_score;
40 15 50       40 croak "Can't find a match for logon strength '$urn'" if @match == 0;
41 15 50       31 croak "Ambiguous logon strength '$urn'" if @match > 1;
42 15         25 $urn = $match[0];
43             }
44              
45 34         157 return bless { urn => $urn }, $class;
46             }
47              
48              
49 59     59 1 1103 sub urn { shift->{urn}; }
50 35     35 1 70 sub score { $strength_score{ shift->{urn} }; }
51              
52              
53             sub assert_match {
54 27     27 1 10319 my $self = shift;
55 27   50     68 my $required = shift || 'low';
56 27   100     60 my $match = shift || 'minimum';
57              
58 27         52 my $class = ref($self);
59 27         60 $required = $class->new($required);
60              
61 27         60 my $provided_urn = $self->urn;
62 27         39 my $required_urn = $required->urn;
63 27 100       92 return if $required_urn eq $provided_urn;
64              
65 17         29 my $provided_score = $self->score;
66 17         26 my $required_score = $required->score;
67 17 100 100     71 return if $required_urn eq STRENGTH_MODERATE and $provided_score == 20;
68              
69 13 100       32 if($match eq 'minimum') {
    100          
70 5 100       20 return if $provided_score > $required_score;
71             }
72             elsif($match ne 'exact') {
73 1         9 die "Unrecognised password strength match type: '$match'";
74             }
75              
76 9         77 die "Invalid logon strength.\n"
77             . "Required: $required_urn\n"
78             . "Provided: $provided_urn\n"
79             . "Comparison: $match\n";
80             }
81              
82             1;
83              
84             __END__