SEBWIN-623, SEBWIN-628, SEBWIN-641, #521: Updated Zoom WebSDK to version 2.10.1 and changed authentication to use SDK key and JWT token.

This commit is contained in:
Damian Büchel 2023-03-07 23:12:59 +01:00
parent 296f87727d
commit 0bb9f42a3a
8 changed files with 138 additions and 188 deletions

View file

@ -92,12 +92,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
case Keys.Proctoring.Zoom.AllowRaiseHand:
MapZoomAllowRaiseHands(settings, value);
break;
case Keys.Proctoring.Zoom.ApiKey:
MapZoomApiKey(settings, value);
break;
case Keys.Proctoring.Zoom.ApiSecret:
MapZoomApiSecret(settings, value);
break;
case Keys.Proctoring.Zoom.AudioMuted:
MapZoomAudioMuted(settings, value);
break;
@ -353,22 +347,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
}
}
private void MapZoomApiKey(AppSettings settings, object value)
{
if (value is string key)
{
settings.Proctoring.Zoom.ApiKey = key;
}
}
private void MapZoomApiSecret(AppSettings settings, object value)
{
if (value is string secret)
{
settings.Proctoring.Zoom.ApiSecret = secret;
}
}
private void MapZoomAudioMuted(AppSettings settings, object value)
{
if (value is bool muted)

View file

@ -258,8 +258,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
internal const string AllowChat = "zoomFeatureFlagChat";
internal const string AllowClosedCaptions = "zoomFeatureFlagCloseCaptions";
internal const string AllowRaiseHand = "zoomFeatureFlagRaiseHand";
internal const string ApiKey = "zoomApiKey";
internal const string ApiSecret = "zoomApiSecret";
internal const string AudioMuted = "zoomAudioMuted";
internal const string Enabled = "zoomEnable";
internal const string MeetingNumber = "zoomRoom";

View file

@ -96,10 +96,9 @@ namespace SafeExamBrowser.Proctoring
}
else if (settings.Zoom.Enabled)
{
credentials.Add(new JProperty("apiKey", settings.Zoom.ApiKey));
credentials.Add(new JProperty("apiSecret", settings.Zoom.ApiSecret));
credentials.Add(new JProperty("meetingNumber", settings.Zoom.MeetingNumber));
credentials.Add(new JProperty("password", settings.Zoom.Password));
credentials.Add(new JProperty("sdkKey", settings.Zoom.SdkKey));
credentials.Add(new JProperty("signature", settings.Zoom.Signature));
credentials.Add(new JProperty("userName", settings.Zoom.UserName));
}

View file

@ -103,8 +103,7 @@ namespace SafeExamBrowser.Proctoring
}
else if (settings.Zoom.Enabled)
{
start = !string.IsNullOrWhiteSpace(settings.Zoom.ApiKey);
start &= !string.IsNullOrWhiteSpace(settings.Zoom.ApiSecret) || !string.IsNullOrWhiteSpace(settings.Zoom.Signature);
start = !string.IsNullOrWhiteSpace(settings.Zoom.SdkKey) && !string.IsNullOrWhiteSpace(settings.Zoom.Signature);
start &= !string.IsNullOrWhiteSpace(settings.Zoom.MeetingNumber);
start &= !string.IsNullOrWhiteSpace(settings.Zoom.UserName);
}
@ -168,9 +167,9 @@ namespace SafeExamBrowser.Proctoring
settings.JitsiMeet.ServerUrl = args.JitsiMeetServerUrl;
settings.JitsiMeet.Token = args.JitsiMeetToken;
settings.Zoom.ApiKey = args.ZoomApiKey;
settings.Zoom.MeetingNumber = args.ZoomMeetingNumber;
settings.Zoom.Password = args.ZoomPassword;
settings.Zoom.SdkKey = args.ZoomSdkKey;
settings.Zoom.Signature = args.ZoomSignature;
settings.Zoom.Subject = args.ZoomSubject;
settings.Zoom.UserName = args.ZoomUserName;
@ -272,8 +271,8 @@ namespace SafeExamBrowser.Proctoring
Thread.Sleep(2000);
window.Close();
control = default(ProctoringControl);
window = default(IProctoringWindow);
control = default;
window = default;
fileSystem.Delete(filePath);
logger.Info("Stopped proctoring.");

View file

@ -1,17 +1,17 @@
<html>
<head>
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.10.1/css/bootstrap.css" />
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.10.1/css/react-select.css" />
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.5.0/css/bootstrap.css" />
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.5.0/css/react-select.css" />
<meta http-equiv="origin-trial" content="" />
</head>
<body>
<script src="https://source.zoom.us/2.5.0/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/2.5.0/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/2.5.0/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/2.5.0/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/2.5.0/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/zoom-meeting-2.5.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9/crypto-js.min.js"></script>
<script src="https://source.zoom.us/2.10.1/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/2.10.1/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/2.10.1/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/2.10.1/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/2.10.1/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/zoom-meeting-2.10.1.min.js"></script>
<script type="text/javascript">
var audioJoin = 0;
var videoJoin = 0;
@ -76,30 +76,26 @@
}
function startMeeting(credentials) {
const ATTENDEE = 0;
var signature = credentials.signature;
var error = function (res) {
alert(`Failed to initialize meeting: ${JSON.stringify(res)}`);
};
if (!ZoomMtg.checkSystemRequirements()) {
alert('This system does not meet the necessary requirements for Zoom!');
}
var success = function () {
requestAnimationFrame(controlUserInterface);
ZoomMtg.setZoomJSLib('https://source.zoom.us/2.5.0/lib', '/av');
ZoomMtg.preLoadWasm();
ZoomMtg.prepareJssdk();
if (!signature) {
signature = ZoomMtg.generateSignature({
meetingNumber: credentials.meetingNumber,
apiKey: credentials.apiKey,
apiSecret: credentials.apiSecret,
role: ATTENDEE,
ZoomMtg.join({
meetingNumber: new Number(credentials.meetingNumber),
passWord: credentials.password,
sdkKey: credentials.sdkKey,
signature: credentials.signature,
userName: credentials.userName,
error: function (res) {
alert(`Failed to generate signature: ${JSON.stringify(res)}`);
alert(`Failed to join meeting: ${JSON.stringify(res)}`);
}
});
}
};
ZoomMtg.init({
var params = {
audioPanelAlwaysOpen: false,
disableCallOut: true,
disableInvite: true,
@ -123,34 +119,19 @@
showPureSharingContent: false,
videoDrag: true,
videoHeader: true,
meetingInfo: [
'topic',
'host',
'participant',
//'mn',
//'pwd',
//'telPwd',
//'invite',
//'dc'
],
error: function (res) {
alert(`Failed to initialize meeting: ${JSON.stringify(res)}`);
},
success: function () {
requestAnimationFrame(controlUserInterface);
meetingInfo: ['topic', 'host', 'participant'],
error: error,
success: success
};
ZoomMtg.join({
apiKey: credentials.apiKey,
meetingNumber: credentials.meetingNumber,
passWord: credentials.password,
signature: signature,
userName: credentials.userName,
error: function (res) {
alert(`Failed to join meeting: ${JSON.stringify(res)}`);
if (!ZoomMtg.checkSystemRequirements()) {
alert('This system does not meet the necessary requirements for Zoom!');
}
});
}
});
ZoomMtg.setZoomJSLib('https://source.zoom.us/2.10.1/lib', '/av');
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();
ZoomMtg.init(params);
}
function webMessageReceived(args) {

View file

@ -16,9 +16,9 @@ namespace SafeExamBrowser.Server.Contracts.Events
public string JitsiMeetRoomName { get; set; }
public string JitsiMeetServerUrl { get; set; }
public string JitsiMeetToken { get; set; }
public string ZoomApiKey { get; set; }
public string ZoomMeetingNumber { get; set; }
public string ZoomPassword { get; set; }
public string ZoomSdkKey { get; set; }
public string ZoomSignature { get; set; }
public string ZoomSubject { get; set; }
public string ZoomUserName { get; set; }

View file

@ -298,9 +298,9 @@ namespace SafeExamBrowser.Server
attributes.Instruction.JitsiMeetToken = attributesJson["jitsiMeetToken"].Value<string>();
break;
case "ZOOM":
attributes.Instruction.ZoomApiKey = attributesJson["zoomAPIKey"].Value<string>();
attributes.Instruction.ZoomMeetingNumber = attributesJson["zoomRoom"].Value<string>();
attributes.Instruction.ZoomPassword = attributesJson["zoomMeetingKey"].Value<string>();
attributes.Instruction.ZoomSdkKey = attributesJson["zoomAPIKey"].Value<string>();
attributes.Instruction.ZoomSignature = attributesJson["zoomToken"].Value<string>();
attributes.Instruction.ZoomSubject = attributesJson["zoomSubject"].Value<string>();
attributes.Instruction.ZoomUserName = attributesJson["zoomUserName"].Value<string>();

View file

@ -31,16 +31,6 @@ namespace SafeExamBrowser.Settings.Proctoring
/// </summary>
public bool AllowRaiseHand { get; set; }
/// <summary>
/// The API key to be used for authentication.
/// </summary>
public string ApiKey { get; set; }
/// <summary>
/// The API secret to be used for authentication.
/// </summary>
public string ApiSecret { get; set; }
/// <summary>
/// Determines whether the audio starts muted.
/// </summary>
@ -71,6 +61,11 @@ namespace SafeExamBrowser.Settings.Proctoring
/// </summary>
public bool ReceiveVideo { get; set; }
/// <summary>
/// The SDK key to be used for authentication.
/// </summary>
public string SdkKey { get; set; }
/// <summary>
/// Determines whether the audio stream of the user will be sent to the server.
/// </summary>