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   71997 use strict; use warnings;
  1     1   2  
  1         74  
  1         7  
  1         3  
  1         101  
2              
3             package Net::OAuth2Server::PKCE;
4              
5             our $VERSION = '0.003';
6              
7 1     1   909 use Digest::SHA ();
  1         5729  
  1         195  
8              
9             our %transform = (
10             plain => sub () { $_[0] },
11             S256 => sub () { my $v = &Digest::SHA::sha256_base64; $v =~ y[+/][-_]; $v },
12             );
13              
14             package Net::OAuth2Server::Request::Authorization::Role::PKCE;
15              
16             our $VERSION = '0.003';
17              
18 1     1   685 use Role::Tiny;
  1         4458  
  1         6  
19 1     1   692 use Class::Method::Modifiers 'fresh';
  1         1629  
  1         391  
20              
21             sub fresh__get_pkce_challenge {
22 259     259   382948 my $self = shift;
23 259 50       651 $self->ensure_required( qw( code_challenge code_challenge_method ) ) or return;
24 259         7786 my ( $challenge, $method ) = $self->params( qw( code_challenge code_challenge_method ) );
25             $self->set_error_invalid_request( "unsupported code_challenge_method: $method" ), return
26 259 50       6537 if not exists $transform{ $method };
27 259 100       641 $self->set_error_invalid_request( sprintf 'bad code_challenge length: %s (must be 43)', length $challenge ), return
28             unless 43 == length $challenge;
29 257 100       1936 $self->set_error_invalid_request( sprintf 'bad character in code_challenge: 0x%02X at position %d', ord $1, -1 + pos $challenge ), return
30             if $challenge =~ /([^A-Za-z0-9_-])/g;
31 65         199 ( $challenge, $method );
32             }
33             fresh get_pkce_challenge => \&fresh__get_pkce_challenge;
34             undef *fresh__get_pkce_challenge;
35              
36             sub fresh__get_pkce_token {
37 0     0   0 my ( $self, $secret ) = ( shift, @_ );
38 0 0       0 my ( $challenge, $method ) = $self->get_pkce_challenge or return;
39 0         0 ( my $hmac = Digest::SHA::hmac_sha256_base64( "$method $challenge", $secret ) ) =~ y[+/][-_];
40 0         0 "$hmac $method";
41             }
42             fresh get_pkce_token => \&fresh__get_pkce_token;
43             undef *fresh__get_pkce_token;
44              
45             package Net::OAuth2Server::Request::Token::AuthorizationCode::Role::PKCE;
46              
47             our $VERSION = '0.003';
48              
49 1     1   8 use Role::Tiny;
  1         2  
  1         14  
50 1     1   179 use Class::Method::Modifiers 'fresh';
  1         2  
  1         53  
51 1     1   8 use Carp ();
  1         2  
  1         454  
52              
53 259     259   397953 sub no_secret_required { my $orig = shift; grep 'client_secret' ne $_, shift->$orig( @_ ) };
  259         770  
54             around required_parameters => \&no_secret_required;
55              
56             sub fresh__get_pkce_challenge {
57 261     261   12128 my ( $self, $method ) = ( shift, @_ );
58 261 50       837 my $t = $transform{ $method }
59             or Carp::croak( "bad code_challenge_method: $method" );
60 261 50       564 $self->ensure_required( 'code_verifier' ) or return;
61 261         7790 my $verifier = $self->param( 'code_verifier' );
62 261 100 100     6863 $self->set_error_invalid_request( sprintf 'bad code_challenge length: %s (must be 43 (min) to 128 (max))', length $verifier ), return
63             unless grep 43 <= $_ && $_ <= 128, length $verifier;
64 259 100       2122 $self->set_error_invalid_request( sprintf 'bad character in code_challenge: 0x%02X at position %d', ord $1, -1 + pos $verifier ), return
65             if $verifier =~ /([^.~A-Za-z0-9_-])/g;
66 69         160 $t->( $verifier );
67             }
68             fresh get_pkce_challenge => \&fresh__get_pkce_challenge;
69             undef *fresh__get_pkce_challenge;
70              
71             sub fresh__ensure_pkce_token {
72 0     0     my ( $self, $secret, $token ) = ( shift, @_ );
73 0           my ( $orig_hmac, $method ) = split / /, $token, 2;
74 0 0         my ( $challenge ) = $self->get_pkce_challenge( $method ) or return !1;
75 0           ( my $hmac = Digest::SHA::hmac_sha256_base64( "$method $challenge", $secret ) ) =~ y[+/][-_];
76 0 0         ( my $ok = $hmac eq $orig_hmac ) or $self->set_error_invalid_client;
77 0           $ok;
78             }
79             fresh ensure_pkce_token => \&fresh__ensure_pkce_token;
80             undef *fresh__ensure_pkce_token;
81              
82             1;
83              
84             __END__