Mojo-JWT

 view release on metacpan or  search on metacpan

lib/Mojo/JWT.pm  view on Meta::CPAN

  my $self = shift;
  delete $self->{token};

  my $claims = $self->claims;
  if ($self->set_iat) { $claims->{iat} = $self->now }
  if (defined(my $exp = $self->expires))    { $claims->{exp} = $exp }
  if (defined(my $nbf = $self->not_before)) { $claims->{nbf} = $nbf }

  my $header  = { %{ $self->header }, typ => 'JWT', alg => $self->algorithm };
  my $hstring = Crypt::Misc::encode_b64u Mojo::JSON::encode_json($header);
  my $cstring = Crypt::Misc::encode_b64u Mojo::JSON::encode_json($claims);
  my $payload = "$hstring.$cstring";
  my $signature;
  my $algo = $self->algorithm;
  if ($algo eq 'none') {
    $signature = '';
  } elsif ($algo =~ $re_rs) {
    $signature = $self->sign_rsa($1, $payload);
  } elsif ($algo =~ $re_hs) {
    $signature = $self->sign_hmac($1, $payload);
  } else {
    Carp::croak 'Unknown algorithm';
  }

  return $self->{token} = "$payload." . Crypt::Misc::encode_b64u $signature;
}

sub now { time }

sub sign_hmac {
  my ($self, $size, $payload) = @_;
  Carp::croak 'symmetric secret not specified' unless my $secret = $self->secret;
  Carp::croak 'Unsupported HS signing algorithm' unless $size == 256 || $size == 384 || $size == 512;
  require Crypt::Mac::HMAC;
  return Crypt::Mac::HMAC::hmac("SHA$size", $secret, $payload);
}

sub sign_rsa {
  my ($self, $size, $payload) = @_;
  Carp::croak 'Unsupported RS signing algorithm' unless $size == 256 || $size == 384 || $size == 512;
  Carp::croak 'secret key not specified' unless my $secret = $self->secret;
  my $crypt = _inflate_rsa_key($secret);
  return $crypt->sign_message($payload, "SHA$size", 'v1.5');
}

sub token { shift->{token} }

sub verify_rsa {
  my ($self, $size, $payload, $signature) = @_;
  Carp::croak 'Unsupported RS verification algorithm' unless $size == 256 || $size == 384 || $size == 512;
  Carp::croak 'public key not specified' unless my $public = $self->public;
  my $crypt = _inflate_rsa_key($public);
  return $crypt->verify_message($signature, $payload, "SHA$size", 'v1.5');
}

sub _inflate_rsa_key {
  my ($key) = @_;
  require Crypt::PK::RSA;
  return $key if $key->$isa('Crypt::PK::RSA');
  if ($key->$isa('Crypt::OpenSSL::RSA')) {
    $key = $key->is_private ? $key->get_private_key_string : $key->get_public_key_string;
  }
  return Crypt::PK::RSA->new(\$key);
}

1;

=head1 NAME

Mojo::JWT - JSON Web Token the Mojo way

=head1 SYNOPSIS

  my $jwt = Mojo::JWT->new(claims => {...}, secret => 's3cr3t')->encode;
  my $claims = Mojo::JWT->new(secret => 's3cr3t')->decode($jwt);

=head1 DESCRIPTION

JSON Web Token is described in L<https://tools.ietf.org/html/rfc7519>.
L<Mojo::JWT> implements that standard with an API that should feel familiar to L<Mojolicious> users (though of course it is useful elsewhere).
Indeed, JWT is much like L<Mojolicious::Sessions> except that the result is a url-safe text string rather than a cookie.

In JWT, the primary payload is called the C<claims>, and a few claims are reserved, as seen in the IETF document.
The header and the claims are signed when stringified to guard against tampering.
Note that while signed, the data is not encrypted, so don't use it to send secrets over clear channels.

=head1 ATTRIBUTES

L<Mojo::JWT> inherits all of the attributes from L<Mojo::Base> and implements the following new ones.

=head2 algorithm

The algorithm to be used to sign a JWT during encoding or else the algorithm that was used for the most recent decoding.
Defaults to C<HS256> until a decode is performed.

C<none> is an acceptable encoding algorithm, however for it to be used to decode, L</allow_none> must be set.

=head2 allow_none

To prevent spoofing attacks, C<allow_none> must be explicitly set to a true value otherwise decoding a JWT which specifies the C<none> algorithm will result in an exception.
The default is of course false.

=head2 claims

The payload to be encoded or else the claims from the most recent decoding.
This must be a hash reference, array references are not allowed as the top-level JWT claims.

=head2 expires

The epoch time value after which the JWT value should not be considered valid.
This value (if set and not undefined) will be used as the C<exp> key in the claims or was extracted from the claims during the most recent decoding.

=head2 header

You may set your own headers when encoding the JWT bypassing a hash reference to the L</header> attribute. Please note that there are two default headers set. B<alg> is set to the value of L</algorithm> or 'HS256' and B<typ> is set to 'JWT'. These ca...

=head2 not_before

The epoch time value before which the JWT value should not be considered valid.
This value (if set and not undefined) will be used as the C<nbf> key in the claims or was extracted from the claims during the most recent decoding.



( run in 1.221 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )