File Coverage

blib/lib/Crypt/JWT.pm
Criterion Covered Total %
statement 437 487 89.7
branch 291 432 67.3
condition 83 175 47.4
subroutine 41 41 100.0
pod 2 2 100.0
total 854 1137 75.1


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