File Coverage

blib/lib/Net/OAuth2Server/PKCE.pm
Criterion Covered Total %
statement 40 50 80.0
branch 12 22 54.5
condition 3 3 100.0
subroutine 11 13 84.6
pod n/a
total 66 88 75.0


line stmt bran cond sub pod time code
1 1     1   60734 use strict; use warnings;
  1     1   2  
  1         28  
  1         4  
  1         2  
  1         45  
2              
3             package Net::OAuth2Server::PKCE;
4             our $VERSION = '0.005';
5              
6 1     1   451 use Digest::SHA ();
  1         2807  
  1         105  
7              
8             our %transform = (
9             plain => sub () { $_[0] },
10             S256 => sub () { my $v = &Digest::SHA::sha256_base64; $v =~ y[+/][-_]; $v },
11             );
12              
13             package Net::OAuth2Server::Request::Authorization::Role::PKCE;
14             our $VERSION = '0.004';
15              
16 1     1   529 use Role::Tiny;
  1         3734  
  1         6  
17 1     1   672 use Class::Method::Modifiers 'fresh';
  1         1401  
  1         355  
18              
19             sub fresh__get_pkce_challenge {
20 259     259   310836 my $self = shift;
21 259 50       558 $self->ensure_required( qw( code_challenge code_challenge_method ) ) or return;
22 259         6221 my ( $challenge, $method ) = $self->params( qw( code_challenge code_challenge_method ) );
23             $self->set_error_invalid_request( "unsupported code_challenge_method: $method" ), return
24 259 50       5125 if not exists $transform{ $method };
25 259 100       486 $self->set_error_invalid_request( sprintf 'bad code_challenge length: %s (must be 43)', length $challenge ), return
26             unless 43 == length $challenge;
27 257 100       1516 $self->set_error_invalid_request( sprintf 'bad character in code_challenge: 0x%02X at position %d', ord $1, -1 + pos $challenge ), return
28             if $challenge =~ /([^A-Za-z0-9_-])/g;
29 65         167 ( $challenge, $method );
30             }
31             fresh get_pkce_challenge => \&fresh__get_pkce_challenge;
32             undef *fresh__get_pkce_challenge;
33              
34             sub fresh__get_pkce_token {
35 0     0   0 my ( $self, $secret ) = ( shift, @_ );
36 0 0       0 my ( $challenge, $method ) = $self->get_pkce_challenge or return;
37 0         0 ( my $hmac = Digest::SHA::hmac_sha256_base64( "$method $challenge", $secret ) ) =~ y[+/][-_];
38 0         0 "$hmac $method";
39             }
40             fresh get_pkce_token => \&fresh__get_pkce_token;
41             undef *fresh__get_pkce_token;
42              
43             package Net::OAuth2Server::Request::Token::AuthorizationCode::Role::PKCE;
44             our $VERSION = '0.004';
45              
46 1     1   11 use Role::Tiny;
  1         1  
  1         7  
47 1     1   154 use Class::Method::Modifiers 'fresh';
  1         2  
  1         45  
48 1     1   6 use Carp ();
  1         2  
  1         407  
49              
50 259     259   307716 sub no_secret_required { my $orig = shift; grep 'client_secret' ne $_, shift->$orig( @_ ) };
  259         612  
51             around required_parameters => \&no_secret_required;
52              
53             sub fresh__get_pkce_challenge {
54 261     261   9474 my ( $self, $method ) = ( shift, @_ );
55 261 50       630 my $t = $transform{ $method }
56             or Carp::croak( "bad code_challenge_method: $method" );
57 261 50       468 $self->ensure_required( 'code_verifier' ) or return;
58 261         6172 my $verifier = $self->param( 'code_verifier' );
59 261 100 100     5577 $self->set_error_invalid_request( sprintf 'bad code_verifier length: %s (must be 43 (min) to 128 (max))', length $verifier ), return
60             unless grep 43 <= $_ && $_ <= 128, length $verifier;
61 259 100       1551 $self->set_error_invalid_request( sprintf 'bad character in code_verifier: 0x%02X at position %d', ord $1, -1 + pos $verifier ), return
62             if $verifier =~ /([^.~A-Za-z0-9_-])/g;
63 69         124 $t->( $verifier );
64             }
65             fresh get_pkce_challenge => \&fresh__get_pkce_challenge;
66             undef *fresh__get_pkce_challenge;
67              
68             sub fresh__ensure_pkce_token {
69 0     0     my ( $self, $secret, $token ) = ( shift, @_ );
70 0           my ( $orig_hmac, $method ) = split / /, $token, 2;
71 0 0         my ( $challenge ) = $self->get_pkce_challenge( $method ) or return !1;
72 0           ( my $hmac = Digest::SHA::hmac_sha256_base64( "$method $challenge", $secret ) ) =~ y[+/][-_];
73 0 0         ( my $ok = $hmac eq $orig_hmac ) or $self->set_error_invalid_client;
74 0           $ok;
75             }
76             fresh ensure_pkce_token => \&fresh__ensure_pkce_token;
77             undef *fresh__ensure_pkce_token;
78              
79             1;
80              
81             __END__