jitsi_meet-1.0.x-dev/modules/src/JitsiJwt/JsonWebTokens.php
modules/src/JitsiJwt/JsonWebTokens.php
<?php
namespace Drupal\jitsi_jwt\JitsiJwt;
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Signature\Algorithm\HS256;
use Jose\Easy\Build;
class JsonWebTokens {
private $algorithm_manager = NULL;
/**
* @var \Jose\Easy\JWSBuilder
*/
private $jws;
/**
* @var string
*/
private $signedJwsString = "";
/**
* @var \Jose\Component\Core\JWK
*/
private $jwk;
/**
* @var string
*/
private $room;
/**
* @var string|\http\Url
*/
private $domain;
/**
* @var string
*/
private $signingPartyId;
/**
* @var string
*/
private $audience;
/**
* @var string
*/
private $algorithm;
/** @var string */
private $nonce;
/**
* @var string
* must be locally or globally unique!
*/
private $subject;
/**
* JsonWebTokens constructor.
* @param string $domain
* Domain of the Jitsi Meet server.
* @param string $secret
* Secret (or key) to create the validation signature.
* @param string $signingPartyId
* Identifier of this Signing party.
* @param string $audience
* For who(m) is this JWT. (often just the domain name of the jitsi).
* @param string $roomId
* Jitsi Meeting room.
* @param string $algorithm
* Hashing Algorithm used by the signature. (only HS256 is supported).
*/
public function __construct(
string $domain,
string $secret,
string $signingPartyId,
string $audience,
string $roomId ="",
$algorithm = "HS256"
) {
//TODO Add check if Algorithm is supported...
$this->algorithm = $algorithm;
if($algorithm === "HS256"){
$this->algorithm_manager = new AlgorithmManager([
new HS256()
]);
} else {
$this->algorithm_manager = new AlgorithmManager([
new $this->algorithm()
]);
}
$this->jwk = JWKFactory::createFromSecret(
$secret,
[
'alg' => $this->algorithm,
'use' => 'sig'
]
);
$this->signingPartyId = $signingPartyId;
$this->audience = $audience;
$this->domain = $domain;
$this->room = $roomId;
}
/**
* @param string $userId
* @param string $userName
* @param string $userEmail
* @param string $avatarUrl
* @param string $subject
* JWT Subject, must be Locally or globally unique.
* @param array $userRoles
* @param float|int $validity
* @param int $notBeforeOffset
* @return $this
* @throws \Exception
*/
public function createToken(
string $subject,
string $userId,
string $userName,
string $userEmail,
string $avatarUrl,
array $userRoles = [],
int $validity = 60*60*24,
int $notBeforeOffset = 0
) {
$now = time();
$this->nonce = bin2hex(random_bytes(128));//Exception!
//TODO Nonce should be stored 2 validate future request until token expires!
$this->subject = $subject;
$this->jws = Build::jws()
->exp($now + $validity) //when to expire
->iat($now) //issued at
->nbf($now + $notBeforeOffset) // not valid before
->jti($this->nonce) //unique JSON webToken Identifier
->alg($this->algorithm) // Algorithm of key
->iss($this->signingPartyId) //issuer
->aud($this->audience)
->sub($this->subject)
->header('typ', 'JWT')
->claim('context', ['user'=> [
"id"=> "$userId",
"name"=>"$userName",
"avatar"=> "$avatarUrl",
'email'=> "$userEmail"
]]);
if(!empty($this->room)){
$this->jws->claim('room', "$this->room");
}
if(!empty($userRoles)){
foreach ($userRoles as $userRole)
$this->jws->claim($userRole, true);
}
$this->signedJwsString = $this->jws->sign($this->jwk);
return $this;
}
/**
* This will generate an URL to log in to the meeting
* @return string
*/
public function getUrl(){
$token = $this->getSignedJWSString();
if(empty($token)){
$query="";
} else {
$query="?jwt=";
}
return "$this->domain/$this->room$query$token";
}
/**
* This will return the plain JWT as a string.
* @return string
*/
public function getSignedJWSString(){
return $this->signedJwsString;
}
}