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   424235 use strict;
  7         70  
  7         213  
4 7     7   35 use warnings;
  7         15  
  7         284  
5              
6             our $VERSION = '0.033';
7              
8 7     7   38 use Exporter 'import';
  7         13  
  7         632  
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   90 use Carp;
  7         30  
  7         568  
14 7     7   3638 use Crypt::Misc qw(decode_b64u encode_b64u);
  7         116382  
  7         596  
15 7     7   4735 use JSON qw(decode_json encode_json);
  7         58684  
  7         38  
16 7     7   5358 use Crypt::PK::RSA;
  7         20547  
  7         329  
17 7     7   4500 use Crypt::PK::ECC;
  7         22752  
  7         350  
18 7     7   3582 use Crypt::PK::Ed25519;
  7         11959  
  7         352  
19 7     7   3614 use Crypt::PK::X25519;
  7         10509  
  7         435  
20 7     7   55 use Crypt::PRNG qw(random_bytes);
  7         17  
  7         377  
21 7     7   3103 use Crypt::KeyWrap ':all';
  7         20  
  7         1182  
22 7     7   55 use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
  7         12  
  7         329  
23 7     7   3452 use Crypt::Mac::HMAC qw(hmac);
  7         8542  
  7         384  
24 7     7   4632 use Compress::Raw::Zlib;
  7         39494  
  7         1597  
25 7     7   58 use Scalar::Util qw(looks_like_number);
  7         19  
  7         53549  
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   185 my ($key) = @_;
36 87 50       221 croak "JWT: undefined RSA key" unless defined $key;
37 87 100       491 croak "JWT: invalid RSA key (cannot be scalar)" unless ref $key;
38             # we need Crypt::PK::RSA object
39 86 100       305 return $key if ref($key) eq 'Crypt::PK::RSA';
40 38 50 66     298 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   33 my ($key) = @_;
59 13 50       33 croak "JWT: undefined ECC key" unless defined $key;
60 13 100       164 croak "JWT: invalid ECC key (cannot be scalar)" unless ref $key;
61             # we need Crypt::PK::ECC object
62 12 100       39 return $key if ref($key) eq 'Crypt::PK::ECC';
63 4 50 33     44 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   6 my ($key) = @_;
70 2 50       8 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       9 return $key if ref($key) eq 'Crypt::PK::Ed25519';
74 2 50 33     30 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       138 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       228 return $key if ref($key) =~ /^Crypt::PK::(ECC|X25519)$/;
86              
87 9 50 33     36 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       44100 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   489 my ($key) = @_;
102 254 50       561 croak "JWT: undefined oct key" unless defined $key;
103 254 100 66     915 if (ref $key eq 'HASH' && $key->{k} && $key->{kty} && $key->{kty} eq 'oct') {
    50 33        
      33        
104 7         46 return decode_b64u($key->{k});
105             }
106             elsif (!ref $key) {
107 247         1051 return $key;
108             }
109 0         0 croak "JWT: invalid oct key";
110             }
111              
112             sub _kid_lookup {
113 4     4   13 my ($kid, $kid_keys, $alg) = @_;
114 4 50 33     18 return undef if !defined $kid || !defined $alg;
115 4 100 66     21 $kid_keys = eval { decode_json($kid_keys) } if $kid_keys && !ref $kid_keys;
  2         16  
116 4 50       14 croak "JWT: kid_keys must be a HASHREF or a valid JSON/HASH" if ref $kid_keys ne 'HASH';
117 4         7 my $found;
118 4 50 33     24 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     43 if ($_->{kid} && $_->{kty} && $_->{kid} eq $kid) {
      66        
122 4         9 $found = $_;
123 4         9 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       9 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   566 my $b64url = shift;
142 279 50       683 return undef unless $b64url;
143 279         1298 my $json = decode_b64u($b64url);
144 279 50       659 return undef unless $json;
145 279         442 my $hash = eval { decode_json($json) };
  279         1854  
146 279 50       941 return undef unless ref $hash eq 'HASH';
147 279         536 return $hash;
148             }
149              
150             sub _add_claims {
151 19     19   58 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         45 my $now = time;
161 19 100       50 $payload->{iat} = $now if $args{auto_iat};
162 19 100       55 $payload->{exp} = $now + $args{relative_exp} if defined $args{relative_exp};
163 19 100       65 $payload->{nbf} = $now + $args{relative_nbf} if defined $args{relative_nbf};
164             }
165              
166             sub _verify_claims {
167 267     267   939 my ($payload, %args) = @_;
168              
169 267 100       715 return if $args{ignore_claims};
170              
171 266 100       699 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         518 for my $claim (qw(exp nbf iat iss sub aud jti)) {
175 1430 100 100     3178 if (defined $args{"verify_$claim"} && $args{"verify_$claim"} != 0) {
176 2         435 croak "JWT: cannot check verify_$claim (payload not decoded JSON/HASH)";
177             }
178             }
179 204         482 return; # nothing to check
180             }
181              
182 60   100     205 my $leeway = $args{leeway} || 0;
183 60         107 my $now = time;
184              
185             ### exp
186 60 100 33     169 if(defined $payload->{exp}) {
    50          
187 45 100 100     139 if (!defined $args{verify_exp} || $args{verify_exp}==1) {
188 41 100       1076 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     161 if(defined $payload->{nbf}) {
    50          
197 30 100 100     72 if (!defined $args{verify_nbf} || $args{verify_nbf}==1) {
198 29 100       405 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       109 if (exists $args{verify_iat}) { #default (non existing verify_iat) == no iat check
207 4 50 0     12 if(defined $payload->{iat}) {
    0          
208 4 100 100     17 if (!defined $args{verify_iat} || $args{verify_iat}==1) {
209 3 100       240 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         108 foreach my $claim (qw(iss sub aud jti)) {
219 165         303 my $check = $args{"verify_$claim"};
220 165 100       333 next unless (defined $check);
221              
222 47 100       110 if (exists $payload->{$claim}) {
223 43 100       95 if (ref $check eq 'Regexp') {
    100          
    50          
224 15         24 my $value = $payload->{$claim};
225 15 100       26 $value = "" if !defined $value;
226 15 100       825 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         19 my $value = $payload->{$claim};
233 14 100 66     535 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         479 croak "JWT: $claim claim required but missing"
241             }
242             }
243              
244             }
245              
246             sub _payload_zip {
247 4     4   11 my ($payload, $header, $z) = @_;
248 4 100       20 my @zip = ref $z eq 'ARRAY' ? @$z : ($z);
249 4 50       12 if ($zip[0] eq 'deflate') {
250 4 100       10 my $level = defined $zip[1] ? $zip[1] : 6;
251 4         11 $header->{zip} = "DEF";
252 4         17 my $d = Compress::Raw::Zlib::Deflate->new(-Bufsize => 1024, -WindowBits => -&MAX_WBITS(), -AppendOutput => 1, -Level => $level );
253 4         3312 my $output = '';
254 4 50       50 $d->deflate($payload, $output) == Z_OK or croak "JWT: deflate failed";
255 4 50       197 $d->flush($output) == Z_OK or croak "JWT: deflate/flush failed";
256 4 50       32 croak "JWT: deflate/output failed" unless $output;
257 4         180 $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   49 my ($payload, $z) = @_;
267 15 50       53 if ($z eq "DEF") {
268 15         78 my $d = Compress::Raw::Zlib::Inflate->new(-Bufsize => 1024, -WindowBits => -&MAX_WBITS());
269 15         6947 my $output = '';
270 15         247 $d->inflate($payload, $output);
271 15 50       50 croak "JWT: inflate failed" unless $output;
272 15         79 $payload = $output;
273             }
274             else {
275 0         0 croak "JWT: unknown zip method '$z'";
276             }
277 15         44 return $payload;
278             }
279              
280             sub _payload_enc {
281 148     148   339 my ($payload) = @_;
282 148 100       437 if (ref($payload) =~ /^(HASH|ARRAY)$/) {
283 21         144 $payload = encode_json($payload);
284             }
285             else {
286 127 50       443 utf8::downgrade($payload, 1) or croak "JWT: payload cannot contain wide character";
287             }
288 148         345 return $payload;
289             }
290              
291             sub _payload_dec {
292 267     267   862 my ($payload, $decode_payload) = @_;
293 267 100 100     1020 return $payload if defined $decode_payload && $decode_payload == 0;
294 205         388 my $de = $payload;
295 205         356 $de = eval { decode_json($de) };
  205         2710  
296 205 100       587 if ($decode_payload) {
297 14 50       36 croak "JWT: payload not a valid JSON" unless $de;
298 14         37 return $de;
299             }
300             else {
301 191 100       580 return defined $de ? $de : $payload;
302             }
303             }
304              
305             sub _encrypt_jwe_cek {
306 115     115   254 my ($key, $hdr) = @_;
307 115         206 my $alg = $hdr->{alg};
308 115         174 my $enc = $hdr->{enc};
309              
310 115 100       289 if ($alg eq 'dir') {
311 12         28 return (_prepare_oct_key($key), '');
312             }
313              
314 103         161 my $cek;
315             my $ecek;
316 103 100       560 if ($enc =~ /^A(128|192|256)GCM/) {
    50          
317 55         374 $cek = random_bytes($1/8);
318             }
319             elsif ($enc =~ /^A(128|192|256)CBC/) {
320 48         374 $cek = random_bytes(2*$1/8);
321             }
322              
323 103 100       2348 if ($alg =~ /^A(128|192|256)KW$/) {
    100          
    100          
    100          
    100          
    50          
324 18         55 $ecek = aes_key_wrap(_prepare_oct_key($key), $cek);
325 18         63 return ($cek, $ecek);
326             }
327             elsif ($alg =~ /^A(128|192|256)GCMKW$/) {
328 18         32 my ($t, $i);
329 18         42 ($ecek, $t, $i) = gcm_key_wrap(_prepare_oct_key($key), $cek);
330 18         83 $hdr->{tag} = encode_b64u($t);
331 18         48 $hdr->{iv} = encode_b64u($i);
332 18         63 return ($cek, $ecek);
333             }
334             elsif ($alg =~ /^PBES2-HS(512|384|256)\+A(128|192|256)KW$/) {
335 24 50 33     254 my $len = looks_like_number($hdr->{p2s}) && $hdr->{p2s} >= 8 && $hdr->{p2s} <= 9999 ? $hdr->{p2s} : 16;
336 24         117 my $salt = random_bytes($len);
337 24 50       293 my $iter = looks_like_number($hdr->{p2c}) ? $hdr->{p2c} : 5000;
338 24         95 $ecek = pbes2_key_wrap(_prepare_oct_key($key), $cek, $alg, $salt, $iter);
339 24         149 $hdr->{p2s} = encode_b64u($salt);
340 24         67 $hdr->{p2c} = $iter;
341 24         116 return ($cek, $ecek);
342             }
343             elsif ($alg =~ /^RSA(-OAEP|-OAEP-256|1_5)$/) {
344 18         103 $key = _prepare_rsa_key($key);
345 18         127 $ecek = rsa_key_wrap($key, $cek, $alg);
346 18         89 return ($cek, $ecek);
347             }
348             elsif ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
349 19         55 $key = _prepare_ecdh_key($key);
350 19         123 ($ecek, $hdr->{epk}) = ecdhaes_key_wrap($key, $cek, $alg, $hdr->{apu}, $hdr->{apv});
351 19         2744 return ($cek, $ecek);
352             }
353             elsif ($alg eq 'ECDH-ES') {
354 6         19 $key = _prepare_ecdh_key($key);
355 6         37 ($cek, $hdr->{epk}) = ecdh_key_wrap($key, $enc, $hdr->{apu}, $hdr->{apv});
356 6         818 return ($cek, '');
357             }
358 0         0 croak "JWE: unknown alg '$alg'";
359             }
360              
361             sub _decrypt_jwe_cek {
362 168     168   422 my ($ecek, $key, $hdr) = @_;
363 168         303 my $alg = $hdr->{alg};
364 168         294 my $enc = $hdr->{enc};
365              
366 168 100       1314 if ($alg eq 'dir') {
    100          
    100          
    100          
    100          
    100          
    50          
367 18         51 return _prepare_oct_key($key);
368             }
369             elsif ($alg =~ /^A(128|192|256)KW$/) {
370 22         60 return aes_key_unwrap(_prepare_oct_key($key), $ecek);
371             }
372             elsif ($alg =~ /^A(128|192|256)GCMKW$/) {
373 22         60 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         143 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         97 $key = _prepare_rsa_key($key);
380 35         4772 return rsa_key_unwrap($key, $ecek, $alg);
381             }
382             elsif ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
383 22         78 $key = _prepare_ecdh_key($key);
384 22         167 return ecdhaes_key_unwrap($key, $ecek, $alg, $hdr->{epk}, $hdr->{apu}, $hdr->{apv});
385             }
386             elsif ($alg eq 'ECDH-ES') {
387 10         29 $key = _prepare_ecdh_key($key);
388 10         74 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   339 my ($cek, $enc, $b64u_header, $b64u_aad, $payload) = @_;
395 115 50       274 my $aad = defined $b64u_aad ? "$b64u_header.$b64u_aad" : $b64u_header;
396 115 100       996 if ($enc =~ /^A(128|192|256)GCM$/) {
    50          
397             # https://tools.ietf.org/html/rfc7518#section-5.3
398 61         255 my $len1 = $1/8;
399 61         116 my $len2 = length($cek);
400 61 50       179 croak "JWE: wrong AES key length ($len1 vs. $len2) for $enc" unless $len1 == $len2;
401 61         210 my $iv = random_bytes(12); # for AESGCM always 12 (96 bits)
402 61         13329 my ($ct, $tag) = gcm_encrypt_authenticate('AES', $cek, $iv, $aad, $payload);
403 61         343 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         326 my ($size, $hash) = ($1/8, "SHA$2");
408 54         142 my $key_len = length($cek) / 2;
409 54         126 my $mac_key = substr($cek, 0, $key_len);
410 54         116 my $aes_key = substr($cek, $key_len, $key_len);
411 54 50       154 croak "JWE: wrong AES key length ($key_len vs. $size)" unless $key_len == $size;
412 54         178 my $iv = random_bytes(16); # for AES always 16
413 54         960 my $m = Crypt::Mode::CBC->new('AES');
414 54         257 my $ct = $m->encrypt($payload, $aes_key, $iv);
415 54         1206 my $aad_len = length($aad);
416 54         328 my $mac_input = $aad . $iv . $ct . pack('N2', ($aad_len / 2147483647)*8, ($aad_len % 2147483647)*8);
417 54         661 my $mac = hmac($hash, $mac_key, $mac_input);
418 54         136 my $sig_len = length($mac) / 2;
419 54         132 my $sig = substr($mac, 0, $sig_len);
420 54         409 return ($ct, $iv, $sig);
421             }
422 0         0 croak "JWE: unsupported enc '$enc'";
423             }
424              
425             sub _decrypt_jwe_payload {
426 168     168   595 my ($cek, $enc, $aad, $ct, $iv, $tag) = @_;
427 168 100       1625 if ($enc =~ /^A(128|192|256)GCM$/) {
    50          
428             # https://tools.ietf.org/html/rfc7518#section-5.3
429 89         446 my $len1 = $1/8;
430 89         182 my $len2 = length($cek);
431 89 50       295 croak "JWE: wrong AES key length ($len1 vs. $len2) for $enc" unless $len1 == $len2;
432 89         18073 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         547 my ($size, $hash) = ($1/8, "SHA$2");
437 79         205 my $key_len = length($cek) / 2;
438 79         204 my $mac_key = substr($cek, 0, $key_len);
439 79         162 my $aes_key = substr($cek, $key_len, $key_len);
440 79 50       237 croak "JWE: wrong AES key length ($key_len vs. $size)" unless $key_len == $size;
441 79         137 my $aad_len = length($aad); # AAD == original encoded header
442 79         461 my $mac_input = $aad . $iv . $ct . pack('N2', ($aad_len / 2147483647)*8, ($aad_len % 2147483647)*8);
443 79         1049 my $mac = hmac($hash, $mac_key, $mac_input);
444 79         178 my $sig_len = length($mac) / 2;
445 79         189 my $sig = substr($mac, 0, $sig_len);
446 79 50       216 croak "JWE: tag mismatch" unless $sig eq $tag;
447 79         598 my $m = Crypt::Mode::CBC->new('AES');
448 79         377 my $pt = $m->decrypt($ct, $aes_key, $iv);
449 79         2210 return $pt;
450             }
451 0         0 croak "JWE: unsupported enc '$enc'";
452             }
453              
454             sub _encode_jwe {
455 115     115   381 my %args = @_;
456 115         286 my $payload = $args{payload};
457 115         188 my $alg = $args{alg};
458 115         295 my $enc = $args{enc};
459 115 100       338 my $header = $args{extra_headers} ? \%{$args{extra_headers}} : {};
  2         7  
460 115 50       329 croak "JWE: missing 'enc'" if !defined $enc;
461 115 50       276 croak "JWE: missing 'payload'" if !defined $payload;
462             # add claims to payload
463 115 100       340 _add_claims($payload, %args) if ref $payload eq 'HASH';
464             # serialize payload
465 115         291 $payload = _payload_enc($payload);
466             # compress payload
467 115 100       289 $payload = _payload_zip($payload, $header, $args{zip}) if $args{zip}; # may set some header items
468             # prepare header
469 115         278 $header->{alg} = $alg;
470 115         219 $header->{enc} = $enc;
471             # key
472 115 50       299 croak "JWE: missing 'key'" if !$args{key};
473 115 50       288 my $key = defined $args{keypass} ? [$args{key}, $args{keypass}] : $args{key};
474             # prepare cek
475 115         318 my ($cek, $ecek) = _encrypt_jwe_cek($key, $header); # adds some header items
476             # encode header
477 115         961 my $json_header = encode_json($header);
478 115         432 my $b64u_header = encode_b64u($json_header);
479 115 50       366 my $b64u_aad = defined $args{aad} ? encode_b64u($args{aad}) : undef;
480             # encrypt payload
481 115         362 my ($ct, $iv, $tag) = _encrypt_jwe_payload($cek, $enc, $b64u_header, $b64u_aad, $payload);
482             # return token parts
483 115         1293 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   1368 my ($b64u_header, $b64u_ecek, $b64u_iv, $b64u_ct, $b64u_tag, $b64u_aad, $unprotected, $shared_unprotected, %args) = @_;
493 174         611 my $header = _b64u_to_hash($b64u_header);
494 174         593 my $ecek = decode_b64u($b64u_ecek);
495 174         490 my $ct = decode_b64u($b64u_ct);
496 174         384 my $iv = decode_b64u($b64u_iv);
497 174         386 my $tag = decode_b64u($b64u_tag);
498 174 50 33     796 croak "JWE: invalid header part" if $b64u_header && !$header;
499 174 50 66     670 croak "JWE: invalid ecek part" if $b64u_ecek && !$ecek;
500 174 50 33     627 croak "JWE: invalid ct part" if $b64u_ct && !$ct;
501 174 50 33     550 croak "JWE: invalid iv part" if $b64u_iv && !$iv;
502 174 50 33     575 croak "JWE: invalid tag part" if $b64u_tag && !$tag;
503              
504 174         233 my $key;
505 174 100       413 if (exists $args{key}) {
    50          
506 172 50       460 $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         10 my $k = _kid_lookup($header->{kid}, $args{kid_keys}, $header->{alg});
512 2 50       6 croak "JWE: kid_keys lookup failed" if !defined $k;
513 2         6 $key = $k;
514             }
515 174 50       364 croak "JWE: missing key" if !defined $key;
516              
517 174         339 my $aa = $args{accepted_alg};
518 174 100 66     673 if (ref($aa) eq 'Regexp') {
    100 66        
519 1 50       162 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       22 my %acca = ref $aa ? map { $_ => 1 } @$aa : ( $aa => 1 );
  5         15  
523 5 100       367 croak "JWE: alg '$header->{alg}' not in accepted_alg" if !$acca{$header->{alg}};
524             }
525              
526 171         333 my $ae = $args{accepted_enc};
527 171 100 66     624 if (ref($ae) eq 'Regexp') {
    100 66        
528 1 50       136 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       20 my %acce = ref $ae ? map { $_ => 1 } @$ae : ( $ae => 1 );
  5         15  
532 5 100       331 croak "JWE: enc '$header->{enc}' not in accepted_enc" if !$acce{$header->{enc}};
533             }
534              
535 168         950 $header = { %$shared_unprotected, %$unprotected, %$header }; # merge headers
536 168         546 my $cek = _decrypt_jwe_cek($ecek, $key, $header);
537 168 50       657 my $aad = defined $b64u_aad ? "$b64u_header.$b64u_aad" : $b64u_header;
538 168         752 my $payload = _decrypt_jwe_payload($cek, $header->{enc}, $aad, $ct, $iv, $tag);
539 168 100       675 $payload = _payload_unzip($payload, $header->{zip}) if $header->{zip};
540 168         699 $payload = _payload_dec($payload, $args{decode_payload});
541 168         931 _verify_claims($payload, %args); # croaks on error
542 168         819 return ($header, $payload);
543             }
544              
545             sub _sign_jws {
546 33     33   81 my ($b64u_header, $b64u_payload, $alg, $key) = @_;
547 33 100       73 return '' if $alg eq 'none'; # no integrity
548 32         43 my $sig;
549 32         75 my $data = "$b64u_header.$b64u_payload";
550 32 100       158 if ($alg =~ /^HS(256|384|512)$/) { # HMAC integrity
    100          
    100          
    100          
    50          
551 19         43 $key = _prepare_oct_key($key);
552 19         231 $sig = hmac("SHA$1", $key, $data);
553             }
554             elsif ($alg =~ /^RS(256|384|512)/) { # RSA+PKCS1-V1_5 signatures
555 5         20 my $pk = _prepare_rsa_key($key);
556 5         28202 $sig = $pk->sign_message($data, "SHA$1", 'v1.5');
557             }
558             elsif ($alg =~ /^PS(256|384|512)/) { # RSA+PSS signatures
559 3         9 my $hash = "SHA$1";
560 3         10 my $hashlen = $1/8;
561 3         10 my $pk = _prepare_rsa_key($key);
562 3         16444 $sig = $pk->sign_message($data, $hash, 'pss', $hashlen);
563             }
564             elsif ($alg =~ /^ES(256|256K|384|512)$/) { # ECDSA signatures
565 4         16 my $hash = {ES256 => 'SHA256', ES256K => 'SHA256', ES384 => 'SHA384', ES512 => 'SHA512'}->{$alg};
566 4         17 my $pk = _prepare_ecc_key($key);
567 4         20856 $sig = $pk->sign_message_rfc7518($data, $hash);
568             }
569             elsif ($alg eq 'EdDSA') { # Ed25519 signatures
570 1         6 my $pk = _prepare_ed25519_key($key);
571 1         6465 $sig = $pk->sign_message($data);
572             }
573 32         216 return encode_b64u($sig);
574             }
575              
576             sub _verify_jws {
577 98     98   248 my ($b64u_header, $b64u_payload, $b64u_sig, $alg, $key) = @_;
578 98         329 my $sig = decode_b64u($b64u_sig);
579 98 50 33     362 croak "JWS: invalid sig part" if $b64u_sig && !$sig;
580 98         217 my $data = "$b64u_header.$b64u_payload";
581              
582 98 50       603 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         135 $key = _prepare_oct_key($key);
587 62 50       809 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         59 my $pk = _prepare_rsa_key($key);
592 19 50       8464 return 1 if $pk->verify_message($sig, $data, $hash, 'v1.5');
593             }
594             elsif ($alg =~ /^PS(256|384|512)/) { # RSA+PSS signatures
595 6         41 my $hash = "SHA$1";
596 6         31 my $hashlen = $1/8;
597 6         18 my $pk = _prepare_rsa_key($key);
598 6 50       1982 return 1 if $pk->verify_message($sig, $data, $hash, 'pss', $hashlen);
599             }
600             elsif ($alg =~ /^ES(256|256K|384|512)$/) { # ECDSA signatures
601 9         54 my $hash = {ES256 => 'SHA256', ES256K => 'SHA256', ES384 => 'SHA384', ES512 => 'SHA512'}->{$alg};
602 9         36 my $pk = _prepare_ecc_key($key);
603 8 50       50964 return 1 if $pk->verify_message_rfc7518($sig, $data, $hash);
604             }
605             elsif ($alg eq 'EdDSA') { # Ed25519 signatures
606 1         6 my $pk = _prepare_ed25519_key($key);
607 1 50       6444 return 1 if $pk->verify_message($sig, $data);
608             }
609 0         0 return 0;
610             }
611              
612             sub _encode_jws {
613 34     34   98 my %args = @_;
614 34         66 my $payload = $args{payload};
615 34         63 my $alg = $args{alg};
616 34 100       86 my $header = $args{extra_headers} ? \%{$args{extra_headers}} : {};
  2         6  
617 34 50       82 croak "JWS: missing 'payload'" if !defined $payload;
618 34 100 100     196 croak "JWS: alg 'none' not allowed" if $alg eq 'none' && !$args{allow_none};
619             # add claims to payload
620 33 100       108 _add_claims($payload, %args) if ref $payload eq 'HASH';
621             # serialize payload
622 33         79 $payload = _payload_enc($payload);
623             # compress payload
624 33 100       86 $payload = _payload_zip($payload, $header, $args{zip}) if $args{zip}; # may set some header items
625             # encode payload
626 33         126 my $b64u_payload = encode_b64u($payload);
627             # prepare header
628 33         77 $header->{alg} = $alg;
629             # encode header
630 33         137 my $json_header = encode_json($header);
631 33         78 my $b64u_header = encode_b64u($json_header);
632             # key
633 33 50 66     137 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         77 my $b64u_signature = _sign_jws($b64u_header, $b64u_payload, $alg, $key);
637 33         206 return ($b64u_header, $b64u_payload, $b64u_signature);
638             }
639              
640             sub _decode_jws {
641 105     105   567 my ($b64u_header, $b64u_payload, $b64u_sig, $unprotected_header, %args) = @_;
642 105         289 my $header = _b64u_to_hash($b64u_header);
643 105 50 33     465 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       303 if (!$args{ignore_signature}) {
647 104         184 my $alg = $header->{alg};
648 104 50       192 croak "JWS: missing header 'alg'" unless $alg;
649 104 100 100     356 croak "JWS: alg 'none' not allowed" if $alg eq 'none' && !$args{allow_none};
650 103 50 66     239 croak "JWS: alg 'none' expects no signature" if $alg eq 'none' && defined $b64u_sig && length($b64u_sig) > 0;
      66        
651              
652 103         179 my $aa = $args{accepted_alg};
653 103 100       358 if (ref $aa eq 'Regexp') {
    100          
    100          
654 1 50       138 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       216 croak "JWS: alg '$alg' not in accepted_alg" if !$acca{$alg};
659             }
660             elsif (defined $aa) {
661 3 100       113 croak "JWS: alg '$alg' not accepted_alg" if $aa ne $alg;
662             }
663              
664 100 100       207 if ($alg ne 'none') {
665 98         132 my $key;
666 98 100       196 if (exists $args{key}) {
    100          
    50          
667 95 50       222 $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       8 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       6 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         3 my $k = $header->{jwk};
682 1 50 33     9 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     29 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         3 $key = $k;
686             }
687 98 50       199 croak "JWS: missing key" if !defined $key;
688              
689 98         236 my $valid = _verify_jws($b64u_header, $b64u_payload, $b64u_sig, $alg, $key);
690 96 50       329 croak "JWS: invalid signature" if !$valid;
691             }
692             }
693 99         302 my $payload = decode_b64u($b64u_payload);
694 99 50 66     375 croak "JWS: invalid payload part" if $b64u_payload && !$payload;
695 99 100       244 $payload = _payload_unzip($payload, $header->{zip}) if $header->{zip};
696 99         323 $payload = _payload_dec($payload, $args{decode_payload});
697 99         413 _verify_claims($payload, %args); # croaks on error
698 68         370 $header = { %$unprotected_header, %$header }; # merge headers
699 68         254 return ($header, $payload);
700             }
701              
702             sub encode_jwt {
703 149     149 1 228904 my %args = @_;
704              
705 149 50       576 croak "JWT: missing 'alg'" unless $args{alg};
706 149   50     759 my $ser = $args{serialization} || 'compact';
707 149 100       1512 if ($args{alg} =~ /^(none|EdDSA|(HS|RS|PS)(256|384|512)|ES(256|256K|384|512))$/) {
    50          
708             ###JWS
709 34         138 my ($b64u_header, $b64u_payload, $b64u_signature) = _encode_jws(%args);
710 33 50       123 if ($ser eq 'compact') { # https://tools.ietf.org/html/rfc7515#section-7.1
    0          
711 33 50       103 croak "JWT: cannot use 'unprotected_headers' with compact serialization" if defined $args{unprotected_headers};
712 33         210 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         539 my ($b64u_header, $b64u_ecek, $b64u_iv, $b64u_ct, $b64u_tag, $b64u_aad) = _encode_jwe(%args);
726 115 50       462 if ($ser eq 'compact') { # https://tools.ietf.org/html/rfc7516#section-7.1
    0          
727 115 50       384 croak "JWT: cannot use 'aad' with compact serialization" if defined $args{aad};
728 115 50       302 croak "JWT: cannot use 'unprotected_headers' with compact serialization" if defined $args{unprotected_headers};
729 115 50       270 croak "JWT: cannot use 'shared_unprotected_headers' with compact serialization" if defined $args{shared_unprotected_headers};
730 115         850 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 126018 my %args = @_;
759 279         639 my ($header, $payload);
760              
761 279 50       4434 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         955 ($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         484 ($header, $payload) = _decode_jws($1, $2, $3, {}, %args);
771             }
772             elsif ($args{token} =~ /^\s*\{.*?\}\s*$/s) {
773 3         36 my $hash = decode_json($args{token});
774 3 100 66     25 if (defined $hash->{payload} && $hash->{protected}) {
    50 33        
775             # Flattened JWS JSON Serialization
776 2         14 ($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       1051 return ($header, $payload) if $args{decode_header};
790 228         1056 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