Client side

#!/usr/bin/perl

use strict; use warnings;

use Crypt::JWT qw(encode_jwt decode_jwt);

use Term::ReadKey;

ReadMode ( 'noecho' );

    say STDERR "Please enter the passphrase:";
    my $pass = <STDIN>;
    chomp $pass;
ReadMode ( 'normal' );    #Back to your regularly scheduled program

my $key = Crypt::PK::RSA->new('/home/user/.ssh/id_rsa', $pass);

my $jws_token = encode_jwt(payload => 'payload', alg => 'RS256', key => $key, extra_headers=>{kid=>'me@example.com'});
say STDOUT $jws_token;

Server side

#!/usr/bin/perl

use strict; use warnings;

use Crypt::JWT qw(encode_jwt decode_jwt);
use Crypt::PK::RSA;

my $request_token = 'xxx';

my $pubkey = Crypt::PK::RSA->new('/home/user/ssh/id_rsa.pub');
my $jwk_hash1 = $pubkey->export_key_jwk('public', 1);
$jwk_hash1->{kid} = 'me@example.com';

my $keylist = {
  keys => [
      $jwk_hash1,
      $jwk_hash2,
  ]
};

my ($header, $client) = decode_jwt(token=>$request_token, kid_keys=>$keylist, decode_header => 1);

say STDERR Dumper $header;
say STDOUT $client;