File Coverage

blib/lib/Crypt/JWT.pm
Criterion Covered Total %
statement 436 486 89.7
branch 291 432 67.3
condition 83 175 47.4
subroutine 41 41 100.0
pod 2 2 100.0
total 853 1136 75.0


line stmt bran cond sub pod time code
1             package Crypt::JWT;
2              
3 7     7   424578 use strict;
  7         73  
  7         225  
4 7     7   38 use warnings;
  7         12  
  7         330  
5              
6             our $VERSION = '0.034';
7              
8 7     7   39 use Exporter 'import';
  7         13  
  7         614  
9             our %EXPORT_TAGS = ( all => [qw(decode_jwt encode_jwt)] );
10             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
11             our @EXPORT = qw();
12              
13 7     7   52 use Carp;
  7         33  
  7         609  
14 7     7   3512 use Crypt::Misc qw(decode_b64u encode_b64u);
  7         153289  
  7         602  
15 7     7   58 use JSON qw(decode_json encode_json);
  7         17  
  7         49  
16 7     7   5294 use Crypt::PK::RSA;
  7         23635  
  7         341  
17 7     7   4000 use Crypt::PK::ECC;
  7         23463  
  7         364  
18 7     7   3383 use Crypt::PK::Ed25519;
  7         12757  
  7         438  
19 7     7   3416 use Crypt::PK::X25519;
  7         11130  
  7         402  
20 7     7   55 use Crypt::PRNG qw(random_bytes);
  7         13  
  7         355  
21 7     7   3228 use Crypt::KeyWrap ':all';
  7         19  
  7         1242  
22 7     7   51 use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
  7         15  
  7         360  
23 7     7   3318 use Crypt::Mac::HMAC qw(hmac);
  7         8988  
  7         385  
24 7     7   4509 use Compress::Raw::Zlib;
  7         40556  
  7         1571  
25 7     7   62 use Scalar::Util qw(looks_like_number);
  7         14  
  7         55728  
26              
27             # JWS: https://tools.ietf.org/html/rfc7515
28             # JWE: https://tools.ietf.org/html/rfc7516
29             # JWK: https://tools.ietf.org/html/rfc7517
30             # JWA: https://tools.ietf.org/html/rfc7518
31             # JWT: https://tools.ietf.org/html/rfc7519
32             # X25519/Ed25519 https://tools.ietf.org/html/rfc8037
33              
34             sub _prepare_rsa_key {
35 87     87   165 my ($key) = @_;
36 87 50       183 croak "JWT: undefined RSA key" unless defined $key;
37 87 100       492 croak "JWT: invalid RSA key (cannot be scalar)" unless ref $key;
38             # we need Crypt::PK::RSA object
39 86 100       235 return $key if ref($key) eq 'Crypt::PK::RSA';
40 38 50 66     297 return Crypt::PK::RSA->new($key) if ref($key) eq 'HASH' || ref($key) eq 'SCALAR';
41 0 0       0 return Crypt::PK::RSA->new(@$key) if ref($key) eq 'ARRAY';
42             # handle also: Crypt::OpenSSL::RSA, Crypt::X509, Crypt::OpenSSL::X509
43 0         0 my $str;
44 0 0       0 if (ref($key) eq 'Crypt::OpenSSL::RSA') {
    0          
45             # https://metacpan.org/pod/Crypt::OpenSSL::RSA
46 0 0       0 $str = $key->is_private ? $key->get_private_key_string : $key->get_public_key_string;
47             }
48             elsif (ref($key) =~ /^Crypt::(X509|OpenSSL::X509)$/) {
49             # https://metacpan.org/pod/Crypt::X509
50             # https://metacpan.org/pod/Crypt::OpenSSL::X509
51 0         0 $str = $key->pubkey;
52             }
53 0 0 0     0 return Crypt::PK::RSA->new(\$str) if defined $str && !ref($str);
54 0         0 croak "JWT: invalid RSA key";
55             }
56              
57             sub _prepare_ecc_key {
58 13     13   29 my ($key) = @_;
59 13 50       34 croak "JWT: undefined ECC key" unless defined $key;
60 13 100       166 croak "JWT: invalid ECC key (cannot be scalar)" unless ref $key;
61             # we need Crypt::PK::ECC object
62 12 100       36 return $key if ref($key) eq 'Crypt::PK::ECC';
63 4 50 33     39 return Crypt::PK::ECC->new($key) if ref($key) eq 'HASH' || ref($key) eq 'SCALAR';
64 0 0       0 return Crypt::PK::ECC->new(@$key) if ref($key) eq 'ARRAY';
65 0         0 croak "JWT: invalid ECC key";
66             }
67              
68             sub _prepare_ed25519_key {
69 2     2   5 my ($key) = @_;
70 2 50       6 croak "JWT: undefined Ed25519 key" unless defined $key;
71 2 50       7 croak "JWT: invalid Ed25519 key (cannot be scalar)" unless ref $key;
72             # we need Crypt::PK::Ed25519 object
73 2 50       5 return $key if ref($key) eq 'Crypt::PK::Ed25519';
74 2 50 33     26 return Crypt::PK::Ed25519->new($key) if ref($key) eq 'HASH' || ref($key) eq 'SCALAR';
75 0 0       0 return Crypt::PK::Ed25519->new(@$key) if ref($key) eq 'ARRAY';
76 0         0 croak "JWT: invalid Ed25519 key";
77             }
78              
79             sub _prepare_ecdh_key {
80 57     57   111 my ($key) = @_;
81 57 50       132 croak "JWT: undefined ECDH key" unless defined $key;
82 57 50       129 croak "JWT: invalid ECDH key (cannot be scalar)" unless ref $key;
83              
84             # we need Crypt::PK::X25519 or Crypt::PK::ECC object
85 57 100       230 return $key if ref($key) =~ /^Crypt::PK::(ECC|X25519)$/;
86              
87 9 50 33     31 if (ref($key) eq 'HASH' || ref($key) eq 'SCALAR') {
88             #HACK: this is ugly
89 9   66     14 my $rv = eval { Crypt::PK::ECC->new($key) } || eval { Crypt::PK::X25519->new($key) };
90 9 50       43438 return $rv if defined $rv;
91             }
92 0 0       0 if (ref($key) eq 'ARRAY') {
93             #HACK: this is ugly
94 0   0     0 my $rv = eval { Crypt::PK::ECC->new(@$key) } || eval { Crypt::PK::X25519->new(@$key) };
95 0 0       0 return $rv if defined $rv;
96             }
97 0         0 croak "JWT: invalid ECDH key";
98             }
99              
100             sub _prepare_oct_key {
101 254     254   471 my ($key) = @_;
102 254 50       514 croak "JWT: undefined oct key" unless defined $key;
103 254 100 66     962 if (ref $key eq 'HASH' && $key->{k} && $key->{kty} && $key->{kty} eq 'oct') {
    50 33        
      33        
104 7         44 return decode_b64u($key->{k});
105             }
106             elsif (!ref $key) {
107 247         1045 return $key;
108             }
109 0         0 croak "JWT: invalid oct key";
110             }
111              
112             sub _kid_lookup {
113 4     4   15 my ($kid, $kid_keys, $alg) = @_;
114 4 50 33     21 return undef if !defined $kid || !defined $alg;
115 4 100 66     17 $kid_keys = eval { decode_json($kid_keys) } if $kid_keys && !ref $kid_keys;
  2         18  
116 4 50       13 croak "JWT: kid_keys must be a HASHREF or a valid JSON/HASH" if ref $kid_keys ne 'HASH';
117 4         6 my $found;
118 4 50 33     21 if (exists $kid_keys->{keys} && ref $kid_keys->{keys} eq 'ARRAY') {
119             #FORMAT: { keys => [ {kid=>'A', kty=>?, ...}, {kid=>'B', kty=>?, ...} ] }
120 4         8 for (@{$kid_keys->{keys}}) {
  4         11  
121 8 100 33     42 if ($_->{kid} && $_->{kty} && $_->{kid} eq $kid) {
      66        
122 4         7 $found = $_;
123 4         8 last;
124             }
125             }
126             }
127             else {
128             #FORMAT: { hexadec1 => "----BEGIN CERTIFICATE-----...", hexadec2 => "----BEGIN CERTIFICATE-----..." }
129             #e.g. https://www.googleapis.com/oauth2/v1/certs
130 0 0 0     0 return \$kid_keys->{$kid} if $kid_keys->{$kid} && !ref $kid_keys->{$kid};
131             }
132 4 50       10 return undef if !$found;
133 4 50 33     38 return $found if $found->{kty} eq 'oct' && $alg =~ /^(HS|dir|PBES2-HS|A)/;
134 0 0 0     0 return $found if $found->{kty} eq 'OKP' && $alg =~ /^(EdDSA|ECDH-ES)/;
135 0 0 0     0 return $found if $found->{kty} eq 'EC' && $alg =~ /^(ES|EC)/;
136 0 0 0     0 return $found if $found->{kty} eq 'RSA' && $alg =~ /^(RS|PS)/;
137 0         0 croak "JWT: key type '$found->{kty}' cannot be used with alg '$alg'";
138             }
139              
140             sub _b64u_to_hash {
141 279     279   533 my $b64url = shift;
142 279 50       721 return undef unless $b64url;
143 279         1272 my $json = decode_b64u($b64url);
144 279 50       922 return undef unless $json;
145 279         421 my $hash = eval { decode_json($json) };
  279         1588  
146 279 50       934 return undef unless ref $hash eq 'HASH';
147 279         544 return $hash;
148             }
149              
150             sub _add_claims {
151 19     19   61 my ($payload, %args) = @_;
152             #### claims (defined for JWS only)
153             # "exp" Expiration Time
154             # "nbf" Not Before
155             # "iat" Issued At
156             # "iss" Issuer
157             # "sub" Subject
158             # "aud" Audience
159             # "jti" JWT ID
160 19         37 my $now = time;
161 19 100       51 $payload->{iat} = $now if $args{auto_iat};
162 19 100       50 $payload->{exp} = $now + $args{relative_exp} if defined $args{relative_exp};
163 19 100       72 $payload->{nbf} = $now + $args{relative_nbf} if defined $args{relative_nbf};
164             }
165              
166             sub _verify_claims {
167 267     267   885 my ($payload, %args) = @_;
168              
169 267 100       696 return if $args{ignore_claims};
170              
171 266 100       653 if (ref($payload) ne 'HASH') {
172             # https://github.com/DCIT/perl-Crypt-JWT/issues/31
173             # payload needs to be decoded into a HASH for checking any verify_XXXX
174 206         480 for my $claim (qw(exp nbf iat iss sub aud jti)) {
175 1430 100 100     3627 if (defined $args{"verify_$claim"} && $args{"verify_$claim"} != 0) {
176 2         324 croak "JWT: cannot check verify_$claim (payload not decoded JSON/HASH)";
177             }
178             }
179 204         531 return; # nothing to check
180             }
181              
182 60   100     189 my $leeway = $args{leeway} || 0;
183 60         93 my $now = time;
184              
185             ### exp
186 60 100 33     165 if(defined $payload->{exp}) {
    50          
187 45 100 100     128 if (!defined $args{verify_exp} || $args{verify_exp}==1) {
188 41 100       879 croak "JWT: exp claim check failed ($payload->{exp}/$leeway vs. $now)" if $payload->{exp} + $leeway <= $now;
189             }
190             }
191             elsif ($args{verify_exp} && $args{verify_exp}==1) {
192 0         0 croak "JWT: exp claim required but missing"
193             }
194              
195             ### nbf
196 53 100 33     142 if(defined $payload->{nbf}) {
    50          
197 30 100 100     69 if (!defined $args{verify_nbf} || $args{verify_nbf}==1) {
198 29 100       404 croak "JWT: nbf claim check failed ($payload->{nbf}/$leeway vs. $now)" if $payload->{nbf} - $leeway > $now;
199             }
200             }
201             elsif ($args{verify_nbf} && $args{verify_nbf}==1) {
202 0         0 croak "JWT: nbf claim required but missing"
203             }
204              
205             ### iat
206 50 100       114 if (exists $args{verify_iat}) { #default (non existing verify_iat) == no iat check
207 4 50 0     9 if(defined $payload->{iat}) {
    0          
208 4 100 100     19 if (!defined $args{verify_iat} || $args{verify_iat}==1) {
209 3 100       257 croak "JWT: iat claim check failed ($payload->{iat}/$leeway vs. $now)" if $payload->{iat} - $leeway > $now;
210             }
211             }
212             elsif ($args{verify_iat} && $args{verify_iat}==1) {
213 0         0 croak "JWT: iat claim required but missing"
214             }
215             }
216              
217             ### iss, sub, aud, jti
218 48         100 foreach my $claim (qw(iss sub aud jti)) {
219 165         342 my $check = $args{"verify_$claim"};
220 165 100       306 next unless (defined $check);
221              
222 47 100       79 if (exists $payload->{$claim}) {
223 43 100       92 if (ref $check eq 'Regexp') {
    100          
    50          
224 15         23 my $value = $payload->{$claim};
225 15 100       29 $value = "" if !defined $value;
226 15 100       839 croak "JWT: $claim claim re check failed" unless $value =~ $check;
227             }
228             elsif (ref $check eq 'CODE') {
229 14 100       32 croak "JWT: $claim claim code check failed" unless $check->($payload->{$claim});
230             }
231             elsif (!ref $check) {
232 14         22 my $value = $payload->{$claim};
233 14 100 66     530 croak "JWT: $claim claim scalar check failed" unless defined $value && $value eq $check;
234             }
235             else {
236 0         0 croak "JWT: verify_$claim must be Regexp, Scalar or CODE";
237             }
238             }
239             else {
240 4         620 croak "JWT: $claim claim required but missing"
241             }
242             }
243              
244             }
245              
246             sub _payload_zip {
247 4     4   10 my ($payload, $header, $z) = @_;
248 4 100       18 my @zip = ref $z eq 'ARRAY' ? @$z : ($z);
249 4 50       12 if ($zip[0] eq 'deflate') {
250 4 100       13 my $level = defined $zip[1] ? $zip[1] : 6;
251 4         11 $header->{zip} = "DEF";
252 4         19 my $d = Compress::Raw::Zlib::Deflate->new(-Bufsize => 1024, -WindowBits => -&MAX_WBITS(), -AppendOutput => 1, -Level => $level );
253 4         3310 my $output = '';
254 4 50       53 $d->deflate($payload, $output) == Z_OK or croak "JWT: deflate failed";
255 4 50       221 $d->flush($output) == Z_OK or croak "JWT: deflate/flush failed";
256 4 50       31 croak "JWT: deflate/output failed" unless $output;
257 4         167 $payload = $output;
258             }
259             else {
260 0         0 croak "JWT: unknown zip method '$zip[0]'";
261             }
262 4         20 return $payload;
263             }
264              
265             sub _payload_unzip {
266 15     15   35 my ($payload, $z) = @_;
267 15 50       43 if ($z eq "DEF") {
268 15         79 my $d = Compress::Raw::Zlib::Inflate->new(-Bufsize => 1024, -WindowBits => -&MAX_WBITS());
269 15         6715 my $output = '';
270 15         222 $d->inflate($payload, $output);
271 15 50       58 croak "JWT: inflate failed" unless $output;
272 15         77 $payload = $output;
273             }
274             else {
275 0         0 croak "JWT: unknown zip method '$z'";
276             }
277 15         37 return $payload;
278             }
279              
280             sub _payload_enc {
281 148     148   282 my ($payload) = @_;
282 148 100       424 if (ref($payload) =~ /^(HASH|ARRAY)$/) {
283 21         364 $payload = JSON->new->utf8->canonical->encode($payload);
284             }
285             else {
286 127 50       437 utf8::downgrade($payload, 1) or croak "JWT: payload cannot contain wide character";
287             }
288 148         344 return $payload;
289             }
290              
291             sub _payload_dec {
292 267     267   822 my ($payload, $decode_payload) = @_;
293 267 100 100     969 return $payload if defined $decode_payload && $decode_payload == 0;
294 205         334 my $de = $payload;
295 205         297 $de = eval { decode_json($de) };
  205         2321  
296 205 100       548 if ($decode_payload) {
297 14 50       33 croak "JWT: payload not a valid JSON" unless $de;
298 14         32 return $de;
299             }
300             else {
301 191 100       564 return defined $de ? $de : $payload;
302             }
303             }
304              
305             sub _encrypt_jwe_cek {
306 115     115   236 my ($key, $hdr) = @_;
307 115         184 my $alg = $hdr->{alg};
308 115         182 my $enc = $hdr->{enc};
309              
310 115 100       232 if ($alg eq 'dir') {
311 12         27 return (_prepare_oct_key($key), '');
312             }
313              
314 103         184 my $cek;
315             my $ecek;
316 103 100       474 if ($enc =~ /^A(128|192|256)GCM/) {
    50          
317 55         345 $cek = random_bytes($1/8);
318             }
319             elsif ($enc =~ /^A(128|192|256)CBC/) {
320 48         327 $cek = random_bytes(2*$1/8);
321             }
322              
323 103 100       2036 if ($alg =~ /^A(128|192|256)KW$/) {
    100          
    100          
    100          
    100          
    50          
324 18         48 $ecek = aes_key_wrap(_prepare_oct_key($key), $cek);
325 18         62 return ($cek, $ecek);
326             }
327             elsif ($alg =~ /^A(128|192|256)GCMKW$/) {
328 18         28 my ($t, $i);
329 18         36 ($ecek, $t, $i) = gcm_key_wrap(_prepare_oct_key($key), $cek);
330 18         77 $hdr->{tag} = encode_b64u($t);
331 18         42 $hdr->{iv} = encode_b64u($i);
332 18         60 return ($cek, $ecek);
333             }
334             elsif ($alg =~ /^PBES2-HS(512|384|256)\+A(128|192|256)KW$/) {
335 24 50 33     207 my $len = looks_like_number($hdr->{p2s}) && $hdr->{p2s} >= 8 && $hdr->{p2s} <= 9999 ? $hdr->{p2s} : 16;
336 24         81 my $salt = random_bytes($len);
337 24 50       278 my $iter = looks_like_number($hdr->{p2c}) ? $hdr->{p2c} : 5000;
338 24         102 $ecek = pbes2_key_wrap(_prepare_oct_key($key), $cek, $alg, $salt, $iter);
339 24         157 $hdr->{p2s} = encode_b64u($salt);
340 24         67 $hdr->{p2c} = $iter;
341 24         121 return ($cek, $ecek);
342             }
343             elsif ($alg =~ /^RSA(-OAEP|-OAEP-256|1_5)$/) {
344 18         47 $key = _prepare_rsa_key($key);
345 18         63 $ecek = rsa_key_wrap($key, $cek, $alg);
346 18         72 return ($cek, $ecek);
347             }
348             elsif ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
349 19         62 $key = _prepare_ecdh_key($key);
350 19         108 ($ecek, $hdr->{epk}) = ecdhaes_key_wrap($key, $cek, $alg, $hdr->{apu}, $hdr->{apv});
351 19         2452 return ($cek, $ecek);
352             }
353             elsif ($alg eq 'ECDH-ES') {
354 6         15 $key = _prepare_ecdh_key($key);
355 6         34 ($cek, $hdr->{epk}) = ecdh_key_wrap($key, $enc, $hdr->{apu}, $hdr->{apv});
356 6         770 return ($cek, '');
357             }
358 0         0 croak "JWE: unknown alg '$alg'";
359             }
360              
361             sub _decrypt_jwe_cek {
362 168     168   393 my ($ecek, $key, $hdr) = @_;
363 168         303 my $alg = $hdr->{alg};
364 168         274 my $enc = $hdr->{enc};
365              
366 168 100       1172 if ($alg eq 'dir') {
    100          
    100          
    100          
    100          
    100          
    50          
367 18         43 return _prepare_oct_key($key);
368             }
369             elsif ($alg =~ /^A(128|192|256)KW$/) {
370 22         54 return aes_key_unwrap(_prepare_oct_key($key), $ecek);
371             }
372             elsif ($alg =~ /^A(128|192|256)GCMKW$/) {
373 22         57 return gcm_key_unwrap(_prepare_oct_key($key), $ecek, decode_b64u($hdr->{tag}), decode_b64u($hdr->{iv}));
374             }
375             elsif ($alg =~ /^PBES2-HS(512|384|256)\+A(128|192|256)KW$/) {
376 39         124 return pbes2_key_unwrap(_prepare_oct_key($key), $ecek, $alg, decode_b64u($hdr->{p2s}), $hdr->{p2c});
377             }
378             elsif ($alg =~ /^RSA(-OAEP|-OAEP-256|1_5)$/) {
379 35         92 $key = _prepare_rsa_key($key);
380 35         4746 return rsa_key_unwrap($key, $ecek, $alg);
381             }
382             elsif ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
383 22         62 $key = _prepare_ecdh_key($key);
384 22         177 return ecdhaes_key_unwrap($key, $ecek, $alg, $hdr->{epk}, $hdr->{apu}, $hdr->{apv});
385             }
386             elsif ($alg eq 'ECDH-ES') {
387 10         23 $key = _prepare_ecdh_key($key);
388 10         64 return ecdh_key_unwrap($key, $enc, $hdr->{epk}, $hdr->{apu}, $hdr->{apv});
389             }
390 0         0 croak "JWE: unknown alg '$alg'";
391             }
392              
393             sub _encrypt_jwe_payload {
394 115     115   317 my ($cek, $enc, $b64u_header, $b64u_aad, $payload) = @_;
395 115 50       245 my $aad = defined $b64u_aad ? "$b64u_header.$b64u_aad" : $b64u_header;
396 115 100       853 if ($enc =~ /^A(128|192|256)GCM$/) {
    50          
397             # https://tools.ietf.org/html/rfc7518#section-5.3
398 61         243 my $len1 = $1/8;
399 61         107 my $len2 = length($cek);
400 61 50       168 croak "JWE: wrong AES key length ($len1 vs. $len2) for $enc" unless $len1 == $len2;
401 61         202 my $iv = random_bytes(12); # for AESGCM always 12 (96 bits)
402 61         13044 my ($ct, $tag) = gcm_encrypt_authenticate('AES', $cek, $iv, $aad, $payload);
403 61         315 return ($ct, $iv, $tag);
404             }
405             elsif ($enc =~ /^A(128|192|256)CBC-HS(256|384|512)$/) {
406             # https://tools.ietf.org/html/rfc7518#section-5.2
407 54         309 my ($size, $hash) = ($1/8, "SHA$2");
408 54         111 my $key_len = length($cek) / 2;
409 54         131 my $mac_key = substr($cek, 0, $key_len);
410 54         121 my $aes_key = substr($cek, $key_len, $key_len);
411 54 50       127 croak "JWE: wrong AES key length ($key_len vs. $size)" unless $key_len == $size;
412 54         185 my $iv = random_bytes(16); # for AES always 16
413 54         810 my $m = Crypt::Mode::CBC->new('AES');
414 54         220 my $ct = $m->encrypt($payload, $aes_key, $iv);
415 54         1118 my $aad_len = length($aad);
416 54         297 my $mac_input = $aad . $iv . $ct . pack('N2', ($aad_len / 2147483647)*8, ($aad_len % 2147483647)*8);
417 54         645 my $mac = hmac($hash, $mac_key, $mac_input);
418 54         112 my $sig_len = length($mac) / 2;
419 54         115 my $sig = substr($mac, 0, $sig_len);
420 54         333 return ($ct, $iv, $sig);
421             }
422 0         0 croak "JWE: unsupported enc '$enc'";
423             }
424              
425             sub _decrypt_jwe_payload {
426 168     168   526 my ($cek, $enc, $aad, $ct, $iv, $tag) = @_;
427 168 100       1383 if ($enc =~ /^A(128|192|256)GCM$/) {
    50          
428             # https://tools.ietf.org/html/rfc7518#section-5.3
429 89         368 my $len1 = $1/8;
430 89         161 my $len2 = length($cek);
431 89 50       226 croak "JWE: wrong AES key length ($len1 vs. $len2) for $enc" unless $len1 == $len2;
432 89         17926 return gcm_decrypt_verify('AES', $cek, $iv, $aad, $ct, $tag);
433             }
434             elsif ($enc =~ /^A(128|192|256)CBC-HS(256|384|512)$/) {
435             # https://tools.ietf.org/html/rfc7518#section-5.2
436 79         492 my ($size, $hash) = ($1/8, "SHA$2");
437 79         179 my $key_len = length($cek) / 2;
438 79         173 my $mac_key = substr($cek, 0, $key_len);
439 79         135 my $aes_key = substr($cek, $key_len, $key_len);
440 79 50       209 croak "JWE: wrong AES key length ($key_len vs. $size)" unless $key_len == $size;
441 79         156 my $aad_len = length($aad); # AAD == original encoded header
442 79         440 my $mac_input = $aad . $iv . $ct . pack('N2', ($aad_len / 2147483647)*8, ($aad_len % 2147483647)*8);
443 79         999 my $mac = hmac($hash, $mac_key, $mac_input);
444 79         186 my $sig_len = length($mac) / 2;
445 79         166 my $sig = substr($mac, 0, $sig_len);
446 79 50       200 croak "JWE: tag mismatch" unless $sig eq $tag;
447 79         467 my $m = Crypt::Mode::CBC->new('AES');
448 79         363 my $pt = $m->decrypt($ct, $aes_key, $iv);
449 79         1995 return $pt;
450             }
451 0         0 croak "JWE: unsupported enc '$enc'";
452             }
453              
454             sub _encode_jwe {
455 115     115   341 my %args = @_;
456 115         208 my $payload = $args{payload};
457 115         174 my $alg = $args{alg};
458 115         173 my $enc = $args{enc};
459 115 100       260 my $header = $args{extra_headers} ? \%{$args{extra_headers}} : {};
  2         7  
460 115 50       294 croak "JWE: missing 'enc'" if !defined $enc;
461 115 50       243 croak "JWE: missing 'payload'" if !defined $payload;
462             # add claims to payload
463 115 100       312 _add_claims($payload, %args) if ref $payload eq 'HASH';
464             # serialize payload
465 115         306 $payload = _payload_enc($payload);
466             # compress payload
467 115 100       301 $payload = _payload_zip($payload, $header, $args{zip}) if $args{zip}; # may set some header items
468             # prepare header
469 115         243 $header->{alg} = $alg;
470 115         212 $header->{enc} = $enc;
471             # key
472 115 50       271 croak "JWE: missing 'key'" if !$args{key};
473 115 50       260 my $key = defined $args{keypass} ? [$args{key}, $args{keypass}] : $args{key};
474             # prepare cek
475 115         269 my ($cek, $ecek) = _encrypt_jwe_cek($key, $header); # adds some header items
476             # encode header
477 115         758 my $json_header = encode_json($header);
478 115         353 my $b64u_header = encode_b64u($json_header);
479 115 50       330 my $b64u_aad = defined $args{aad} ? encode_b64u($args{aad}) : undef;
480             # encrypt payload
481 115         366 my ($ct, $iv, $tag) = _encrypt_jwe_payload($cek, $enc, $b64u_header, $b64u_aad, $payload);
482             # return token parts
483 115         1209 return ( $b64u_header,
484             encode_b64u($ecek),
485             encode_b64u($iv),
486             encode_b64u($ct),
487             encode_b64u($tag),
488             $b64u_aad);
489             }
490              
491             sub _decode_jwe {
492 174     174   1284 my ($b64u_header, $b64u_ecek, $b64u_iv, $b64u_ct, $b64u_tag, $b64u_aad, $unprotected, $shared_unprotected, %args) = @_;
493 174         532 my $header = _b64u_to_hash($b64u_header);
494 174         517 my $ecek = decode_b64u($b64u_ecek);
495 174         471 my $ct = decode_b64u($b64u_ct);
496 174         349 my $iv = decode_b64u($b64u_iv);
497 174         363 my $tag = decode_b64u($b64u_tag);
498 174 50 33     770 croak "JWE: invalid header part" if $b64u_header && !$header;
499 174 50 66     540 croak "JWE: invalid ecek part" if $b64u_ecek && !$ecek;
500 174 50 33     528 croak "JWE: invalid ct part" if $b64u_ct && !$ct;
501 174 50 33     588 croak "JWE: invalid iv part" if $b64u_iv && !$iv;
502 174 50 33     505 croak "JWE: invalid tag part" if $b64u_tag && !$tag;
503              
504 174         230 my $key;
505 174 100       348 if (exists $args{key}) {
    50          
506 172 50       432 $key = defined $args{keypass} ? [$args{key}, $args{keypass}] : $args{key};
507             }
508             elsif (exists $args{kid_keys}) {
509             # BEWARE: stricter approach since 0.023
510             # when 'kid_keys' specified it croaks if header doesn't contain 'kid' value or if 'kid' wasn't found in 'kid_keys'
511 2         11 my $k = _kid_lookup($header->{kid}, $args{kid_keys}, $header->{alg});
512 2 50       7 croak "JWE: kid_keys lookup failed" if !defined $k;
513 2         6 $key = $k;
514             }
515 174 50       374 croak "JWE: missing key" if !defined $key;
516              
517 174         269 my $aa = $args{accepted_alg};
518 174 100 66     659 if (ref($aa) eq 'Regexp') {
    100 66        
519 1 50       159 croak "JWE: alg '$header->{alg}' does not match accepted_alg" if $header->{alg} !~ $aa;
520             }
521             elsif ($aa && (ref($aa) eq 'ARRAY' || !ref($aa))) {
522 5 100       18 my %acca = ref $aa ? map { $_ => 1 } @$aa : ( $aa => 1 );
  5         15  
523 5 100       407 croak "JWE: alg '$header->{alg}' not in accepted_alg" if !$acca{$header->{alg}};
524             }
525              
526 171         272 my $ae = $args{accepted_enc};
527 171 100 66     563 if (ref($ae) eq 'Regexp') {
    100 66        
528 1 50       134 croak "JWE: enc '$header->{enc}' does not match accepted_enc" if $header->{enc} !~ $ae;
529             }
530             elsif ($ae && (ref($ae) eq 'ARRAY' || !ref($ae))) {
531 5 100       15 my %acce = ref $ae ? map { $_ => 1 } @$ae : ( $ae => 1 );
  5         15  
532 5 100       336 croak "JWE: enc '$header->{enc}' not in accepted_enc" if !$acce{$header->{enc}};
533             }
534              
535 168         907 $header = { %$shared_unprotected, %$unprotected, %$header }; # merge headers
536 168         455 my $cek = _decrypt_jwe_cek($ecek, $key, $header);
537 168 50       497 my $aad = defined $b64u_aad ? "$b64u_header.$b64u_aad" : $b64u_header;
538 168         531 my $payload = _decrypt_jwe_payload($cek, $header->{enc}, $aad, $ct, $iv, $tag);
539 168 100       588 $payload = _payload_unzip($payload, $header->{zip}) if $header->{zip};
540 168         594 $payload = _payload_dec($payload, $args{decode_payload});
541 168         849 _verify_claims($payload, %args); # croaks on error
542 168         789 return ($header, $payload);
543             }
544              
545             sub _sign_jws {
546 33     33   85 my ($b64u_header, $b64u_payload, $alg, $key) = @_;
547 33 100       76 return '' if $alg eq 'none'; # no integrity
548 32         46 my $sig;
549 32         82 my $data = "$b64u_header.$b64u_payload";
550 32 100       162 if ($alg =~ /^HS(256|384|512)$/) { # HMAC integrity
    100          
    100          
    100          
    50          
551 19         42 $key = _prepare_oct_key($key);
552 19         234 $sig = hmac("SHA$1", $key, $data);
553             }
554             elsif ($alg =~ /^RS(256|384|512)/) { # RSA+PKCS1-V1_5 signatures
555 5         13 my $pk = _prepare_rsa_key($key);
556 5         27525 $sig = $pk->sign_message($data, "SHA$1", 'v1.5');
557             }
558             elsif ($alg =~ /^PS(256|384|512)/) { # RSA+PSS signatures
559 3         10 my $hash = "SHA$1";
560 3         11 my $hashlen = $1/8;
561 3         9 my $pk = _prepare_rsa_key($key);
562 3         16263 $sig = $pk->sign_message($data, $hash, 'pss', $hashlen);
563             }
564             elsif ($alg =~ /^ES(256|256K|384|512)$/) { # ECDSA signatures
565 4         17 my $hash = {ES256 => 'SHA256', ES256K => 'SHA256', ES384 => 'SHA384', ES512 => 'SHA512'}->{$alg};
566 4         21 my $pk = _prepare_ecc_key($key);
567 4         20993 $sig = $pk->sign_message_rfc7518($data, $hash);
568             }
569             elsif ($alg eq 'EdDSA') { # Ed25519 signatures
570 1         5 my $pk = _prepare_ed25519_key($key);
571 1         6250 $sig = $pk->sign_message($data);
572             }
573 32         183 return encode_b64u($sig);
574             }
575              
576             sub _verify_jws {
577 98     98   251 my ($b64u_header, $b64u_payload, $b64u_sig, $alg, $key) = @_;
578 98         321 my $sig = decode_b64u($b64u_sig);
579 98 50 33     345 croak "JWS: invalid sig part" if $b64u_sig && !$sig;
580 98         233 my $data = "$b64u_header.$b64u_payload";
581              
582 98 50       599 if ($alg eq 'none' ) { # no integrity
    100          
    100          
    100          
    100          
    50          
583 0         0 return 1;
584             }
585             elsif ($alg =~ /^HS(256|384|512)$/) { # HMAC integrity
586 62         128 $key = _prepare_oct_key($key);
587 62 50       832 return 1 if $sig eq hmac("SHA$1", $key, $data);
588             }
589             elsif ($alg =~ /^RS(256|384|512)/) { # RSA+PKCS1-V1_5 signatures
590 20         59 my $hash = "SHA$1";
591 20         53 my $pk = _prepare_rsa_key($key);
592 19 50       8026 return 1 if $pk->verify_message($sig, $data, $hash, 'v1.5');
593             }
594             elsif ($alg =~ /^PS(256|384|512)/) { # RSA+PSS signatures
595 6         42 my $hash = "SHA$1";
596 6         30 my $hashlen = $1/8;
597 6         20 my $pk = _prepare_rsa_key($key);
598 6 50       2063 return 1 if $pk->verify_message($sig, $data, $hash, 'pss', $hashlen);
599             }
600             elsif ($alg =~ /^ES(256|256K|384|512)$/) { # ECDSA signatures
601 9         55 my $hash = {ES256 => 'SHA256', ES256K => 'SHA256', ES384 => 'SHA384', ES512 => 'SHA512'}->{$alg};
602 9         37 my $pk = _prepare_ecc_key($key);
603 8 50       50670 return 1 if $pk->verify_message_rfc7518($sig, $data, $hash);
604             }
605             elsif ($alg eq 'EdDSA') { # Ed25519 signatures
606 1         4 my $pk = _prepare_ed25519_key($key);
607 1 50       6194 return 1 if $pk->verify_message($sig, $data);
608             }
609 0         0 return 0;
610             }
611              
612             sub _encode_jws {
613 34     34   96 my %args = @_;
614 34         65 my $payload = $args{payload};
615 34         57 my $alg = $args{alg};
616 34 100       86 my $header = $args{extra_headers} ? \%{$args{extra_headers}} : {};
  2         5  
617 34 50       85 croak "JWS: missing 'payload'" if !defined $payload;
618 34 100 100     200 croak "JWS: alg 'none' not allowed" if $alg eq 'none' && !$args{allow_none};
619             # add claims to payload
620 33 100       107 _add_claims($payload, %args) if ref $payload eq 'HASH';
621             # serialize payload
622 33         83 $payload = _payload_enc($payload);
623             # compress payload
624 33 100       88 $payload = _payload_zip($payload, $header, $args{zip}) if $args{zip}; # may set some header items
625             # encode payload
626 33         123 my $b64u_payload = encode_b64u($payload);
627             # prepare header
628 33         78 $header->{alg} = $alg;
629             # encode header
630 33         156 my $json_header = encode_json($header);
631 33         84 my $b64u_header = encode_b64u($json_header);
632             # key
633 33 50 66     124 croak "JWS: missing 'key'" if !$args{key} && $alg ne 'none';
634 33 50       79 my $key = defined $args{keypass} ? [$args{key}, $args{keypass}] : $args{key};
635             # sign header
636 33         80 my $b64u_signature = _sign_jws($b64u_header, $b64u_payload, $alg, $key);
637 33         182 return ($b64u_header, $b64u_payload, $b64u_signature);
638             }
639              
640             sub _decode_jws {
641 105     105   558 my ($b64u_header, $b64u_payload, $b64u_sig, $unprotected_header, %args) = @_;
642 105         280 my $header = _b64u_to_hash($b64u_header);
643 105 50 33     492 croak "JWS: invalid header part" if $b64u_header && !$header;
644 105 100       233 $unprotected_header = {} if ref $unprotected_header ne 'HASH';
645              
646 105 100       236 if (!$args{ignore_signature}) {
647 104         181 my $alg = $header->{alg};
648 104 50       194 croak "JWS: missing header 'alg'" unless $alg;
649 104 100 100     330 croak "JWS: alg 'none' not allowed" if $alg eq 'none' && !$args{allow_none};
650 103 50 66     232 croak "JWS: alg 'none' expects no signature" if $alg eq 'none' && defined $b64u_sig && length($b64u_sig) > 0;
      66        
651              
652 103         158 my $aa = $args{accepted_alg};
653 103 100       348 if (ref $aa eq 'Regexp') {
    100          
    100          
654 1 50       139 croak "JWS: alg '$alg' does not match accepted_alg" if $alg !~ $aa;
655             }
656             elsif (ref $aa eq 'ARRAY') {
657 2         6 my %acca = map { $_ => 1 } @$aa;
  5         15  
658 2 100       234 croak "JWS: alg '$alg' not in accepted_alg" if !$acca{$alg};
659             }
660             elsif (defined $aa) {
661 3 100       117 croak "JWS: alg '$alg' not accepted_alg" if $aa ne $alg;
662             }
663              
664 100 100       203 if ($alg ne 'none') {
665 98         126 my $key;
666 98 100       188 if (exists $args{key}) {
    100          
    50          
667 95 50       216 $key = defined $args{keypass} ? [$args{key}, $args{keypass}] : $args{key};
668             }
669             elsif (exists $args{kid_keys}) {
670             # BEWARE: stricter approach since 0.023
671             # when 'kid_keys' specified it croaks if header doesn't contain 'kid' value or if 'kid' wasn't found in 'kid_keys'
672 2 50       7 my $kid = exists $header->{kid} ? $header->{kid} : $unprotected_header->{kid};
673 2         7 my $k = _kid_lookup($kid, $args{kid_keys}, $alg);
674 2 50       7 croak "JWS: kid_keys lookup failed" if !defined $k;
675 2         4 $key = $k;
676             }
677             elsif ($args{key_from_jwk_header}) {
678             # BEWARE: stricter approach since 0.023
679             # - header 'jwk' is by default ignored (unless given: key_from_jwk_header => 1)
680             # - only RSA/ECDSA public keys are accepted
681 1         2 my $k = $header->{jwk};
682 1 50 33     8 croak "JWS: jwk header does not contain a key" if !defined $k || ref($k) ne 'HASH' || !defined $k->{kty};
      33        
683 1 50 33     13 croak "JWS: jwk header allowed only for RSA/ECDSA" if $alg !~ /^(RS|PS|ES)/ || $k->{kty} !~ /^(RSA|EC)$/;
684 1 50 33     18 croak "JWS: jwk header must be a public key" if $k->{d} || $k->{p} || $k->{q} || $k->{dp} || $k->{dq} || $k->{qi};
      33        
      33        
      33        
      33        
685 1         2 $key = $k;
686             }
687 98 50       206 croak "JWS: missing key" if !defined $key;
688              
689 98         232 my $valid = _verify_jws($b64u_header, $b64u_payload, $b64u_sig, $alg, $key);
690 96 50       332 croak "JWS: invalid signature" if !$valid;
691             }
692             }
693 99         302 my $payload = decode_b64u($b64u_payload);
694 99 50 66     364 croak "JWS: invalid payload part" if $b64u_payload && !$payload;
695 99 100       237 $payload = _payload_unzip($payload, $header->{zip}) if $header->{zip};
696 99         351 $payload = _payload_dec($payload, $args{decode_payload});
697 99         421 _verify_claims($payload, %args); # croaks on error
698 68         389 $header = { %$unprotected_header, %$header }; # merge headers
699 68         246 return ($header, $payload);
700             }
701              
702             sub encode_jwt {
703 149     149 1 226118 my %args = @_;
704              
705 149 50       527 croak "JWT: missing 'alg'" unless $args{alg};
706 149   50     651 my $ser = $args{serialization} || 'compact';
707 149 100       1340 if ($args{alg} =~ /^(none|EdDSA|(HS|RS|PS)(256|384|512)|ES(256|256K|384|512))$/) {
    50          
708             ###JWS
709 34         131 my ($b64u_header, $b64u_payload, $b64u_signature) = _encode_jws(%args);
710 33 50       113 if ($ser eq 'compact') { # https://tools.ietf.org/html/rfc7515#section-7.1
    0          
711 33 50       100 croak "JWT: cannot use 'unprotected_headers' with compact serialization" if defined $args{unprotected_headers};
712 33         197 return "$b64u_header.$b64u_payload.$b64u_signature";
713             }
714             elsif ($ser eq 'flattened') { # https://tools.ietf.org/html/rfc7515#section-7.2.2
715 0         0 my $token = { protected => $b64u_header, payload => $b64u_payload, signature => $b64u_signature };
716 0 0       0 $token->{header} = \%{$args{unprotected_headers}} if ref $args{unprotected_headers} eq 'HASH';
  0         0  
717 0         0 return encode_json($token);
718             }
719             else {
720 0         0 croak "JWT: unsupported JWS serialization '$ser'";
721             }
722             }
723             elsif ($args{alg} =~ /^(dir|A(128|192|256)KW|A(128|192|256)GCMKW|PBES2-(HS256\+A128KW|HS384\+A192KW|HS512\+A256KW)|RSA-OAEP|RSA-OAEP-256|RSA1_5|ECDH-ES\+A(128|192|256)KW|ECDH-ES)$/) {
724             ### JWE
725 115         482 my ($b64u_header, $b64u_ecek, $b64u_iv, $b64u_ct, $b64u_tag, $b64u_aad) = _encode_jwe(%args);
726 115 50       483 if ($ser eq 'compact') { # https://tools.ietf.org/html/rfc7516#section-7.1
    0          
727 115 50       319 croak "JWT: cannot use 'aad' with compact serialization" if defined $args{aad};
728 115 50       251 croak "JWT: cannot use 'unprotected_headers' with compact serialization" if defined $args{unprotected_headers};
729 115 50       211 croak "JWT: cannot use 'shared_unprotected_headers' with compact serialization" if defined $args{shared_unprotected_headers};
730 115         781 return "$b64u_header.$b64u_ecek.$b64u_iv.$b64u_ct.$b64u_tag";
731             }
732             elsif ($ser eq 'flattened') { # https://tools.ietf.org/html/rfc7516#section-7.2.2
733 0         0 my $token = {
734             protected => $b64u_header,
735             encrypted_key => $b64u_ecek,
736             iv => $b64u_iv,
737             ciphertext => $b64u_ct,
738             tag => $b64u_tag,
739             };
740             # header: JWE Per-Recipient Unprotected Header when the JWE Per-Recipient Unprotected Header
741 0 0       0 $token->{header} = \%{$args{unprotected_headers}} if ref $args{unprotected_headers} eq 'HASH';
  0         0  
742             # unprotected: JWE Shared Unprotected Header
743 0 0       0 $token->{unprotected} = \%{$args{shared_unprotected_headers}} if ref $args{shared_unprotected_headers} eq 'HASH';
  0         0  
744             # aad: Additional Authenticated Data (AAD)
745 0 0       0 $token->{aad} = $b64u_aad if defined $b64u_aad;
746 0         0 return encode_json($token);
747             }
748             else {
749 0         0 croak "JWT: unsupported JWE serialization '$ser'";
750             }
751             }
752             else {
753 0         0 croak "JWT: unexpected alg '$args{alg}'";
754             }
755             }
756              
757             sub decode_jwt {
758 279     279 1 129409 my %args = @_;
759 279         599 my ($header, $payload);
760              
761 279 50       4351 if (!$args{token}) {
    100          
    100          
    50          
762 0         0 croak "JWT: missing token";
763             }
764             elsif ($args{token} =~ /^([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]*)=*\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*$/) {
765             # JWE token (5 segments)
766 173         914 ($header, $payload) = _decode_jwe($1, $2, $3, $4, $5, undef, {}, {}, %args);
767             }
768             elsif ($args{token} =~ /^([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]*)=*$/) {
769             # JWS token (3 segments)
770 103         456 ($header, $payload) = _decode_jws($1, $2, $3, {}, %args);
771             }
772             elsif ($args{token} =~ /^\s*\{.*?\}\s*$/s) {
773 3         30 my $hash = decode_json($args{token});
774 3 100 66     24 if (defined $hash->{payload} && $hash->{protected}) {
    50 33        
775             # Flattened JWS JSON Serialization
776 2         15 ($header, $payload) = _decode_jws($hash->{protected}, $hash->{payload}, $hash->{signature}, $hash->{header}, %args);
777             }
778             elsif ($hash->{ciphertext} && $hash->{protected}) {
779             # Flattened JWE JSON Serialization
780 1         8 ($header, $payload) = _decode_jwe($hash->{protected}, $hash->{encrypted_key}, $hash->{iv}, $hash->{ciphertext}, $hash->{tag}, $hash->{aad}, $hash->{header}, $hash->{unprotected}, %args);
781             }
782             else {
783 0         0 croak "JWT: unsupported JWS/JWT JSON Serialization";
784             }
785             }
786             else {
787 0         0 croak "JWT: invalid token format";
788             }
789 236 100       1001 return ($header, $payload) if $args{decode_header};
790 228         980 return $payload;
791             }
792              
793             1;
794              
795             #### URLs
796             # https://metacpan.org/pod/JSON::WebToken
797             # https://metacpan.org/pod/Mojo::JWT
798             # https://bitbucket.org/b_c/jose4j/wiki/JWE%20Examples
799             # https://bitbucket.org/b_c/jose4j/wiki/JWS%20Examples
800             # https://github.com/dvsekhvalnov/jose-jwt/tree/master/JWT/jwe
801             # https://github.com/progrium/ruby-jwt
802             # https://github.com/jpadilla/pyjwt/
803              
804             =pod
805              
806             =head1 NAME
807              
808             Crypt::JWT - JSON Web Token (JWT, JWS, JWE) as defined by RFC7519, RFC7515, RFC7516
809              
810             =head1 SYNOPSIS
811              
812             # encoding
813             use Crypt::JWT qw(encode_jwt);
814             my $jws_token = encode_jwt(payload=>$data, alg=>'HS256', key=>'secret');
815             my $jwe_token = encode_jwt(payload=>$data, alg=>'PBES2-HS256+A128KW', enc=>'A128GCM', key=>'secret');
816              
817             # decoding
818             use Crypt::JWT qw(decode_jwt);
819             my $data1 = decode_jwt(token=>$jws_token, key=>'secret');
820             my $data2 = decode_jwt(token=>$jwe_token, key=>'secret');
821              
822             =head1 DESCRIPTION
823              
824             Implements B - L.
825             The implementation covers not only B - L,
826             but also B - L.
827              
828             The module implements B defined in L - B.
829              
830             This module supports B and B serialization, general JSON serialization is not supported yet.
831              
832             =head1 EXPORT
833              
834             Nothing is exported by default.
835              
836             You can export selected functions:
837              
838             use Crypt::JWT qw(decode_jwt encode_jwt);
839              
840             Or all of them at once:
841              
842             use Crypt::JWT ':all';
843              
844             =head1 FUNCTIONS
845              
846             =head2 decode_jwt
847              
848             my $data = decode_jwt(%named_args);
849              
850             Named arguments:
851              
852             =over
853              
854             =item token
855              
856             Mandatory argument, a string with either JWS or JWE JSON Web Token.
857              
858             ### JWS token example (3 segments)
859             $t = "eyJhbGciOiJIUzI1NiJ9.dGVzdA.ujBihtLSr66CEWqN74SpLUkv28lra_CeHnxLmLNp4Jo";
860             my $data = decode_jwt(token=>$t, key=>$k);
861              
862             ### JWE token example (5 segments)
863             $t = "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtXIn0.UusxEbzhGkORxTRq0xkFKhvzPrXb9smw.VGfOuq0Fxt6TsdqLZUpnxw.JajIQQ.pkKZ7MHS0XjyGmRsqgom6w";
864             my $data = decode_jwt(token=>$t, key=>$k);
865              
866             =item key
867              
868             A key used for token decryption (JWE) or token signature validation (JWS).
869             The value depends on the C token header value.
870              
871             JWS alg header key value
872             ------------------ ----------------------------------
873             none no key required
874             HS256 string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
875             HS384 dtto
876             HS512 dtto
877             RS256 public RSA key, perl HASH ref with JWK key structure,
878             a reference to SCALAR string with PEM or DER or JSON/JWK data,
879             object: Crypt::PK::RSA, Crypt::OpenSSL::RSA, Crypt::X509 or Crypt::OpenSSL::X509
880             RS384 public RSA key, see RS256
881             RS512 public RSA key, see RS256
882             PS256 public RSA key, see RS256
883             PS384 public RSA key, see RS256
884             PS512 public RSA key, see RS256
885             ES256 public ECC key, perl HASH ref with JWK key structure,
886             a reference to SCALAR string with PEM or DER or JSON/JWK data,
887             an instance of Crypt::PK::ECC
888             ES256K public ECC key, see ES256
889             ES384 public ECC key, see ES256
890             ES512 public ECC key, see ES256
891             EdDSA public Ed25519 key
892              
893             JWE alg header key value
894             ------------------ ----------------------------------
895             dir string (raw octects) or perl HASH ref with JWK, kty=>'oct', length depends on 'enc' algorithm
896             A128KW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
897             A192KW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
898             A256KW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
899             A128GCMKW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
900             A192GCMKW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
901             A256GCMKW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
902             PBES2-HS256+A128KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
903             PBES2-HS384+A192KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
904             PBES2-HS512+A256KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
905             RSA-OAEP private RSA key, perl HASH ref with JWK key structure,
906             a reference to SCALAR string with PEM or DER or JSON/JWK data,
907             an instance of Crypt::PK::RSA or Crypt::OpenSSL::RSA
908             RSA-OAEP-256 private RSA key, see RSA-OAEP
909             RSA1_5 private RSA key, see RSA-OAEP
910             ECDH-ES private ECC or X25519 key, perl HASH ref with JWK key structure,
911             a reference to SCALAR string with PEM or DER or JSON/JWK data,
912             an instance of Crypt::PK::ECC
913             ECDH-ES+A128KW private ECC or X25519 key, see ECDH-ES
914             ECDH-ES+A192KW private ECC or X25519 key, see ECDH-ES
915             ECDH-ES+A256KW private ECC or X25519 key, see ECDH-ES
916              
917             Example using the key from C token header:
918              
919             my $data = decode_jwt(token=>$t, key_from_jwk_header=>1);
920             my ($header, $data) = decode_jwt(token=>$t, decode_header=>1, key_from_jwk_header=>1);
921              
922             Examples with raw octet keys:
923              
924             #string
925             my $data = decode_jwt(token=>$t, key=>'secretkey');
926             #binary key
927             my $data = decode_jwt(token=>$t, key=>pack("H*", "788A6E38F36B7596EF6A669E94"));
928             #perl HASH ref with JWK structure (key type 'oct')
929             my $data = decode_jwt(token=>$t, key=>{kty=>'oct', k=>"GawgguFyGrWKav7AX4VKUg"});
930              
931             Examples with RSA keys:
932              
933             my $pem_key_string = <<'EOF';
934             -----BEGIN PRIVATE KEY-----
935             MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCoVm/Sl5r+Ofky
936             jioRSZK26GW6WyjyfWKddsSi13/NOtCn0rRErSF/u3QrgGMpWFqKohqbi1VVC+SZ
937             ...
938             8c1vm2YFafgdkSk9Qd1oU2Fv1aOQy4VovOFzJ3CcR+2r7cbRfcpLGnintHtp9yek
939             02p+d5g4OChfFNDhDtnIqjvY
940             -----END PRIVATE KEY-----
941             EOF
942              
943             my $jwk_key_json_string = '{"kty":"RSA","n":"0vx7agoebG...L6tSoc_BJECP","e":"AQAB"}';
944              
945             #a reference to SCALAR string with PEM or DER or JSON/JWK data,
946             my $data = decode_jwt(token=>$t, key=>\$pem_key_string);
947             my $data = decode_jwt(token=>$t, key=>\$der_key_string);
948             my $data = decode_jwt(token=>$t, key=>\$jwk_key_json_string);
949              
950             #instance of Crypt::PK::RSA
951             my $data = decode_jwt(token=>$t, key=>Crypt::PK::RSA->new('keyfile.pem'));
952             my $data = decode_jwt(token=>$t, key=>Crypt::PK::RSA->new(\$pem_key_string));
953              
954             #instance of Crypt::OpenSSL::RSA
955             my $data = decode_jwt(token=>$t, key=>Crypt::OpenSSL::RSA->new_private_key($pem_key_string));
956              
957             #instance of Crypt::X509 (public key only)
958             my $data = decode_jwt(token=>$t, key=>Crypt::X509->new(cert=>$cert));
959              
960             #instance of Crypt::OpenSSL::X509 (public key only)
961             my $data = decode_jwt(token=>$t, key=>Crypt::OpenSSL::X509->new_from_file('cert.pem'));
962             my $data = decode_jwt(token=>$t, key=>Crypt::OpenSSL::X509->new_from_string($cert));
963              
964             #perl HASH ref with JWK structure (key type 'RSA')
965             my $rsa_priv = {
966             kty => "RSA",
967             n => "0vx7agoebGcQSuuPiLJXZpt...eZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
968             e => "AQAB",
969             d => "X4cTteJY_gn4FYPsXB8rdXi...FLN5EEaG6RoVH-HLKD9Mdx5ooGURknhnrRwUkC7h5fJLMWbFAKLWY2v7B6NqSzUvx0_YSf",
970             p => "83i-7IvMGXoMXCskv73TKr8...Z27zvoj6pbUQyLPBQxtPnwD20-60eTmD2ujMt5PoMrm8RmNhVWtjjMmMjOpSicFHjXOuVI",
971             q => "3dfOR9cuYq-0S-mkFLzgItg...q3hWeMuG0ouqnb3obLyuqjVZQ1dIrdgTnCdYzBcOW5r37AFXjift_NGiovonzhKpoVVS78",
972             dp => "G4sPXkc6Ya9y8oJW9_ILj4...zi_H7TkS8x5SdX3oE0oiYwxIiemTAu0UOa5pgFGyJ4c8t2VF40XRugKTP8akhFo5tA77Qe",
973             dq => "s9lAH9fggBsoFR8Oac2R_E...T2kGOhvIllTE1efA6huUvMfBcpn8lqW6vzzYY5SSF7pMd_agI3G8IbpBUb0JiraRNUfLhc",
974             qi => "GyM_p6JrXySiz1toFgKbWV...4ypu9bMWx3QJBfm0FoYzUIZEVEcOqwmRN81oDAaaBk0KWGDjJHDdDmFW3AN7I-pux_mHZG",
975             };
976             my $data = decode_jwt(token=>$t, key=>$rsa_priv});
977              
978             Examples with ECC keys:
979              
980             my $pem_key_string = <<'EOF';
981             -----BEGIN EC PRIVATE KEY-----
982             MHcCAQEEIBG1c3z52T8XwMsahGVdOZWgKCQJfv+l7djuJjgetdbDoAoGCCqGSM49
983             AwEHoUQDQgAEoBUyo8CQAFPeYPvv78ylh5MwFZjTCLQeb042TjiMJxG+9DLFmRSM
984             lBQ9T/RsLLc+PmpB1+7yPAR+oR5gZn3kJQ==
985             -----END EC PRIVATE KEY-----
986             EOF
987              
988             my $jwk_key_json_string = '{"kty":"EC","crv":"P-256","x":"MKB..7D4","y":"4Et..FyM"}';
989              
990             #a reference to SCALAR string with PEM or DER or JSON/JWK data,
991             my $data = decode_jwt(token=>$t, key=>\$pem_key_string);
992             my $data = decode_jwt(token=>$t, key=>\$der_key_string);
993             my $data = decode_jwt(token=>$t, key=>\$jwk_key_json_string);
994              
995             #instance of Crypt::PK::ECC
996             my $data = decode_jwt(token=>$t, key=>Crypt::PK::ECC->new('keyfile.pem'));
997             my $data = decode_jwt(token=>$t, key=>Crypt::PK::ECC->new(\$pem_key_string));
998              
999             #perl HASH ref with JWK structure (key type 'EC')
1000             my $ecc_priv = {
1001             kty => "EC",
1002             crv => "P-256",
1003             x => "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
1004             y => "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
1005             d => "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
1006             };
1007             my $data = decode_jwt(token=>$t, key=>$ecc_priv});
1008              
1009             =item keypass
1010              
1011             When 'key' parameter is an encrypted private RSA or ECC key this optional parameter may contain a password for private key decryption.
1012              
1013             =item kid_keys
1014              
1015             This parametes can be either a JWK Set JSON string (see RFC7517) or a perl HASH ref with JWK Set structure like this:
1016              
1017             my $keylist = {
1018             keys => [
1019             { kid=>"key1", kty=>"oct", k=>"GawgguFyGrWKav7AX4VKUg" },
1020             { kid=>"key2", kty=>"oct", k=>"ulxLGy4XqhbpkR5ObGh1gX" },
1021             ]
1022             };
1023             my $payload = decode_jwt(token=>$t, kid_keys=>$keylist);
1024              
1025             The structure described above is used e.g. by L
1026              
1027             use Mojo::UserAgent;
1028             my $ua = Mojo::UserAgent->new;
1029             my $google_keys => $ua->get('https://www.googleapis.com/oauth2/v2/certs')->result->json;
1030             my $payload = decode_jwt(token => $t, kid_keys => $google_keys);
1031              
1032             B we also support alternative structure used e.g. by L:
1033              
1034             use LWP::Simple;
1035             my $google_certs = get('https://www.googleapis.com/oauth2/v1/certs');
1036             my $payload = decode_jwt(token => $t, kid_keys => $google_certs);
1037              
1038             When the token header contains C item the corresponding key is looked up in C list and used for token
1039             decoding (you do not need to pass the explicit key via C parameter).
1040              
1041             B When C is specified it croaks if token header does not contain C value or
1042             if C was not found in C.
1043              
1044             =item key_from_jwk_header
1045              
1046             B
1047              
1048             C<1> - use C header value for validating JWS signature if neither C nor C specified, B
1049              
1050             C<0> (default) - ignore C header value when validating JWS signature
1051              
1052             Keep in mind that enabling C requires C header to exist and be an valid RSA/ECDSA public key (otherwise it croaks).
1053              
1054             =item allow_none
1055              
1056             C<1> - accept JWS tokens with C 'alg' header value (which means that token has no signature), B
1057              
1058             C<0> (default) - do not allow JWS with C 'alg' header value
1059              
1060             =item ignore_signature
1061              
1062             C<1> - do not check signature on JWS tokens, B
1063              
1064             C<0> (default) - check signature on JWS tokens
1065              
1066             =item accepted_alg
1067              
1068             C (default) means accept all 'alg' algorithms except 'none' (for accepting 'none' use C)
1069              
1070             C name of accepted 'alg' algorithm (only one)
1071              
1072             C a list of accepted 'alg' algorithms
1073              
1074             C that has to match 'alg' algorithm name
1075              
1076             my $payload = decode_jwt(token=>$t, key=>$k, accepted_alg=>'HS256');
1077             #or
1078             my $payload = decode_jwt(token=>$t, key=>$k, accepted_alg=>['HS256','HS384']);
1079             #or
1080             my $payload = decode_jwt(token=>$t, key=>$k, accepted_alg=>qr/^HS(256|384|512)$/);
1081              
1082             =item accepted_enc
1083              
1084             C (default) means accept all 'enc' algorithms
1085              
1086             C name of accepted 'enc' algorithm (only one)
1087              
1088             C a list of accepted 'enc' algorithms
1089              
1090             C that has to match 'enc' algorithm name
1091              
1092             my $payload = decode_jwt(token=>$t, key=>$k, accepted_enc=>'A192GCM');
1093             #or
1094             my $payload = decode_jwt(token=>$t, key=>$k, accepted_enc=>['A192GCM','A256GCM']);
1095             #or
1096             my $payload = decode_jwt(token=>$t, key=>$k, accepted_enc=>qr/^A(128|192|256)GCM$/);
1097              
1098             =item decode_payload
1099              
1100             C<0> - do not decode payload, return it as a raw string (octects).
1101              
1102             C<1> - decode payload from JSON string, return it as perl hash ref (or array ref) - decode_json failure means fatal error (croak).
1103              
1104             C (default) - if possible decode payload from JSON string, if decode_json fails return payload as a raw string (octets).
1105              
1106             =item decode_header
1107              
1108             C<0> (default) - do not return decoded header as a return value of decode_jwt()
1109              
1110             C<1> - return decoded header as a return value of decode_jwt()
1111              
1112             my $payload = decode_jwt(token=>$t, key=>$k);
1113             #or
1114             my ($header, $payload) = decode_jwt(token=>$t, key=>$k, decode_header=>1);
1115              
1116             =item verify_iss
1117              
1118             B If C is specified and
1119             claim C (Issuer) is completely missing it is a failure since 0.024
1120              
1121             C - subroutine (with 'iss' claim value passed as argument) should return C otherwise verification fails
1122              
1123             C - 'iss' claim value has to match given regexp otherwise verification fails
1124              
1125             C - 'iss' claim value has to be equal to given string (since 0.029)
1126              
1127             C (default) - do not verify 'iss' claim
1128              
1129             =item verify_aud
1130              
1131             B If C is specified and
1132             claim C (Audience) is completely missing it is a failure since 0.024
1133              
1134             C - subroutine (with 'aud' claim value passed as argument) should return C otherwise verification fails
1135              
1136             C - 'aud' claim value has to match given regexp otherwise verification fails
1137              
1138             C - 'aud' claim value has to be equal to given string (since 0.029)
1139              
1140             C (default) - do not verify 'aud' claim
1141              
1142             =item verify_sub
1143              
1144             B If C is specified and
1145             claim C (Subject) is completely missing it is a failure since 0.024
1146              
1147             C - subroutine (with 'sub' claim value passed as argument) should return C otherwise verification fails
1148              
1149             C - 'sub' claim value has to match given regexp otherwise verification fails
1150              
1151             C - 'sub' claim value has to be equal to given string (since 0.029)
1152              
1153             C (default) - do not verify 'sub' claim
1154              
1155             =item verify_jti
1156              
1157             B If C is specified and
1158             claim C (JWT ID) is completely missing it is a failure since 0.024
1159              
1160             C - subroutine (with 'jti' claim value passed as argument) should return C otherwise verification fails
1161              
1162             C - 'jti' claim value has to match given regexp otherwise verification fails
1163              
1164             C - 'jti' claim value has to be equal to given string (since 0.029)
1165              
1166             C (default) - do not verify 'jti' claim
1167              
1168             =item verify_iat
1169              
1170             C - Issued At 'iat' claim must be valid (not in the future) if present
1171              
1172             C<0> (default) - ignore 'iat' claim
1173              
1174             C<1> - require valid 'iat' claim
1175              
1176             =item verify_nbf
1177              
1178             C (default) - Not Before 'nbf' claim must be valid if present
1179              
1180             C<0> - ignore 'nbf' claim
1181              
1182             C<1> - require valid 'nbf' claim
1183              
1184             =item verify_exp
1185              
1186             C (default) - Expiration Time 'exp' claim must be valid if present
1187              
1188             C<0> - ignore 'exp' claim
1189              
1190             C<1> - require valid 'exp' claim
1191              
1192             =item leeway
1193              
1194             Tolerance in seconds related to C, C and C. Default is C<0>.
1195              
1196             =item ignore_claims
1197              
1198             C<1> - do not check claims (iat, exp, nbf, iss, aud, sub, jti), B
1199              
1200             C<0> (default) - check claims
1201              
1202             =back
1203              
1204             =head2 encode_jwt
1205              
1206             my $token = encode_jwt(%named_args);
1207              
1208             Named arguments:
1209              
1210             =over
1211              
1212             =item payload
1213              
1214             Value of this mandatory parameter can be a string/buffer or HASH ref or ARRAY ref
1215              
1216             my $token = encode_jwt(payload=>"any raw data", key=>$k, alg=>'HS256');
1217             #or
1218             my $token = encode_jwt(payload=>{a=>1,b=>2}, key=>$k, alg=>'HS256');
1219             #or
1220             my $token = encode_jwt(payload=>[11,22,33,44], key=>$k, alg=>'HS256');
1221              
1222             HASH refs and ARRAY refs payloads are serialized as JSON strings
1223              
1224             =item alg
1225              
1226             The 'alg' header value is mandatory for both JWE and JWS tokens.
1227              
1228             Supported JWE 'alg' algorithms:
1229              
1230             dir
1231             A128KW
1232             A192KW
1233             A256KW
1234             A128GCMKW
1235             A192GCMKW
1236             A256GCMKW
1237             PBES2-HS256+A128KW
1238             PBES2-HS384+A192KW
1239             PBES2-HS512+A256KW
1240             RSA-OAEP
1241             RSA-OAEP-256
1242             RSA1_5
1243             ECDH-ES+A128KW
1244             ECDH-ES+A192KW
1245             ECDH-ES+A256KW
1246             ECDH-ES
1247              
1248             Supported JWS algorithms:
1249              
1250             none ... no integrity (NOTE: disabled by default)
1251             HS256 ... HMAC+SHA256 integrity
1252             HS384 ... HMAC+SHA384 integrity
1253             HS512 ... HMAC+SHA512 integrity
1254             RS256 ... RSA+PKCS1-V1_5 + SHA256 signature
1255             RS384 ... RSA+PKCS1-V1_5 + SHA384 signature
1256             RS512 ... RSA+PKCS1-V1_5 + SHA512 signature
1257             PS256 ... RSA+PSS + SHA256 signature
1258             PS384 ... RSA+PSS + SHA384 signature
1259             PS512 ... RSA+PSS + SHA512 signature
1260             ES256 ... ECDSA + SHA256 signature
1261             ES256K ... ECDSA + SHA256 signature
1262             ES384 ... ECDSA + SHA384 signature
1263             ES512 ... ECDSA + SHA512 signature
1264             EdDSA ... Ed25519 signature
1265              
1266             =item enc
1267              
1268             The 'enc' header is mandatory for JWE tokens.
1269              
1270             Supported 'enc' algorithms:
1271              
1272             A128GCM
1273             A192GCM
1274             A256GCM
1275             A128CBC-HS256
1276             A192CBC-HS384
1277             A256CBC-HS512
1278              
1279             =item key
1280              
1281             A key used for token encryption (JWE) or token signing (JWS). The value depends on C token header value.
1282              
1283             JWS alg header key value
1284             ------------------ ----------------------------------
1285             none no key required
1286             HS256 string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
1287             HS384 dtto
1288             HS512 dtto
1289             RS256 private RSA key, perl HASH ref with JWK key structure,
1290             a reference to SCALAR string with PEM or DER or JSON/JWK data,
1291             object: Crypt::PK::RSA, Crypt::OpenSSL::RSA, Crypt::X509 or Crypt::OpenSSL::X509
1292             RS384 private RSA key, see RS256
1293             RS512 private RSA key, see RS256
1294             PS256 private RSA key, see RS256
1295             PS384 private RSA key, see RS256
1296             PS512 private RSA key, see RS256
1297             ES256 private ECC key, perl HASH ref with JWK key structure,
1298             a reference to SCALAR string with PEM or DER or JSON/JWK data,
1299             an instance of Crypt::PK::ECC
1300             ES256K private ECC key, see ES256
1301             ES384 private ECC key, see ES256
1302             ES512 private ECC key, see ES256
1303             EdDSA private Ed25519 key
1304              
1305             JWE alg header key value
1306             ------------------ ----------------------------------
1307             dir string (raw octects) or perl HASH ref with JWK, kty=>'oct', length depends on 'enc' algorithm
1308             A128KW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
1309             A192KW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
1310             A256KW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
1311             A128GCMKW string (raw octects) 16 bytes (or perl HASH ref with JWK, kty=>'oct')
1312             A192GCMKW string (raw octects) 24 bytes (or perl HASH ref with JWK, kty=>'oct')
1313             A256GCMKW string (raw octects) 32 bytes (or perl HASH ref with JWK, kty=>'oct')
1314             PBES2-HS256+A128KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
1315             PBES2-HS384+A192KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
1316             PBES2-HS512+A256KW string (raw octects) of any length (or perl HASH ref with JWK, kty=>'oct')
1317             RSA-OAEP public RSA key, perl HASH ref with JWK key structure,
1318             a reference to SCALAR string with PEM or DER or JSON/JWK data,
1319             an instance of Crypt::PK::RSA or Crypt::OpenSSL::RSA
1320             RSA-OAEP-256 public RSA key, see RSA-OAEP
1321             RSA1_5 public RSA key, see RSA-OAEP
1322             ECDH-ES public ECC or X25519 key, perl HASH ref with JWK key structure,
1323             a reference to SCALAR string with PEM or DER or JSON/JWK data,
1324             an instance of Crypt::PK::ECC
1325             ECDH-ES+A128KW public ECC or X25519 key, see ECDH-ES
1326             ECDH-ES+A192KW public ECC or X25519 key, see ECDH-ES
1327             ECDH-ES+A256KW public ECC or X25519 key, see ECDH-ES
1328              
1329             =item keypass
1330              
1331             When 'key' parameter is an encrypted private RSA or ECC key this optional parameter may contain a password for private key decryption.
1332              
1333             =item allow_none
1334              
1335             C<1> - allow JWS with C 'alg' header value (which means that token has no signature), B
1336              
1337             C<0> (default) - do not allow JWS with C 'alg' header value
1338              
1339             =item extra_headers
1340              
1341             This optional parameter may contain a HASH ref with items that will be added to JWT header.
1342              
1343             If you want to use PBES2-based 'alg' like C you can set PBES2 salt len (p2s) in bytes and
1344             iteration count (p2c) via C like this:
1345              
1346             my $token = encode_jwt(payload=>$p, key=>$k, alg=>'PBES2-HS512+A256KW', extra_headers=>{p2c=8000, p2s=>32});
1347             #NOTE: handling of p2s header is a special case, in the end it is replaced with the generated salt
1348              
1349             =item unprotected_headers
1350              
1351             A hash with additional integrity unprotected headers - JWS and JWE (not available for C serialization);
1352              
1353             =item shared_unprotected_headers
1354              
1355             A hash with additional integrity unprotected headers - JWE only (not available for C serialization);
1356              
1357             =item aad
1358              
1359             Additional Authenticated Data - scalar value with any (even raw octects) data - JWE only (not available for C serialization);
1360              
1361             =item serialization
1362              
1363             Specify serialization method: C (= default) for Compact JWS/JWE serialization or C for Flattened JWS/JWE JSON serialization.
1364              
1365             General JSON serialization is not supported yet.
1366              
1367             =item zip
1368              
1369             Compression method, currently 'deflate' is the only one supported. C (default) means no compression.
1370              
1371             my $token = encode_jwt(payload=>$p, key=>$k, alg=>'HS256', zip=>'deflate');
1372             #or define compression level
1373             my $token = encode_jwt(payload=>$p, key=>$k, alg=>'HS256', zip=>['deflate', 9]);
1374              
1375             =item auto_iat
1376              
1377             C<1> - set 'iat' (Issued At) claim to current time (epoch seconds since 1970) at the moment of token encoding
1378              
1379             C<0> (default) - do not set 'iat' claim
1380              
1381             NOTE: claims are part of the payload and can be used only if the payload is a HASH ref!
1382              
1383             =item relative_exp
1384              
1385             Set 'exp' claim (Expiration Time) to current time + C value (in seconds).
1386              
1387             NOTE: claims are part of the payload and can be used only if the payload is a HASH ref!
1388              
1389             =item relative_nbf
1390              
1391             Set 'nbf' claim (Not Before) to current time + C value (in seconds).
1392              
1393             NOTE: claims are part of the payload and can be used only if the payload is a HASH ref!
1394              
1395             =back
1396              
1397             =head1 SEE ALSO
1398              
1399             L, L, L, L, L, L
1400              
1401             =head1 LICENSE
1402              
1403             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1404              
1405             =head1 COPYRIGHT
1406              
1407             Copyright (c) 2015-2021 DCIT, a.s. L / Karel Miko