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   72199 use strict; use warnings;
  1     1   3  
  1         30  
  1         5  
  1         3  
  1         56  
2              
3             package Net::OAuth2Server::PKCE;
4              
5             our $VERSION = '0.002';
6              
7 1     1   559 use Digest::SHA ();
  1         3207  
  1         133  
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.002';
17              
18 1     1   589 use Role::Tiny;
  1         4336  
  1         8  
19 1     1   705 use Class::Method::Modifiers 'fresh';
  1         1623  
  1         397  
20              
21             sub fresh__get_pkce_challenge {
22 259     259   378957 my $self = shift;
23 259 50       657 $self->ensure_required( qw( code_challenge code_challenge_method ) ) or return;
24 259         7749 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       6462 if not exists $transform{ $method };
27 259 100       587 $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       1889 $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         209 ( $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.002';
48              
49 1     1   10 use Role::Tiny;
  1         2  
  1         13  
50 1     1   183 use Class::Method::Modifiers 'fresh';
  1         2  
  1         57  
51 1     1   7 use Carp ();
  1         2  
  1         450  
52              
53 259     259   383233 sub no_secret_required { my $orig = shift; grep 'client_secret' ne $_, shift->$orig( @_ ) };
  259         689  
54             around required_parameters => \&no_secret_required;
55              
56             sub fresh__get_pkce_challenge {
57 261     261   11905 my ( $self, $method ) = ( shift, @_ );
58 261 50       902 my $t = $transform{ $method }
59             or Carp::croak( "bad code_challenge_method: $method" );
60 261 50       585 $self->ensure_required( 'code_verifier' ) or return;
61 261         7611 my $verifier = $self->param( 'code_verifier' );
62 261 100 100     6793 $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       2057 $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         144 $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__