lemonldap-ng/lemonldap-ng-common/lib/Lemonldap/NG/Common/JWT.pm
2021-06-28 15:36:29 +02:00

89 lines
2.1 KiB
Perl

package Lemonldap::NG::Common::JWT;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK =
qw(getAccessTokenSessionId getJWTHeader getJWTPayload getJWTSignature getJWTSignedData)
; # symbols to export on request
use JSON;
use MIME::Base64 qw/encode_base64 decode_base64/;
our $VERSION = '2.0.12';
# Gets the Access Token session ID embedded in a LLNG-emitted JWT
sub getAccessTokenSessionId {
my ($access_token) = @_;
# Access Token is a JWT, extract the JTI field
# and use it as session ID
if ( index( $access_token, '.' ) > 0 ) {
my $data = getJWTPayload($access_token);
if ( $data and $data->{jti} ) {
return $data->{jti};
}
else {
return;
}
}
# Access Token is the session ID directly
else {
return $access_token;
}
}
# Isolate and decode parts of a JWT
# @param jwt in serialized form
# @param part 0 for header, 1 for payload, 2 for signature
# @param json whether or not to decode as JSON
# @return JSON string
sub getJWTPart {
my ( $jwt, $part ) = @_;
my @jwt_parts = split( /\./, $jwt );
my $data = decode_base64url( $jwt_parts[$part] );
my $json_hash;
eval { $json_hash = from_json($data); };
return undef if ($@);
return $json_hash;
}
# Return the JWT data that has to be signed by the OP
# @param jwt serialized JWT
# @return the string data to pass to the signature method
sub getJWTSignedData {
my ($jwt) = @_;
my @jwt_parts = split( /\./, $jwt );
return ( $jwt_parts[0] . "." . $jwt_parts[1] );
}
# Convenience method to get the decoded JWT header
# @param jwt JWT in serialized form
# @return Perl hash
sub getJWTHeader {
my ($jwt) = @_;
return getJWTPart( $jwt, 0 );
}
# Convenience method to get the decoded JWT payload
# @param jwt JWT in serialized form
# @return Perl hash
sub getJWTPayload {
my ($jwt) = @_;
return getJWTPart( $jwt, 1 );
}
sub getJWTSignature {
my ($jwt) = @_;
my @jwt_parts = split( /\./, $jwt );
return $jwt_parts[2];
}
sub decode_base64url {
my $s = shift;
$s =~ tr[-_][+/];
$s .= '=' while length($s) % 4;
return decode_base64($s);
}
1;