JSON::WebToken(3pm)

πŸ’– JSON::WebToken πŸ’–

okay so bestie, buckle up β€” this is the manual page for JSON::WebToken, a JSON Web Token (JWT) implementation for Perl πŸŽ€ (that's the NAME section, we're doing this properly, don't worry).


✨ SYNOPSIS ✨

here's the whole vibe in one go, literally just copy it:

use Test::More;
use JSON;
use JSON::WebToken;

my $claims = {
    iss => 'joe',
    exp => 1300819380,
    'http://example.com/is_root' => JSON::true,
};
my $secret = 'secret';

my $jwt = encode_jwt $claims, $secret;
my $got = decode_jwt $jwt, $secret;
is_deeply $got, $claims;

done_testing;

like... encode, decode, is_deeply, done_testing. that's the whole arc. slay πŸ’…


🌸 DESCRIPTION 🌸

JSON::WebToken is a JSON Web Token (JWT) implementation for Perl. periodt.

🚨 THIS MODULE IS ALPHA LEVEL INTERFACE. like, genuinely alpha, bestie. it's giving "works but don't build your whole life on it" energy. you've been warned 😭

πŸ¦‹ METHODS πŸ¦‹

encode($claims [, $secret, $algorithm, $extra_headers ]) : String

this one encodes a JWT out of a hash reference. it's literally the glow-up from hash β†’ string πŸ‘‘

my $jwt = JSON::WebToken->encode({
    iss => 'joe',
    exp => 1300819380,
    'http://example.com/is_root' => JSON::true,
}, 'secret');
# $jwt = join '.',
#     'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
#     'eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ'
#     '4ldFxjibgJGz_uaIRCIq89b5ipR-sbI2Uq7B2WNEDs0'

the default encryption algorithm is "HS256" β€” that's the main character, that's the default. but you can change the algorithm, watch this:

my $pricate_key_string = '...';
my $public_key_string  = '...';

my $jwt = JSON::WebToken->encode({
    iss => 'joe',
    exp => 1300819380,
    'http://example.com/is_root' => JSON::true,
}, $pricate_key_string, 'RS256');

my $claims = JSON::WebToken->decode($jwt, $public_key_string);

(and yes, $pricate_key_string is spelled exactly like that in the original β€” we do not fix, we do not correct, we respect the lore πŸ™ˆ)

when you're using RS256, RS384 or RS512 algorithms, you need Crypt::PK::RSA. it's a dependency, it's non-negotiable, it's the price of admission πŸ’€

and if you want to create a "Plaintext JWT", you should specify "none" for the algorithm:

my $jwt = JSON::WebToken->encode({
    iss => 'joe',
    exp => 1300819380,
    'http://example.com/is_root' => JSON::true,
}, '', 'none');
# $jwt = join '.',
#     'eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0',
#     'eyJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlLCJpc3MiOiJqb2UifQ',
#     ''

see that empty third segment? that's the unsigned life ✨ no signature, no stress (but also, lowkey, no security β€” just saying 🫢).

decode($jwt [, $secret, $verify_signature, $accepted_algorithms ]) : HASH

this one goes the other way β€” decodes a hash reference out of a JWT string. reverse uno card πŸ”„

my $claims = JSON::WebToken->decode($jwt, $secret, 1, ["RS256"]);
⚠️ lowkey important: any signing algorithm (except "none") is acceptable by default, so you should check it with the $accepted_algorithms parameter. like, fr fr, do not skip this. this is the vibe check your JWT needs πŸ™

add_signing_algorithm($algorithm, $class)

this one adds a signing algorithm. it's the "bring your own algorithm" feature, very DIY, very iconic πŸŽ€

# resolve JSON::WebToken::Crypt::MYALG
JSON::WebToken->add_signing_algorithm('MYALGXXX'   => 'MYALG');

# resolve Some::Class::Algorithm
JSON::WebToken->add_signing_algorithm('SOMEALGXXX' => '+Some::Class::Algorithm');

see the + prefix on that second one? that's how you tell it to resolve Some::Class::Algorithm. iykyk πŸ’…

SEE ALSO JSON::WebToken::Crypt::HMAC or JSON::WebToken::Crypt::RAS.

(that's RAS with a single S, exactly as written β€” i'm not touching it, it's not my business 🌈)


πŸ‘‘ FUNCTIONS πŸ‘‘

encode_jwt($claims [, $secret, $algorithm, $extra_headers ]) : String

same as the encode() method. literally the same thing, just a function instead of a method. that's it, that's the whole section πŸ¦‹

decode_jwt($jwt [, $secret, $verify_signature, $accepted_algorithms ]) : Hash

same as the decode() method. again: same thing, function flavour. we love a convenience wrapper ✨


πŸ’€ ERROR CODES πŸ’€

when things go sideways, JSON::WebToken::Exception will be thrown with the following code. here's the whole roster, no skips:

  • ERROR_JWT_INVALID_PARAMETER β€” thrown when some method arguments are not valid. the "you typed it wrong" classic πŸ™ˆ
  • ERROR_JWT_MISSING_SECRET β€” thrown when secret is required (("alg != "none"")). like bestie, you need the secret.
  • ERROR_JWT_INVALID_SEGMENT_COUNT β€” thrown when JWT segment count is not between 2 and 4. two, three, four. that's the range. count your dots πŸ’…
  • ERROR_JWT_INVALID_SEGMENT_ENCODING β€” thrown when each JWT segment is not encoded by base64url. wrong encoding, wrong vibe 😭
  • ERROR_JWT_UNWANTED_SIGNATURE β€” thrown when ("alg == "none"") but a signature segment found. you said no signature and then brought a signature?? pick a lane 🚨
  • ERROR_JWT_INVALID_SIGNATURE β€” thrown when JWT signature is invalid. the signature ain't signing πŸ’€
  • ERROR_JWT_NOT_SUPPORTED_SIGNING_ALGORITHM β€” thrown when the given signing algorithm is not supported. we don't know her πŸ‘‘
  • ERROR_JWT_UNACCEPTABLE_ALGORITHM β€” thrown when the given signing algorithm is not included in acceptable_algorithms. she's supported, just not here, not tonight 🌸

🫢 AUTHOR 🫢

xaicron <xaicron@cpan.org>

zentooo

two icons, one module πŸ’œ


Copyright 2012 - xaicron


🌈 LICENSE 🌈

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. free software, free spirit, free as in bestie πŸŽ€


πŸ’– SEE ALSO πŸ’–

<http://tools.ietf.org/html/draft-ietf-oauth-json-web-token>


and that's the whole page, bestie!! 🧚 no cap, every flag, every error code, every typo preserved with love. this was perl v5.42.2, dated 2026-03-08 β€” catch you on the next man page πŸ’…βœ¨πŸ“

πŸ“¦ where this page comes from