From 628477095ddeeac5d73ccfc661ed8fdde8068b38 Mon Sep 17 00:00:00 2001 From: Jim Seconde Date: Wed, 12 Feb 2025 10:44:16 +0000 Subject: [PATCH 1/2] Use firebase JWT --- composer.json | 2 +- src/OpenTok/OpenTok.php | 37 +++++++++---------------------------- 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index 7cfe1f5..3db0491 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "php": "^7.2|^8.0", "ext-xml": "*", "johnstevenson/json-works": "~1.1", - "firebase/php-jwt": "^6.0", + "firebase/php-jwt": "^6.11", "guzzlehttp/guzzle": "~6.0|~7.0", "ext-json": "*", "vonage/jwt": "^0.5.1" diff --git a/src/OpenTok/OpenTok.php b/src/OpenTok/OpenTok.php index 36d56f1..a4ef38b 100644 --- a/src/OpenTok/OpenTok.php +++ b/src/OpenTok/OpenTok.php @@ -3,6 +3,7 @@ namespace OpenTok; use DateTimeImmutable; +use Firebase\JWT\JWT; use Firebase\JWT\Key; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Encoding\ChainedFormatter; @@ -84,7 +85,7 @@ public function __construct($apiKey, $apiSecret, $options = array()) * @param string $sessionId The session ID corresponding to the session to which the user * will connect. * - * @param array $options This array defines options for the token. This array includes the + * @param array $payload This array defines options for the token. This array includes the * following keys, all of which are optional: * * * * @param bool $legacy By default, OpenTok uses SHA256 JWTs for authentication. Switching - * legacy to true will create a deprecated T1 token for backwards compatibility. + * legacy to true will create a T1 token for backwards compatibility. * * @return string The token string. */ - public function generateToken(string $sessionId, array $options = array(), bool $legacy = false): string + public function generateToken(string $sessionId, array $payload = array(), bool $legacy = false): string { if ($legacy) { - return $this->returnLegacyToken($sessionId, $options); + return $this->returnLegacyToken($sessionId, $payload); } $issuedAt = new \DateTimeImmutable('@' . time()); $defaults = [ + 'iss' => $this->apiKey, + 'iat' => $issuedAt->getTimestamp(), 'session_id' => $sessionId, 'role' => Role::PUBLISHER, - 'expireTime' => null, - 'initial_layout_list' => [''], 'ist' => 'project', 'nonce' => mt_rand(), 'scope' => 'session.connect' ]; - $options = array_merge($defaults, array_intersect_key($options, $defaults)); - - $builder = new Builder(new JoseEncoder(), ChainedFormatter::default()); - $builder = $builder->issuedBy($this->apiKey); - - if ($options['expireTime']) { - $expiry = new \DateTimeImmutable('@' . $options['expireTime']); - $builder = $builder->expiresAt($expiry); - } - - unset($options['expireTime']); - - $builder = $builder->issuedAt($issuedAt); - $builder = $builder->canOnlyBeUsedAfter($issuedAt); - $builder = $builder->identifiedBy(bin2hex(random_bytes(16))); - - foreach ($options as $key => $value) { - $builder = $builder->withClaim($key, $value); - } - - $token = $builder->getToken(new \Lcobucci\JWT\Signer\Hmac\Sha256(), InMemory::plainText($this->apiSecret)); + $payload = array_merge($defaults, array_intersect_key($payload, $defaults)); - return $token->toString(); + return JWT::encode($payload, $this->apiSecret, 'HS256'); } private function returnLegacyToken(string $sessionId, array $options = []): string From 8288d8ae27b440e6fb605b133c30474e7ce00909 Mon Sep 17 00:00:00 2001 From: Jim Seconde Date: Wed, 12 Feb 2025 11:35:00 +0000 Subject: [PATCH 2/2] Test firebase JWT --- tests/OpenTokTest/OpenTokTest.php | 51 ++++++++++++------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/tests/OpenTokTest/OpenTokTest.php b/tests/OpenTokTest/OpenTokTest.php index 4920acb..996f8c9 100644 --- a/tests/OpenTokTest/OpenTokTest.php +++ b/tests/OpenTokTest/OpenTokTest.php @@ -2,6 +2,8 @@ namespace OpenTokTest; +use Firebase\JWT\JWT; +use Firebase\JWT\Key; use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Token\Plain; use OpenTok\Render; @@ -753,41 +755,28 @@ public function testWillCreateLegacyT1WhenRequested(): void public function testWillCreateLegacyT1DirectlyToBypassExpBug(): void { $openTok = new OpenTok('12345678', '0123456789abcdef0123456789abcdef0123456789'); - $token = $openTok->generateToken('1_MX4xMjM0NTY3OH4-VGh1IEZlYiAyNyAwNDozODozMSBQU1QgMjAxNH4wLjI0NDgyMjI', []); + $token = $openTok->generateToken('1_MX4xMjM0NTY3OH4-VGh1IEZlYiAyNyAwNDozODozMSBQU1QgMjAxNH4wLjI0NDgyMjI', [], true); $this->assertEquals('T1', substr($token, 0, 2)); } - /** - * Makes sure that a JWT is generated for the client-side token - * - * Currently disabled due to the backend requiring an `exp` claim, which was - * not required on T1s. Uncomment when the backend is fixed. - CRT - */ - // public function testWillCreateJwt(): void - // { - // $openTok = new OpenTok('my-api-key', 'my-super-long-and-cool-api-secret'); - // $token = $openTok->generateToken('some-token-value'); - - // $config = Configuration::forSymmetricSigner( - // new \Lcobucci\JWT\Signer\Hmac\Sha256(), - // \Lcobucci\JWT\Signer\Key\InMemory::plainText('my-super-long-and-cool-api-secret') - // ); - - // $token = $config->parser()->parse($token); - // $this->assertInstanceOf(Plain::class, $token); - - // $this->assertTrue($config->validator()->validate($token, new \Lcobucci\JWT\Validation\Constraint\SignedWith( - // $config->signer(), - // $config->signingKey() - // ))); - - // $this->assertEquals('my-api-key', $token->claims()->get('iss')); - // $this->assertEquals('some-token-value', $token->claims()->get('session_id')); - // $this->assertEquals('publisher', $token->claims()->get('role')); - // $this->assertEquals('project', $token->claims()->get('ist')); - // $this->assertEquals('session.connect', $token->claims()->get('scope')); - // } + public function testWillGenerateSha256Token(): void + { + $openTok = new OpenTok('12345678', '0123456789abcdef0123456789abcdef0123456789'); + $token = $openTok->generateToken('1_MX4xMjM0NTY3OH4-VGh1IEZlYiAyNyAwNDozODozMSBQU1QgMjAxNH4wLjI0NDgyMjI'); + + $this->assertNotEquals('T1', substr($token, 0, 2)); + + $decoded = JWT::decode($token, new Key('0123456789abcdef0123456789abcdef0123456789', 'HS256')); + $decodedArray = (array) $decoded; + + $this->assertEquals('12345678', $decodedArray['iss']); + $this->assertEquals('1_MX4xMjM0NTY3OH4-VGh1IEZlYiAyNyAwNDozODozMSBQU1QgMjAxNH4wLjI0NDgyMjI', $decodedArray['session_id']); + $this->assertEquals('project', $decodedArray['ist']); + $this->assertEquals('session.connect', $decodedArray['scope']); + $this->assertEquals('publisher', $decodedArray['role']); + + } public function testStartsArchive(): void {