Skip to content

Commit

Permalink
feat(jwt): Move client JWT to fragments from query parameters (jitsi#640
Browse files Browse the repository at this point in the history
)

* chore(jwt): move client JWT to fragments from query parameters

* squash: Uses hash params for the iframeAPI tests.

The param parsing logic is from jitsi-meet.

* squash: Fixes setting userInfo.

* squash: Fixes userInfo for old tests.

---------

Co-authored-by: damencho <damencho@jitsi.org>
  • Loading branch information
aaronkvanmeerten and damencho authored May 31, 2024
1 parent f9d24ee commit 995cb67
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 47 deletions.
19 changes: 13 additions & 6 deletions src/test/java/org/jitsi/meet/test/IFrameAPIBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.jitsi.meet.test;

import com.google.gson.*;
import org.apache.commons.lang3.*;
import org.jitsi.meet.test.base.*;
import org.jitsi.meet.test.util.*;
import org.jitsi.meet.test.web.*;
Expand Down Expand Up @@ -144,12 +145,18 @@ protected JitsiMeetUrl getIFrameUrl(JsonObject userInfo, String password, String
.appendConfig(config)
.getFragmentParamsAsJson();

iFrameUrl.addRoomParameter("domain", domain);
iFrameUrl.addRoomParameter("room", currentRoomName);
iFrameUrl.addRoomParameter("config", defaultParams.get("config").toString());
iFrameUrl.addRoomParameter("interfaceConfig", defaultParams.get("interfaceConfig").toString());
iFrameUrl.addRoomParameter("userInfo", userInfo != null ? userInfo.toString() : "");
iFrameUrl.addRoomParameter("password", password != null ? password : "");
iFrameUrl.addFragmentParam("domain", domain);
iFrameUrl.addFragmentParam("room", currentRoomName);

// do not include empty params (externalAPI complains)
if (userInfo != null && StringUtils.isNotBlank(userInfo.toString()))
{
iFrameUrl.addFragmentParam("userInfo", userInfo.toString());
}
if (password != null && StringUtils.isNotBlank(password))
{
iFrameUrl.addFragmentParam("password", password);
}

// Override the server and the path part(which is s room name)
iFrameUrl.setServerUrl(pagePath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void testFunctionGetParticipantsInfo()

this.iFrameUrl = getIFrameUrl(userInfo, null);

ensureOneParticipant(this.iFrameUrl);
ensureOneParticipant(this.iFrameUrl, new WebParticipantOptions().setSkipDisplayNameSet(true));

WebParticipant participant1 = getParticipant1();
String endpointId1 = participant1.getEndpointId();
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/org/jitsi/meet/test/LastNTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void testLastN()
WebDriver driver1 = participant1.getDriver();

WebParticipant participant2 = joinSecondParticipant(meetUrl2);
WebDriver driver2 = participant2.getDriver();

participant2.waitToJoinMUC();
participant2.waitForIceConnected();

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/org/jitsi/meet/test/ModeratedRoomsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void testModeratedTenant()
JitsiMeetUrl url = getJitsiMeetUrl();
url.setRoomName(tenantName + '/' + url.getRoomName());

ensureTwoParticipants(url.copy().addRoomParameter("jwt", token), url);
ensureTwoParticipants(url.copy().addFragmentParam("jwt", token), url);

assertTrue(getParticipant1().isModerator(), "Participant 1 must be moderator");
assertFalse(getParticipant2().isModerator(), "Participant 2 must not be moderator");
Expand Down
17 changes: 16 additions & 1 deletion src/test/java/org/jitsi/meet/test/base/JitsiMeetUrl.java
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,20 @@ public JitsiMeetUrl addRoomParameter(String paramKey, String paramValue)
return this;
}

/**
* Sets the {@link #fragmentParameters} part of the conference URL.
*
* @param paramKey the fragment parameter key name
* @param paramValue the value to assign to the framgent parameter key
* @return a reference to this object.
*/
public JitsiMeetUrl addFragmentParam(String paramKey, String paramValue)
{
this.fragmentParams.put(paramKey, paramValue);

return this;
}

/**
* Sets the {@link #serverUrl} part of the conference URL.
*
Expand Down Expand Up @@ -422,7 +436,8 @@ public String toString()

urlBuilder.append(entry.getKey());
urlBuilder.append("=");
urlBuilder.append(entry.getValue());
// make sure we add a valid json param
urlBuilder.append(JsonParser.parseString(entry.getValue()).toString());
}

return urlBuilder.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ public JitsiMeetUrl getJitsiMeetUrl()
String token = System.getProperty(TOKEN_PNAME);
if (StringUtils.isNotBlank(token))
{
url.addRoomParameter("jwt", token);
url.addFragmentParam("jwt", token);
}

return url;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public void testPersonalRoom()

// moderator + guest
ensureThreeParticipants(
url.copy().addRoomParameter("jwt", moderator1Token),
url.copy().addRoomParameter("jwt", moderator2Token),
url.copy().addFragmentParam("jwt", moderator1Token),
url.copy().addFragmentParam("jwt", moderator2Token),
url);

// FIXME: Showing remote video menu in tileview does not work
Expand Down Expand Up @@ -107,8 +107,8 @@ public void testRandomRoom()

// moderator + guest
ensureThreeParticipants(
url.copy().addRoomParameter("jwt", moderator1Token),
url.copy().addRoomParameter("jwt", moderator2Token),
url.copy().addFragmentParam("jwt", moderator1Token),
url.copy().addFragmentParam("jwt", moderator2Token),
url);

// FIXME: Showing remote video menu in tileview does not work
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/org/jitsi/meet/test/misc/BackendLobbyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void testPersonalWithNoLobby()
JitsiMeetUrl url = getJitsiMeetUrl();
url.setRoomName(tenantName + '/' + nonModerator1RoomName);

ensureTwoParticipants(url.copy().addRoomParameter("jwt", nonModerator1Token), url);
ensureTwoParticipants(url.copy().addFragmentParam("jwt", nonModerator1Token), url);

assertFalse(getParticipant1().getSecurityDialog().isLobbyEnabled());
assertFalse(getParticipant2().getSecurityDialog().isLobbySectionPresent());
Expand Down Expand Up @@ -141,7 +141,7 @@ public void testPersonalRoomWithLobby()

lobbyScreen.join();

joinSecondParticipant(url.copy().addRoomParameter("jwt", moderatorToken));
joinSecondParticipant(url.copy().addFragmentParam("jwt", moderatorToken));
WebParticipant moderator = getParticipant2();

moderator.waitToJoinMUC();
Expand All @@ -154,7 +154,7 @@ public void testPersonalRoomWithLobby()

moderator.hangUp();

joinSecondParticipant(url.copy().addRoomParameter("jwt", moderatorToken));
joinSecondParticipant(url.copy().addFragmentParam("jwt", moderatorToken));
moderator = getParticipant2();

moderator.waitToJoinMUC();
Expand All @@ -163,7 +163,7 @@ public void testPersonalRoomWithLobby()
assertEquals(name2, participant1.getName(),
"Wrong name for the knocking participant or participant is missing");

joinThirdParticipant(url.copy().addRoomParameter("jwt", nonModerator2Token), null);
joinThirdParticipant(url.copy().addFragmentParam("jwt", nonModerator2Token), null);

WebParticipant participant3 = getParticipant3();
LobbyScreen lobbyScreen3 = participant3.getLobbyScreen();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ public void testRoomPreSetPassword()
JitsiMeetUrl url = getJitsiMeetUrl();
url.setRoomName(tenantName + '/' + roomName);

joinFirstParticipant(url.copy().addRoomParameter("jwt", moderator1Token), null);
joinFirstParticipant(url.copy().addFragmentParam("jwt", moderator1Token), null);

joinWithPassAndCheck(getParticipant1());

joinSecondParticipant(url.copy().addRoomParameter("jwt", moderator2Token));
joinSecondParticipant(url.copy().addFragmentParam("jwt", moderator2Token));
joinWithPassAndCheck(getParticipant2());

joinThirdParticipant(url, null);
Expand Down
10 changes: 5 additions & 5 deletions src/test/java/org/jitsi/meet/test/misc/SingleModeratorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void testPersonalRoomAndModerators()
url.setRoomName(tenantName + '/' + roomName);

// moderator + guest
ensureTwoParticipants(url.copy().addRoomParameter("jwt", moderatorToken), url);
ensureTwoParticipants(url.copy().addFragmentParam("jwt", moderatorToken), url);

assertTrue(getParticipant1().isModerator(), "Participant 1 must be moderator");
assertFalse(getParticipant2().isModerator(), "Participant 2 must not be moderator");
Expand All @@ -89,8 +89,8 @@ public void testPersonalRoomAndModerators()

// moderator + another authenticated user from same tenant
ensureTwoParticipants(
url.copy().addRoomParameter("jwt", moderatorToken),
url.copy().addRoomParameter("jwt", nonModerator1Token));
url.copy().addFragmentParam("jwt", moderatorToken),
url.copy().addFragmentParam("jwt", nonModerator1Token));

assertFalse(getParticipant2().isModerator(), "Participant 2 must not be moderator");
ModeratedRoomsTest.checkModeratorMenuItems(getParticipant2(), getParticipant1());
Expand All @@ -99,8 +99,8 @@ public void testPersonalRoomAndModerators()

// moderator + another authenticated user from different tenant
ensureTwoParticipants(
url.copy().addRoomParameter("jwt", moderatorToken),
url.copy().addRoomParameter("jwt", nonModerator2Token));
url.copy().addFragmentParam("jwt", moderatorToken),
url.copy().addFragmentParam("jwt", nonModerator2Token));

assertFalse(getParticipant2().isModerator(), "Participant 2 must not be moderator");
ModeratedRoomsTest.checkModeratorMenuItems(getParticipant2(), getParticipant1());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public void testTwoModeratorsFromSameTenant()

// moderator + guest
ensureThreeParticipants(
url.copy().addRoomParameter("jwt", moderator1Token),
url.copy().addRoomParameter("jwt", moderator2Token),
url.copy().addFragmentParam("jwt", moderator1Token),
url.copy().addFragmentParam("jwt", moderator2Token),
url);

// FIXME: Showing remote video menu in tile view does not work
Expand All @@ -102,8 +102,8 @@ public void testTwoModeratorsFromSameTenant()
// Now let's test changing the second participant with one from different tenant
getParticipant2().hangUp();
ensureThreeParticipants(
url.copy().addRoomParameter("jwt", moderator1Token),
url.copy().addRoomParameter("jwt", nonModeratorToken),
url.copy().addFragmentParam("jwt", moderator1Token),
url.copy().addFragmentParam("jwt", nonModeratorToken),
url);

// FIXME: Showing remote video menu in tileview does not work
Expand Down
95 changes: 78 additions & 17 deletions src/test/resources/files/iframeAPITest.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,86 @@
</head>
<body>
<script>
const params = new URLSearchParams(document.location.search);
const config = JSON.parse(params.get("config"));
const interfaceConfig = JSON.parse(params.get("interfaceConfig"));
const password = params.get("password");

const uInfoObj = params.get("userInfo");
const userInfo = uInfoObj && uInfoObj.length > 0 ?
JSON.parse(uInfoObj) : undefined;

var domain = params.get("domain");
var options = {
jwt: params.get("jwt"),
roomName: params.get("room"),
const blacklist = [ '__proto__', 'constructor', 'prototype' ];
const paramStr = document.location.hash;
const params = {};
const paramParts = paramStr?.substring(1).split('&') || [];

paramParts.forEach(part => {
const param = part.split('=');
const key = param[0];

if (!key || key.split('.').some(k => blacklist.includes(k))) {
return;
}

let value;

try {
value = param[1];


const decoded = decodeURIComponent(value).replace(/\\&/, '&')
.replace(/[\u2018\u2019]/g, '\'')
.replace(/[\u201C\u201D]/g, '"');

value = decoded === 'undefined' || decoded === '' ? undefined : JSON.parse(decoded);

} catch (e) {
console.error(`Failed to parse URL parameter value: ${String(value)}`, e);

return;
}
params[key] = value;
});
const json = {
config: {},
interfaceConfig: {}
};

for (const param of Object.keys(params)) {
let base = json;
const names = param.split('.');
const last = names.pop() ?? '';

for (const name of names) {
base = base[name] = base[name] || {};
}

base[last] = params[param];
}

// we can drop the url params in the future
const urlParams = new URLSearchParams(document.location.search);

const config = !Object.keys(json.config).length ? JSON.parse(urlParams.get("config"))
: json.config;
const interfaceConfig = !Object.keys(json.interfaceConfig).length ? JSON.parse(urlParams.get("interfaceConfig"))
: json.interfaceConfig;
const password = json.password || urlParams.get("password");
const uInfoObj = urlParams.get("userInfo") || json.userInfo; // prefer url just for compatability with old code

let userInfo;
if (uInfoObj) {
if (uInfoObj.length > 0) {
userInfo = JSON.parse(uInfoObj);
} else if (Object.keys(uInfoObj).length) {
userInfo = uInfoObj;
}
}
const jwt = json.jwt || urlParams.get("jwt");
const roomName = json.room || urlParams.get("room");
const domain = json.domain || urlParams.get("domain");

const options = {
jwt,
roomName,
configOverwrite: config,
interfaceConfigOverwrite: interfaceConfig,
userInfo
};

var externalAPIScript = document.createElement('script');
const externalAPIScript = document.createElement('script');
externalAPIScript.src = `https://${domain}/external_api.js`;
externalAPIScript.type = "text/javascript";
externalAPIScript.onload = function(){
Expand All @@ -36,13 +97,13 @@
window.jitsiAPI.test.isModerator = true;
}
});
window.jitsiAPI.addListener('audioAvailabilityChanged', function(event) {
window.jitsiAPI.addEventListener('audioAvailabilityChanged', function(event) {
window.jitsiAPI.test.audioAvailabilityChanged = event;
});
window.jitsiAPI.addListener('videoAvailabilityChanged', function(event) {
window.jitsiAPI.addEventListener('videoAvailabilityChanged', function(event) {
window.jitsiAPI.test.videoAvailabilityChanged = event;
});
window.jitsiAPI.addListener('videoConferenceJoined', function(event) {
window.jitsiAPI.addEventListener('videoConferenceJoined', function(event) {
window.jitsiAPI.test.videoConferenceJoined = event;
});
if (password && password.length > 0) {
Expand Down

0 comments on commit 995cb67

Please sign in to comment.