2021-01-08 17:38:15 +01:00
|
|
|
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/;
|
|
|
|
|
2021-06-28 15:36:29 +02:00
|
|
|
our $VERSION = '2.0.12';
|
|
|
|
|
2021-01-08 17:38:15 +01:00
|
|
|
# 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;
|