Skip to content

Commit

Permalink
Added shim layer
Browse files Browse the repository at this point in the history
  • Loading branch information
SecondeJK committed Jan 15, 2025
1 parent 3f10580 commit 7ea8056
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 8 deletions.
40 changes: 34 additions & 6 deletions src/OpenTok/OpenTok.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,47 @@ class OpenTok
private $apiSecret;
/** @internal */
private $client;
/** @internal */

/**
* @var array
* @internal
* Options that can override the defaults. Additionally, you can set the keys
* application_id & private_key_path to strings that will then override the default
* OpenTok Client behaviour when making requests to the Vonage Video API.
*/
public $options;

/** @internal */
public function __construct($apiKey, $apiSecret, $options = array())
{
$validateKeys = true;
Validators::validateVonageJwtArguments($options);
$apiUrl = 'https://api.opentok.com';

if (array_key_exists('application_id', $options) && array_key_exists('private_key_path', $options)) {
$validateKeys = false;
$apiUrl = 'https://video.api.vonage.com';
}

// unpack optional arguments (merging with default values) into named variables
$defaults = array(
'apiUrl' => 'https://api.opentok.com',
'apiUrl' => $apiUrl,
'client' => null,
'timeout' => null // In the future we should set this to 2
'timeout' => null, // In the future we should set this to 2
'application_id' => null,
'private_key_path' => null,
);

$this->options = array_merge($defaults, array_intersect_key($options, $defaults));

list($apiUrl, $client, $timeout) = array_values($this->options);

// validate arguments
Validators::validateApiKey($apiKey);
Validators::validateApiSecret($apiSecret);
if ($validateKeys) {
Validators::validateApiKey($apiKey);
Validators::validateApiSecret($apiSecret);
}

Validators::validateApiUrl($apiUrl);
Validators::validateClient($client);
Validators::validateDefaultTimeout($timeout);
Expand Down Expand Up @@ -116,9 +137,16 @@ public function __construct($apiKey, $apiSecret, $options = array())
* @param bool $legacy By default, OpenTok uses SHA256 JWTs for authentication. Switching
* legacy to true will create a deprecated T1 token for backwards compatibility.
*
* Optionally, you can set $vonage to true and it will generate a Vonage Video token if you are using
* the shim behaviour.
*
* @return string The token string.
*/
public function generateToken(string $sessionId, array $options = array(), bool $legacy = false): string
public function generateToken(
string $sessionId,
array $options = array(),
bool $legacy = false
): string
{
// Note, JWT generation disabled due to a backend bug regarding `exp` claims being mandatory - CRT
// if ($legacy) {
Expand Down
20 changes: 20 additions & 0 deletions src/OpenTok/Util/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

use OpenTok\Exception\ForceDisconnectAuthenticationException;
use OpenTok\Exception\ForceDisconnectUnexpectedValueException;
use Vonage\JWT\TokenGenerator;

/**
* @internal
Expand All @@ -46,6 +47,8 @@ class Client

protected $apiKey;
protected $apiSecret;
protected $applicationId = null;
protected $privateKeyPath = null;
protected $configured = false;

/**
Expand All @@ -64,6 +67,14 @@ public function configure($apiKey, $apiSecret, $apiUrl, $options = array())
$this->apiKey = $apiKey;
$this->apiSecret = $apiSecret;

if (array_key_exists('application_id', $options) || array_key_exists('private_key_path', $options)) {
if (!is_null($options['application_id']) && !is_null($options['private_key_path'])) {
$this->applicationId = $options['application_id'];
$this->privateKeyPath = $options['private_key_path'];
$apiUrl = 'https://video.api.vonage.com';
}
}

if (isset($this->options['client'])) {
$this->client = $options['client'];
} else {
Expand Down Expand Up @@ -124,13 +135,22 @@ public function isConfigured()

private function createAuthHeader()
{
if (!is_null($this->applicationId) && !is_null($this->privateKeyPath)) {
$projectRoot = dirname(__DIR__, 3); // Adjust the number of dirname() calls if necessary to match your
// project structure.
$privateKeyFullPath = $projectRoot . DIRECTORY_SEPARATOR . $this->privateKeyPath;
$tokenGenerator = new TokenGenerator($this->applicationId, file_get_contents($privateKeyFullPath));
return $tokenGenerator->generate();
}

$token = array(
'ist' => 'project',
'iss' => $this->apiKey,
'iat' => time(), // this is in seconds
'exp' => time() + (5 * 60),
'jti' => uniqid('', true),
);

return JWT::encode($token, $this->apiSecret, 'HS256');
}

Expand Down
18 changes: 18 additions & 0 deletions src/OpenTok/Util/Validators.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ public static function validateApiKey($apiKey)
}
}

public static function validateVonageJwtArguments(array $options)
{
if (!isset($data['application_id']) && !isset($data['private_key_path'])) {
return;
}

if (isset($data['application_id']) && isset($data['private_key_path'])) {
if (is_string($data['application_id']) && is_string($data['private_key_path'])) {
return;
};
}

// If one key is present but not the other, validation fails
throw new InvalidArgumentException(
'You are attempting to use the Vonage Video API. Both application_id and private key paths must be in options and both strings.'
);
}

public static function validateForceMuteAllOptions(array $options)
{
$validOptions = [
Expand Down
32 changes: 30 additions & 2 deletions tests/OpenTokTest/OpenTokTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -758,9 +758,37 @@ public function testWillCreateLegacyT1DirectlyToBypassExpBug(): void
$this->assertEquals('T1', substr($token, 0, 2));
}

public function testWillHitVonageVideoWithVonageJwt(): void
{
// All of this manual DRY exists because the hardcoded setup helper methods
// were not written to handle this sort of behaviour overriding.
$mocks = [
'code' => 200,
'headers' => [
'Content-Type' => 'application/json'
],
'path' => 'v2/project/APIKEY/archive/session'
];

$customAgent = [
'application_id' => 'abc123',
'private_key_path' => './tests/OpenTokTest/test.key',
];

$this->setupOTWithMocks([$mocks], $customAgent);

$sessionId = '2_MX44NTQ1MTF-flR1ZSBOb3YgMTIgMDk6NDA6NTkgUFNUIDIwMTN-MC43NjU0Nzh-';
$archive = $this->opentok->startArchive($sessionId, ['maxBitrate' => 2000000]);

$this->assertCount(1, $this->historyContainer);

$request = $this->historyContainer[0]['request'];
$this->assertEquals('POST', strtoupper($request->getMethod()));
}

/**
* 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
*/
Expand Down Expand Up @@ -1319,7 +1347,7 @@ public function testGetsArchiveWithMaxBitrate(): void

$request = $this->historyContainer[0]['request'];
$this->assertEquals('GET', strtoupper($request->getMethod()));
$this->assertEquals('/v2/project/'.$this->API_KEY.'/archive/'.$archiveId, $request->getUri()->getPath());
$this->assertEquals('/v2/project/' . $this->API_KEY . '/archive/' . $archiveId, $request->getUri()->getPath());
$this->assertEquals('api.opentok.com', $request->getUri()->getHost());
$this->assertEquals('https', $request->getUri()->getScheme());

Expand Down
28 changes: 28 additions & 0 deletions tests/OpenTokTest/test.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCy3YiiZ206+/7j
oDzF9qGHhFuxEGuGL1ufGm0LvCiOgNJpV4KGatjdminomS0PwI6v9Gz3r4mYBxeR
3xXV3xPpr3yEDu+ivQN8oMei4ttg++nuyk26gjAdEvz5uSQBV5lWvgjR6tlSPb/j
ca4d5AymuWmT110qcQ+ui7eoOWAfQIWj5Tlqk6YyXUnoMlD4c2c9/hOJZR51VF1n
diDONkHplqjzGfdHxDxCBXsIW1wi8h6PVHH54rDmYay1ojRVPJ7b2RBu8vgvWYoR
du6cY8Bp/1skQUEvtOBhFN62vAZ12s91jFO+plzyA9oDfAXVguW0yRWj5GNJmtPZ
YIcynpjvAgMBAAECggEAM1tzq3n5/Zk0jyRHvum5aKFi+HzH+t/nNVBPpjJxDLXF
dLTJSBIu0bY9uUkeDKtT7QbIMPgokEvdAyfka6PhYlRecsadHQObmDHMEKOFrRu4
CDXzSo2uBfMZSxTTV0VRRHxNKQT/QGN1kPdnsLJ1xXtwaqBIYnLTN2FrqvRKer4+
molQK8v838q4tOVT0ZKjIFHX+zyebKqJDOsCO+jDnrKIw3VTID6iZ0DNwGp5xNJT
HOLiT7CQM7Lg7fMdQp9xQxrGWJFw26cuvewmBuPdZRdqc8indgT5pq+VIZkLeTAB
XMnf0W35abwIUlfMIvhVZOiaeZzMwzNuV/Qp9GPFAQKBgQDzVpWxefxmTyHCWXz4
2m+wojoxEBgn6GRdvUbji7vyRRlmGZRNVybwqqxXyCq3RYdIwV55Ihk7O0mmO4g+
ESuDchZaMxouzXzDKz8jyoG6Gxymd8QJetnA8ctFwUGnTrK3sCxnTAjphGSf1PlT
vdev+f6T/QT0MT7qxUloDC9hAQKBgQC8LCF6OaFlZdi/kKPFcXbYIxFWRCdiun/A
xAL3+UsMllF53aZcWnIsm9rv0sKhPfrTGCp0eLUyinZzjxzdGDeb5hqafWVArXfT
xj4NC5uQVO2w0HGqB0BpZkBCtiyu25Pw0xPvXlcvwCBYcIDvJuf0hwiGBBKPk1b8
LjlkbfoJ7wKBgQDZsU499gmtZYGoIvLAlnpxJNC2b9WMbkTL77bpfmrntJWiV6Pr
BNrbV3TTG0nLp7H9jrB74dt8t++NfZjHHgk1kO0aSLlVwZOp7piP5mzkF7kr291P
Nc505FubzeZ0TN1po3w19TnL3xs+OgPLvPymfBoaPrMd2qiU02Z2ZOBGAQKBgA9V
GTU4VOpKLisNwgpogGKEGPmKfBsTTy2JyyQhb/gKl4Dyioej5wGzgVdhOPKidjmV
EoCDBWCk35ny40swmfdd/HTyGrn2aHkdAhlWBMrx4Jwzn89W3+y2pC3LYkCtK5TH
3iv25+vAH+KU6CyUYvoNtqgU1N5WBxRtP8frHiCJAoGAOtq0v8K2KKrEI6L/jHhJ
eNZVUWdGQTZx33vvt5lIboxrNyajaBo25LpmmEAKOhgD61ivHJNrxVDkOMKNx2xt
WnLZvQr7M62SdjWFmcFuY/xRbaX6IOW6C9qps3MdtJeFVw9P6z7udXfXHsCEbQvd
YyR0bVDYLxbCAdYjs7PyCA8=
-----END PRIVATE KEY-----

0 comments on commit 7ea8056

Please sign in to comment.