line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
444
|
use strict; use warnings; |
|
1
|
|
|
1
|
|
2
|
|
|
1
|
|
|
|
|
22
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
55
|
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Net::OAuth2Server::OIDC; |
4
|
|
|
|
|
|
|
our $VERSION = '0.006'; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Net::OAuth2Server::Request::Authorization::Role::OIDC; |
7
|
|
|
|
|
|
|
our $VERSION = '0.006'; |
8
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
571
|
use Role::Tiny; |
|
1
|
|
|
|
|
3920
|
|
|
1
|
|
|
|
|
6
|
|
10
|
1
|
|
|
1
|
|
1757
|
use Class::Method::Modifiers 'fresh'; |
|
1
|
|
|
|
|
1555
|
|
|
1
|
|
|
|
|
403
|
|
11
|
|
|
|
|
|
|
|
12
|
0
|
|
|
0
|
|
|
sub fresh__response_type_requiring_nonce { qw( token id_token ) } |
13
|
|
|
|
|
|
|
sub fresh__valid_parameter_values { ( |
14
|
0
|
|
|
0
|
|
|
display => [qw( page popup touch wap )], |
15
|
|
|
|
|
|
|
prompt => [qw( none login consent select_account )], |
16
|
|
|
|
|
|
|
) } |
17
|
|
|
|
|
|
|
fresh response_type_requiring_nonce => \&fresh__response_type_requiring_nonce; |
18
|
|
|
|
|
|
|
fresh valid_parameter_values => \&fresh__valid_parameter_values; |
19
|
|
|
|
|
|
|
undef *fresh__response_type_requiring_nonce; |
20
|
|
|
|
|
|
|
undef *fresh__valid_parameter_values; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub around__new { |
23
|
|
|
|
|
|
|
my $orig = shift; |
24
|
|
|
|
|
|
|
my $class = shift; |
25
|
|
|
|
|
|
|
my $self = $class->$orig( @_ ); |
26
|
|
|
|
|
|
|
return $self if $self->error; |
27
|
|
|
|
|
|
|
if ( $self->scope->contains( 'openid' ) ) { |
28
|
|
|
|
|
|
|
return $self->set_error_invalid_request( 'missing parameter: nonce' ) |
29
|
|
|
|
|
|
|
if ( not defined $self->param('nonce') ) |
30
|
|
|
|
|
|
|
and $self->response_type->contains( $self->response_type_requiring_nonce ); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my %validate = $self->valid_parameter_values; |
33
|
|
|
|
|
|
|
my @invalid = sort grep { |
34
|
|
|
|
|
|
|
my $name = $_; |
35
|
|
|
|
|
|
|
my $value = $self->param( $name ); |
36
|
|
|
|
|
|
|
defined $value and not grep $value eq $_, @{ $validate{ $name } }; |
37
|
|
|
|
|
|
|
} keys %validate; |
38
|
|
|
|
|
|
|
return $self->set_error_invalid_request( "invalid value for parameter: @invalid" ) if @invalid; |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
else { |
41
|
|
|
|
|
|
|
return $self->set_error_invalid_request( 'id_token requested outside of openid scope' ) |
42
|
|
|
|
|
|
|
if $self->response_type->contains( 'id_token' ); |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
$self; |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
around 'new' => \&around__new; |
47
|
|
|
|
|
|
|
undef *around__new; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
package Net::OAuth2Server::Response::Role::OIDC; |
50
|
|
|
|
|
|
|
our $VERSION = '0.006'; |
51
|
|
|
|
|
|
|
|
52
|
1
|
|
|
1
|
|
8
|
use Role::Tiny; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
6
|
|
53
|
1
|
|
|
1
|
|
160
|
use Class::Method::Modifiers 'fresh'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
55
|
|
54
|
1
|
|
|
1
|
|
549
|
use MIME::Base64 (); |
|
1
|
|
|
|
|
664
|
|
|
1
|
|
|
|
|
22
|
|
55
|
1
|
|
|
1
|
|
453
|
use JSON::WebToken (); |
|
1
|
|
|
|
|
18252
|
|
|
1
|
|
|
|
|
28
|
|
56
|
1
|
|
|
1
|
|
1829
|
use Digest::SHA (); |
|
1
|
|
|
|
|
2776
|
|
|
1
|
|
|
|
|
26
|
|
57
|
1
|
|
|
1
|
|
13
|
use Carp (); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
531
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# copy-paste from newer MIME::Base64 for older versions without it |
60
|
|
|
|
|
|
|
my $b64url_enc = MIME::Base64->can( 'encode_base64url' ) || sub { |
61
|
|
|
|
|
|
|
my $e = MIME::Base64::encode_base64( shift, '' ); |
62
|
|
|
|
|
|
|
$e =~ s/=+\z//; |
63
|
|
|
|
|
|
|
$e =~ tr[+/][-_]; |
64
|
|
|
|
|
|
|
return $e; |
65
|
|
|
|
|
|
|
}; |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
0
|
|
|
sub fresh__supported_response_types { qw( code id_token token ) } |
68
|
|
|
|
|
|
|
fresh supported_response_types => \&fresh__supported_response_types; |
69
|
|
|
|
|
|
|
undef *fresh__supported_response_types; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub around__for_authorization { |
72
|
|
|
|
|
|
|
my $orig = shift; |
73
|
|
|
|
|
|
|
my ( $class, $req, $grant ) = ( shift, @_ ); |
74
|
|
|
|
|
|
|
my $self = $class->$orig( @_ ); |
75
|
|
|
|
|
|
|
return $self if $self->is_error or not $grant; |
76
|
|
|
|
|
|
|
$grant->create_id_token( $self, 1 ) if $req->response_type->contains( 'id_token' ); |
77
|
|
|
|
|
|
|
$self; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
around for_authorization => \&around__for_authorization; |
80
|
|
|
|
|
|
|
undef *around__for_authorization; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub around__for_token { |
83
|
|
|
|
|
|
|
my $orig = shift; |
84
|
|
|
|
|
|
|
my ( $class, $req, $grant ) = ( shift, @_ ); |
85
|
|
|
|
|
|
|
my $self = $class->$orig( @_ ); |
86
|
|
|
|
|
|
|
return $self if $self->is_error or not $grant; |
87
|
|
|
|
|
|
|
$grant->create_id_token( $self, 0 ) if $grant->scope->contains( 'openid' ); |
88
|
|
|
|
|
|
|
$self; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
around for_token => \&around__for_token; |
91
|
|
|
|
|
|
|
undef *around__for_token; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
my %hashed = qw( code c_hash access_token at_hash ); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub fresh__add_id_token { |
96
|
0
|
|
|
0
|
|
|
my ( $self, $nonce, $pay, $head, $key ) = ( shift, @_ ); |
97
|
0
|
0
|
|
|
|
|
Carp::croak 'missing payload' unless $pay; |
98
|
0
|
0
|
0
|
|
|
|
Carp::croak 'header and payload must be hashes' if grep 'HASH' ne ref, $pay, $head || (); |
99
|
0
|
0
|
|
|
|
|
$pay->{'nonce'} = $nonce if $nonce; |
100
|
0
|
|
0
|
|
|
|
my $alg = ( $head && $head->{'alg'} ) || 'none'; |
101
|
0
|
0
|
|
|
|
|
if ( $alg =~ /\A[A-Za-z]{2}([0-9]+)\z/ ) { |
102
|
0
|
|
|
|
|
|
my $sha = Digest::SHA->new( "$1" ); |
103
|
0
|
|
|
|
|
|
while ( my ( $k, $k_hash ) = each %hashed ) { |
104
|
0
|
0
|
|
|
|
|
next unless $self->has_param( $k ); |
105
|
0
|
|
|
|
|
|
my $digest = $sha->reset->add( $self->param( $k ) )->digest; |
106
|
0
|
|
|
|
|
|
$pay->{ $k_hash } = $b64url_enc->( substr $digest, 0, length( $digest ) / 2 ); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
} |
109
|
0
|
|
|
|
|
|
$self->add_token( id_token => JSON::WebToken->encode( $pay, $key, $alg, $head ) ); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
fresh add_id_token => \&fresh__add_id_token; |
112
|
|
|
|
|
|
|
undef *fresh__add_id_token; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
1; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
__END__ |