File Coverage

blib/lib/OIDC/Lite/Model/IDToken.pm
Criterion Covered Total %
statement 82 82 100.0
branch 24 24 100.0
condition 9 9 100.0
subroutine 17 17 100.0
pod 6 6 100.0
total 138 138 100.0


line stmt bran cond sub pod time code
1             package OIDC::Lite::Model::IDToken;
2 2     2   19986 use strict;
  2         4  
  2         68  
3 2     2   7 use warnings;
  2         2  
  2         47  
4 2     2   8 use base 'Class::Accessor::Fast';
  2         3  
  2         629  
5              
6 2     2   3571 use MIME::Base64 qw/encode_base64url decode_base64url/;
  2         1236  
  2         166  
7 2     2   909 use JSON::WebToken qw/encode_jwt decode_jwt/;
  2         34632  
  2         121  
8 2     2   1084 use Params::Validate;
  2         10267  
  2         123  
9 2     2   6825 use Digest::SHA qw/sha256 sha384 sha512/;
  2         16521  
  2         229  
10 2     2   859 use OIDC::Lite::Util::JWT;
  2         4  
  2         60  
11              
12 2     2   8 use constant HALF_BITS_DENOMINATOR => 2 * 8;
  2         2  
  2         84  
13 2     2   7 use constant ALG_LEN => 2;
  2         3  
  2         64  
14 2     2   6 use constant BITS_LEN => 3;
  2         2  
  2         1277  
15              
16              
17             =head1 NAME
18              
19             OIDC::Lite::Model::IDToken - model class that represents ID token
20              
21             =head1 ACCESSORS
22              
23             =head2 header
24              
25             JWT Header
26              
27             =head2 payload
28              
29             JWT Payload
30              
31             =head2 key
32              
33             Key for JWT Signature
34              
35             =cut
36              
37             __PACKAGE__->mk_accessors(qw(
38             header
39             payload
40             key
41             token_string
42             ));
43              
44             =head1 METHODS
45              
46             =head2 new( \%header, \%payload, $key )
47              
48             Constructor
49              
50             my $id_token = OIDC::Lite::Model::IDToken->new();
51             ...
52             my $id_token = OIDC::Lite::Model::IDToken->new(
53             header => \%header,
54             payload => \%payload,
55             key => $key,
56             );
57              
58             =cut
59              
60             sub new {
61 19     19 1 6629 my $class = shift;
62 19 100       81 my @args = @_ == 1 ? %{$_[0]} : @_;
  1         6  
63 19         609 my %params = Params::Validate::validate_with(
64             params => \@args,
65             spec => {
66             header => { optional => 1 },
67             payload => { optional => 1 },
68             key => { optional => 1 },
69             },
70             allow_extra => 0,
71             );
72              
73 19         169 my $self = bless \%params, $class;
74 19 100       68 unless($self->header){
75 2         22 my %header=();
76 2         7 $self->header(\%header);
77             }
78 19 100       146 unless($self->payload){
79 2         23 my %payload=();
80 2         5 $self->payload(\%payload);
81             }
82            
83 19         116 return $self;
84             }
85              
86             =head2 get_token_string()
87              
88             generate signature and return ID Token string.
89              
90             my $id_token_string = $id_token->get_token_string();
91              
92             =cut
93              
94             sub get_token_string {
95 6     6 1 1676 my ($self) = @_;
96              
97 6 100       18 $self->header->{typ} = q{JWT}
98             unless($self->header->{typ});
99 6 100       51 $self->header->{alg} = q{none}
100             unless($self->header->{alg});
101              
102             # generate token string
103 6         44 my $jwt = encode_jwt($self->payload, $self->key, $self->header->{alg}, $self->header);
104 6         12614 $self->token_string($jwt);
105 6         45 return $jwt;
106             }
107              
108             =head2 access_token_hash()
109              
110             generate signature and return ID Token string.
111              
112             $id_token->code_hash($access_token);
113              
114             =cut
115              
116             sub access_token_hash {
117 3     3 1 24 my ($self, $access_token_string) = @_;
118              
119 3 100 100     7 if($self->header->{alg} && $self->header->{alg} ne 'none')
120             {
121 1         16 my $bit = substr($self->header->{alg}, ALG_LEN, BITS_LEN);
122 1         10 my $len = $bit/HALF_BITS_DENOMINATOR;
123 1         10 my $sha = Digest::SHA->new($bit);
124 1         31 $sha->add($access_token_string);
125 1         19 $self->payload->{at_hash} = encode_base64url(substr($sha->digest, 0, $len));
126             }
127             }
128              
129             =head2 code_hash()
130              
131             Set Authorization Code Hash to ID Token.
132              
133             $id_token->code_hash($authorization_code);
134              
135             =cut
136              
137             sub code_hash {
138 3     3 1 85 my ($self, $authorization_code) = @_;
139              
140 3 100 100     8 if($self->header->{alg} && $self->header->{alg} ne 'none')
141             {
142 1         11 my $bit = substr($self->header->{alg}, ALG_LEN, BITS_LEN);
143 1         6 my $len = $bit/HALF_BITS_DENOMINATOR;
144 1         3 my $sha = Digest::SHA->new($bit);
145 1         12 $sha->add($authorization_code);
146 1         6 $self->payload->{c_hash} = encode_base64url(substr($sha->digest, 0, $len));
147             }
148             }
149              
150             =head2 load($token_string)
151              
152             load ID Token object from token string
153              
154             my $token_string = 'eyJhbGciOiJub25lIiwidHlwIjoiSldTIn0.eyJmb28iOiJiYXIifQ.';
155             my $id_token = OIDC::Lite::Model::IDToken->load($token_string);
156              
157             =cut
158              
159             sub load {
160 12     12 1 1459 my ($self, $token_string) = @_;
161 12 100       33 return unless($token_string);
162              
163 11         31 my $header = OIDC::Lite::Util::JWT::header($token_string);
164 11         27 my $payload = OIDC::Lite::Util::JWT::payload($token_string);
165 11 100 100     57 return unless ( $header and $payload );
166              
167 8         24 my $id_token = OIDC::Lite::Model::IDToken->new(
168             header => $header,
169             payload => $payload,
170             );
171 8         22 $id_token->token_string($token_string);
172 8         51 return $id_token;
173             }
174              
175             =head2 verify()
176              
177             verify token signature.
178              
179             my $token_string = '...';
180             my $id_token = OIDC::Lite::Model::IDToken->load($token_string);
181              
182             my $key = 'shared_secret_key';
183             $id_token->key($key);
184             unless($id_token->verify()){
185             # validation failed
186             }
187              
188             =cut
189              
190             sub verify {
191 8     8 1 70 my ($self) = @_;
192 8 100       19 return 0
193             unless($self->token_string);
194              
195 7 100       45 $self->key('')
196             unless($self->key);
197              
198 7         49 my $payload = undef;
199 7         10 eval{
200 7         15 $payload = decode_jwt($self->token_string, $self->key, 1, 1);
201             };
202 7 100       1711 if($@){
203 4         37 return 0;
204             }
205 3         13 return (defined($payload));
206             }
207              
208             =head1 AUTHOR
209              
210             Ryo Ito, Eritou.06@gmail.comE
211              
212             =head1 COPYRIGHT AND LICENSE
213              
214             Copyright (C) 2012 by Ryo Ito
215              
216             This library is free software; you can redistribute it and/or modify
217             it under the same terms as Perl itself, either Perl version 5.8.8 or,
218             at your option, any later version of Perl 5 you may have available.
219              
220             =cut
221              
222             1;