From 5108697ac88c0819519e34d9895c3f6343fb3671 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Fri, 4 Sep 2020 13:14:52 +0300 Subject: [PATCH 01/13] Add support for Jitsi openidtoken-jwt auth If the widget URL specifies this auth, generate a JWT token containing the info needed by the Jitsi backend. --- package.json | 1 + src/vector/jitsi/index.ts | 53 +++++++++++++++++++++++++++++++++++++-- yarn.lock | 5 ++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d6d7140a09..0a151e0e28 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "browser-request": "^0.3.3", "gfm.css": "^1.1.2", "highlight.js": "^9.13.1", + "jsrsasign": "^9.1.5", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop", "olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz", diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 081246c0a9..47d6e24f73 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -19,6 +19,7 @@ require("./index.scss"); import * as qs from 'querystring'; import { Capability, WidgetApi } from "matrix-react-sdk/src/widgets/WidgetApi"; +import { KJUR } from "jsrsasign"; // Dev note: we use raw JS without many dependencies to reduce bundle size. // We do not need all of React to render a Jitsi conference. @@ -33,6 +34,8 @@ let conferenceId: string; let displayName: string; let avatarUrl: string; let userId: string; +let jitsiAuth: string; +let roomId: string; let widgetApi: WidgetApi; @@ -69,6 +72,8 @@ let widgetApi: WidgetApi; displayName = qsParam('displayName', true); avatarUrl = qsParam('avatarUrl', true); // http not mxc userId = qsParam('userId'); + jitsiAuth = qsParam('auth', true); + roomId = qsParam('roomId', true); if (widgetApi) { await widgetApi.waitReady(); @@ -91,6 +96,45 @@ function switchVisibleContainers() { document.getElementById("joinButtonContainer").style.visibility = inConference ? 'hidden' : 'unset'; } +/** + * Create a JWT token fot jitsi openidtoken-jwt auth + * + * See TODO add link + */ +function createJWTToken() { + // Header + const header = {alg: 'HS256', typ: 'JWT'}; + // Payload + const payload = { + // TODO change this to refer to spec? + iss: "app_id", + sub: jitsiDomain, + aud: `https://${jitsiDomain}`, + room: "*", + context: { + matrix: { + // TODO openid token retrieved as per MSC1960 + token: "foobar", + room_id: roomId, + }, + user: { + avatar: avatarUrl, + name: displayName, + }, + }, + }; + // Sign JWT + // The secret string here is irrelevant, we're only using the JWT + // to transport data to Prosody in the Jitsi stack. + // See TODO add link + return KJUR.jws.JWS.sign( + "HS256", + JSON.stringify(header), + JSON.stringify(payload), + "notused", + ); +} + function joinConference() { // event handler bound in HTML switchVisibleContainers(); @@ -102,7 +146,7 @@ function joinConference() { // event handler bound in HTML "they mention 'external_api' or 'jitsi' in the stack. They're just Jitsi Meet trying to parse " + "our fragment values and not recognizing the options.", ); - const meetApi = new JitsiMeetExternalAPI(jitsiDomain, { + const options = { width: "100%", height: "100%", parentNode: document.querySelector("#jitsiContainer"), @@ -113,7 +157,12 @@ function joinConference() { // event handler bound in HTML MAIN_TOOLBAR_BUTTONS: [], VIDEO_LAYOUT_FIT: "height", }, - }); + jwt: undefined, + }; + if (jitsiAuth === "openidtoken-jwt") { + options.jwt = createJWTToken(); + } + const meetApi = new JitsiMeetExternalAPI(jitsiDomain, options); if (displayName) meetApi.executeCommand("displayName", displayName); if (avatarUrl) meetApi.executeCommand("avatarUrl", avatarUrl); if (userId) meetApi.executeCommand("email", userId); diff --git a/yarn.lock b/yarn.lock index 9b1342e5e6..441250b72c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6914,6 +6914,11 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jsrsasign@^9.1.5: + version "9.1.5" + resolved "https://registry.yarnpkg.com/jsrsasign/-/jsrsasign-9.1.5.tgz#fe286425d2c05b2d0865d24ded53e34b12abd2ca" + integrity sha512-iJLF8FvZHlwyQudrRtQomHj1HdPAcM8QSRTt0FJo8a6iFgaGCpKUrE7lWyELpAjrFs8jUC/Azc0vfhlj3yqHPQ== + jsx-ast-utils@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.3.0.tgz#edd727794ea284d7fda575015ed1b0cde0289ab6" From 8534328921f7e1d0324587b7e825adfe48b33d69 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 18:10:19 +0300 Subject: [PATCH 02/13] Implement OpenID token fetch from Jitsi widget Using MSC1960 to fetch an OpenID token via postmessage API. This is needed for Jitsi openidtoken-jwt auth. --- src/vector/jitsi/index.ts | 85 +++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 12 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 47d6e24f73..48a0cd020c 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -18,8 +18,9 @@ limitations under the License. require("./index.scss"); import * as qs from 'querystring'; -import { Capability, WidgetApi } from "matrix-react-sdk/src/widgets/WidgetApi"; -import { KJUR } from "jsrsasign"; +import {Capability, KnownWidgetActions, WidgetApi} from 'matrix-react-sdk/src/widgets/WidgetApi'; +import {KJUR} from 'jsrsasign'; +import {objectClone} from 'matrix-react-sdk/lib/utils/objects'; // Dev note: we use raw JS without many dependencies to reduce bundle size. // We do not need all of React to render a Jitsi conference. @@ -36,9 +37,54 @@ let avatarUrl: string; let userId: string; let jitsiAuth: string; let roomId: string; +let openIDToken: string; let widgetApi: WidgetApi; +function processOpenIDMessage(msg) { + const data = (msg.action === 'get_openid') ? msg.response : msg.data; + // TODO: just use data.state once https://github.com/matrix-org/matrix-react-sdk/pull/5172 is out + const result = (data.state !== undefined) ? data.state : + (data.success === true) ? 'allowed' : 'blocked'; + + switch (result) { + case 'allowed': + console.info('Successfully got OpenID credentials.'); + openIDToken = data.access_token; + // Send a response if this was not a response + if (msg.action === 'openid_credentials') { + const request = objectClone(msg); + request.response = {}; + window.parent.postMessage(request, '*'); + } + enableJoinButton(); + break; + case 'blocked': + console.warn('OpenID credentials request was blocked by user.'); + break; + default: + // nothing to do + } +} + +/** + * Implements processing OpenID token requests as per MSC1960 + */ +function onWidgetMessage(msg) { + const data = msg.data; + if (!data) { + return; + } + switch (data.action) { + case 'get_openid': + case 'openid_credentials': + processOpenIDMessage(data); + break; + default: + // Nothing to do + } +} + (async function() { try { // The widget's options are encoded into the fragment to avoid leaking info to the server. The widget @@ -78,11 +124,21 @@ let widgetApi: WidgetApi; if (widgetApi) { await widgetApi.waitReady(); await widgetApi.setAlwaysOnScreen(false); // start off as detachable from the screen + + if (jitsiAuth === 'openidtoken-jwt') { + window.addEventListener('message', onWidgetMessage); + widgetApi.callAction( + KnownWidgetActions.GetOpenIDCredentials, + {}, + (response) => {console.log(response);}, + ); + } else { + enableJoinButton(); + } + // TODO: register widgetApi listeners for PTT controls (https://github.com/vector-im/riot-web/issues/12795) + } else { + enableJoinButton(); } - - // TODO: register widgetApi listeners for PTT controls (https://github.com/vector-im/riot-web/issues/12795) - - document.getElementById("joinButton").onclick = () => joinConference(); } catch (e) { console.error("Error setting up Jitsi widget", e); document.getElementById("jitsiContainer").innerText = "Failed to load Jitsi widget"; @@ -90,6 +146,11 @@ let widgetApi: WidgetApi; } })(); + +function enableJoinButton() { + document.getElementById("joinButton").onclick = () => joinConference(); +} + function switchVisibleContainers() { inConference = !inConference; document.getElementById("jitsiContainer").style.visibility = inConference ? 'unset' : 'hidden'; @@ -107,14 +168,13 @@ function createJWTToken() { // Payload const payload = { // TODO change this to refer to spec? - iss: "app_id", + iss: 'app_id', sub: jitsiDomain, aud: `https://${jitsiDomain}`, room: "*", context: { matrix: { - // TODO openid token retrieved as per MSC1960 - token: "foobar", + token: openIDToken, room_id: roomId, }, user: { @@ -128,10 +188,10 @@ function createJWTToken() { // to transport data to Prosody in the Jitsi stack. // See TODO add link return KJUR.jws.JWS.sign( - "HS256", + 'HS256', JSON.stringify(header), JSON.stringify(payload), - "notused", + 'notused', ); } @@ -159,7 +219,7 @@ function joinConference() { // event handler bound in HTML }, jwt: undefined, }; - if (jitsiAuth === "openidtoken-jwt") { + if (jitsiAuth === 'penidtoken-jwt') { options.jwt = createJWTToken(); } const meetApi = new JitsiMeetExternalAPI(jitsiDomain, options); @@ -168,6 +228,7 @@ function joinConference() { // event handler bound in HTML if (userId) meetApi.executeCommand("email", userId); meetApi.on("readyToClose", () => { + window.removeEventListener('message', onWidgetMessage); switchVisibleContainers(); // noinspection JSIgnoredPromiseFromCall From 0410a6b3be82a41457275e4d1ce879dea146e092 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 19:23:36 +0300 Subject: [PATCH 03/13] Use Jitsi domain in the JWT issuer --- src/vector/jitsi/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 48a0cd020c..73c561bccf 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -167,8 +167,10 @@ function createJWTToken() { const header = {alg: 'HS256', typ: 'JWT'}; // Payload const payload = { - // TODO change this to refer to spec? - iss: 'app_id', + // As per Jitsi token auth, `iss` needs to be set to something agreed between + // JWT generating side and Prosody config. Since we have no configuration for + // the widgets, we can't set one anywhere. Using the Jitsi domain here probably makes sense. + iss: jitsiDomain, sub: jitsiDomain, aud: `https://${jitsiDomain}`, room: "*", From 2205f0611eb539cd46016898b5fec4e5438d6067 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 19:25:44 +0300 Subject: [PATCH 04/13] Add some links to the openidtoken-jwt spec --- src/vector/jitsi/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 73c561bccf..3fe0aa3011 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -125,6 +125,7 @@ function onWidgetMessage(msg) { await widgetApi.waitReady(); await widgetApi.setAlwaysOnScreen(false); // start off as detachable from the screen + // See https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification if (jitsiAuth === 'openidtoken-jwt') { window.addEventListener('message', onWidgetMessage); widgetApi.callAction( @@ -160,7 +161,7 @@ function switchVisibleContainers() { /** * Create a JWT token fot jitsi openidtoken-jwt auth * - * See TODO add link + * See https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification */ function createJWTToken() { // Header From 4164df647ca99bd57cb74f8268d5f49cb7f4babe Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 19:51:16 +0300 Subject: [PATCH 05/13] Improve error messsage of Jitsi widget If openidtoken request fails, show an error. Also render error a bit nicer in generic widget load errors. --- src/vector/jitsi/index.html | 4 +++- src/vector/jitsi/index.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vector/jitsi/index.html b/src/vector/jitsi/index.html index b9fc950e15..1259eb1c4a 100644 --- a/src/vector/jitsi/index.html +++ b/src/vector/jitsi/index.html @@ -11,7 +11,9 @@

Jitsi Video Conference

- +
+ +
diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 3fe0aa3011..ba24451feb 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -61,6 +61,7 @@ function processOpenIDMessage(msg) { break; case 'blocked': console.warn('OpenID credentials request was blocked by user.'); + document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; break; default: // nothing to do @@ -142,8 +143,7 @@ function onWidgetMessage(msg) { } } catch (e) { console.error("Error setting up Jitsi widget", e); - document.getElementById("jitsiContainer").innerText = "Failed to load Jitsi widget"; - switchVisibleContainers(); + document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; } })(); From acfd7252bdeb1f5083679fcac269ed2af4be5bb4 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 20:26:05 +0300 Subject: [PATCH 06/13] Remove todo --- src/vector/jitsi/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index ba24451feb..785d4c3c61 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -189,7 +189,6 @@ function createJWTToken() { // Sign JWT // The secret string here is irrelevant, we're only using the JWT // to transport data to Prosody in the Jitsi stack. - // See TODO add link return KJUR.jws.JWS.sign( 'HS256', JSON.stringify(header), From 3b434a70d21daa59bf41ef446d304a7248a0ecb9 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 20:36:26 +0300 Subject: [PATCH 07/13] Fix typo --- src/vector/jitsi/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 785d4c3c61..e3cafa8221 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -221,7 +221,7 @@ function joinConference() { // event handler bound in HTML }, jwt: undefined, }; - if (jitsiAuth === 'penidtoken-jwt') { + if (jitsiAuth === 'openidtoken-jwt') { options.jwt = createJWTToken(); } const meetApi = new JitsiMeetExternalAPI(jitsiDomain, options); From 21c862fe2b5e9ccbf5cacd51e59a0b7b66e4d197 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Mon, 7 Sep 2020 20:47:07 +0300 Subject: [PATCH 08/13] Remove console.log --- src/vector/jitsi/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index e3cafa8221..84a858c094 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -132,7 +132,7 @@ function onWidgetMessage(msg) { widgetApi.callAction( KnownWidgetActions.GetOpenIDCredentials, {}, - (response) => {console.log(response);}, + () => {}, ); } else { enableJoinButton(); From 151dd5709cff0cba373e8f31e702a03bac56ee67 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 8 Sep 2020 11:32:09 +0300 Subject: [PATCH 09/13] Fix import Co-authored-by: Travis Ralston --- src/vector/jitsi/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 84a858c094..fa9e7759fb 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -20,7 +20,7 @@ require("./index.scss"); import * as qs from 'querystring'; import {Capability, KnownWidgetActions, WidgetApi} from 'matrix-react-sdk/src/widgets/WidgetApi'; import {KJUR} from 'jsrsasign'; -import {objectClone} from 'matrix-react-sdk/lib/utils/objects'; +import {objectClone} from 'matrix-react-sdk/src/utils/objects'; // Dev note: we use raw JS without many dependencies to reduce bundle size. // We do not need all of React to render a Jitsi conference. From 3309b2ec552bc463e7a7197ce7c44bc8b6aec0b9 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 8 Sep 2020 11:37:50 +0300 Subject: [PATCH 10/13] Block on matrix-org/matrix-react-sdk#5172 And shuffle code around a bit. --- src/vector/jitsi/index.ts | 86 +++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index fa9e7759fb..8392e1e530 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -41,51 +41,6 @@ let openIDToken: string; let widgetApi: WidgetApi; -function processOpenIDMessage(msg) { - const data = (msg.action === 'get_openid') ? msg.response : msg.data; - // TODO: just use data.state once https://github.com/matrix-org/matrix-react-sdk/pull/5172 is out - const result = (data.state !== undefined) ? data.state : - (data.success === true) ? 'allowed' : 'blocked'; - - switch (result) { - case 'allowed': - console.info('Successfully got OpenID credentials.'); - openIDToken = data.access_token; - // Send a response if this was not a response - if (msg.action === 'openid_credentials') { - const request = objectClone(msg); - request.response = {}; - window.parent.postMessage(request, '*'); - } - enableJoinButton(); - break; - case 'blocked': - console.warn('OpenID credentials request was blocked by user.'); - document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; - break; - default: - // nothing to do - } -} - -/** - * Implements processing OpenID token requests as per MSC1960 - */ -function onWidgetMessage(msg) { - const data = msg.data; - if (!data) { - return; - } - switch (data.action) { - case 'get_openid': - case 'openid_credentials': - processOpenIDMessage(data); - break; - default: - // Nothing to do - } -} - (async function() { try { // The widget's options are encoded into the fragment to avoid leaking info to the server. The widget @@ -147,6 +102,47 @@ function onWidgetMessage(msg) { } })(); +function processOpenIDMessage(msg) { + const data = (msg.action === 'get_openid') ? msg.response : msg.data; + + switch (data.state) { + case 'allowed': + console.info('Successfully got OpenID credentials.'); + openIDToken = data.access_token; + // Send a response if this was not a response + if (msg.action === 'openid_credentials') { + const request = objectClone(msg); + request.response = {}; + window.parent.postMessage(request, '*'); + } + enableJoinButton(); + break; + case 'blocked': + console.warn('OpenID credentials request was blocked by user.'); + document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; + break; + default: + // nothing to do + } +} + +/** + * Implements processing OpenID token requests as per MSC1960 + */ +function onWidgetMessage(msg) { + const data = msg.data; + if (!data) { + return; + } + switch (data.action) { + case 'get_openid': + case 'openid_credentials': + processOpenIDMessage(data); + break; + default: + // Nothing to do + } +} function enableJoinButton() { document.getElementById("joinButton").onclick = () => joinConference(); From a7abd8599e56eb63c1bbec0bae1721115eb05a1c Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 8 Sep 2020 11:44:11 +0300 Subject: [PATCH 11/13] More usage of constants --- src/vector/jitsi/index.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 8392e1e530..a80a07c471 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -22,6 +22,8 @@ import {Capability, KnownWidgetActions, WidgetApi} from 'matrix-react-sdk/src/wi import {KJUR} from 'jsrsasign'; import {objectClone} from 'matrix-react-sdk/src/utils/objects'; +const JITSI_OPENIDTOKEN_JWT_AUTH = 'openidtoken-jwt'; + // Dev note: we use raw JS without many dependencies to reduce bundle size. // We do not need all of React to render a Jitsi conference. @@ -82,7 +84,7 @@ let widgetApi: WidgetApi; await widgetApi.setAlwaysOnScreen(false); // start off as detachable from the screen // See https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification - if (jitsiAuth === 'openidtoken-jwt') { + if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) { window.addEventListener('message', onWidgetMessage); widgetApi.callAction( KnownWidgetActions.GetOpenIDCredentials, @@ -103,14 +105,14 @@ let widgetApi: WidgetApi; })(); function processOpenIDMessage(msg) { - const data = (msg.action === 'get_openid') ? msg.response : msg.data; + const data = (msg.action === KnownWidgetActions.GetOpenIDCredentials) ? msg.response : msg.data; switch (data.state) { case 'allowed': console.info('Successfully got OpenID credentials.'); openIDToken = data.access_token; - // Send a response if this was not a response - if (msg.action === 'openid_credentials') { + // Send a response if this was not a response to GetOpenIDCredentials + if (msg.action === KnownWidgetActions.ReceiveOpenIDCredentials) { const request = objectClone(msg); request.response = {}; window.parent.postMessage(request, '*'); @@ -135,8 +137,8 @@ function onWidgetMessage(msg) { return; } switch (data.action) { - case 'get_openid': - case 'openid_credentials': + case KnownWidgetActions.GetOpenIDCredentials: + case KnownWidgetActions.ReceiveOpenIDCredentials: processOpenIDMessage(data); break; default: @@ -217,7 +219,7 @@ function joinConference() { // event handler bound in HTML }, jwt: undefined, }; - if (jitsiAuth === 'openidtoken-jwt') { + if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) { options.jwt = createJWTToken(); } const meetApi = new JitsiMeetExternalAPI(jitsiDomain, options); From 579650a1dd61d466d0125cc621ccf00724823c29 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 8 Sep 2020 12:50:53 +0300 Subject: [PATCH 12/13] Move most of the OpenID token flow to WidgetAPI --- src/vector/jitsi/index.ts | 77 +++++++++++++-------------------------- 1 file changed, 25 insertions(+), 52 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index a80a07c471..0f94f04db0 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -18,9 +18,8 @@ limitations under the License. require("./index.scss"); import * as qs from 'querystring'; -import {Capability, KnownWidgetActions, WidgetApi} from 'matrix-react-sdk/src/widgets/WidgetApi'; +import {Capability, WidgetApi} from 'matrix-react-sdk/src/widgets/WidgetApi'; import {KJUR} from 'jsrsasign'; -import {objectClone} from 'matrix-react-sdk/src/utils/objects'; const JITSI_OPENIDTOKEN_JWT_AUTH = 'openidtoken-jwt'; @@ -39,7 +38,6 @@ let avatarUrl: string; let userId: string; let jitsiAuth: string; let roomId: string; -let openIDToken: string; let widgetApi: WidgetApi; @@ -85,12 +83,8 @@ let widgetApi: WidgetApi; // See https://github.com/matrix-org/prosody-mod-auth-matrix-user-verification if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) { - window.addEventListener('message', onWidgetMessage); - widgetApi.callAction( - KnownWidgetActions.GetOpenIDCredentials, - {}, - () => {}, - ); + // Request credentials, give callback to continue when received + widgetApi.requestOpenIDCredentials(credentialsResponseCallback); } else { enableJoinButton(); } @@ -104,45 +98,16 @@ let widgetApi: WidgetApi; } })(); -function processOpenIDMessage(msg) { - const data = (msg.action === KnownWidgetActions.GetOpenIDCredentials) ? msg.response : msg.data; - - switch (data.state) { - case 'allowed': - console.info('Successfully got OpenID credentials.'); - openIDToken = data.access_token; - // Send a response if this was not a response to GetOpenIDCredentials - if (msg.action === KnownWidgetActions.ReceiveOpenIDCredentials) { - const request = objectClone(msg); - request.response = {}; - window.parent.postMessage(request, '*'); - } - enableJoinButton(); - break; - case 'blocked': - console.warn('OpenID credentials request was blocked by user.'); - document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; - break; - default: - // nothing to do - } -} - /** - * Implements processing OpenID token requests as per MSC1960 + * Enable or show error depending on what the credentials response is. */ -function onWidgetMessage(msg) { - const data = msg.data; - if (!data) { - return; - } - switch (data.action) { - case KnownWidgetActions.GetOpenIDCredentials: - case KnownWidgetActions.ReceiveOpenIDCredentials: - processOpenIDMessage(data); - break; - default: - // Nothing to do +function credentialsResponseCallback() { + if (widgetApi.openIDCredentials) { + console.info('Successfully got OpenID credentials.'); + enableJoinButton(); + } else { + console.warn('OpenID credentials request was blocked by user.'); + document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; } } @@ -175,7 +140,7 @@ function createJWTToken() { room: "*", context: { matrix: { - token: openIDToken, + token: widgetApi.openIDCredentials.accessToken, room_id: roomId, }, user: { @@ -196,6 +161,17 @@ function createJWTToken() { } function joinConference() { // event handler bound in HTML + let jwt; + if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) { + if (!widgetApi.openIDCredentials || !widgetApi.openIDCredentials.accessToken) { + // We've failing to get a token, don't try to init conference + console.warn('Expected to have an OpenID credential, cannot initialize widget.'); + document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget"; + return; + } + jwt = createJWTToken(); + } + switchVisibleContainers(); // noinspection JSIgnoredPromiseFromCall @@ -217,18 +193,15 @@ function joinConference() { // event handler bound in HTML MAIN_TOOLBAR_BUTTONS: [], VIDEO_LAYOUT_FIT: "height", }, - jwt: undefined, + jwt: jwt, }; - if (jitsiAuth === JITSI_OPENIDTOKEN_JWT_AUTH) { - options.jwt = createJWTToken(); - } + const meetApi = new JitsiMeetExternalAPI(jitsiDomain, options); if (displayName) meetApi.executeCommand("displayName", displayName); if (avatarUrl) meetApi.executeCommand("avatarUrl", avatarUrl); if (userId) meetApi.executeCommand("email", userId); meetApi.on("readyToClose", () => { - window.removeEventListener('message', onWidgetMessage); switchVisibleContainers(); // noinspection JSIgnoredPromiseFromCall From 7018a498a70931fc01e5835fc63d08640f264f72 Mon Sep 17 00:00:00 2001 From: Jason Robinson Date: Tue, 8 Sep 2020 12:52:17 +0300 Subject: [PATCH 13/13] Quieten some IDE warnings --- src/vector/jitsi/index.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts index 0f94f04db0..6e697fee2f 100644 --- a/src/vector/jitsi/index.ts +++ b/src/vector/jitsi/index.ts @@ -174,8 +174,11 @@ function joinConference() { // event handler bound in HTML switchVisibleContainers(); - // noinspection JSIgnoredPromiseFromCall - if (widgetApi) widgetApi.setAlwaysOnScreen(true); // ignored promise because we don't care if it works + if (widgetApi) { + // ignored promise because we don't care if it works + // noinspection JSIgnoredPromiseFromCall + widgetApi.setAlwaysOnScreen(true); + } console.warn( "[Jitsi Widget] The next few errors about failing to parse URL parameters are fine if " + @@ -204,8 +207,11 @@ function joinConference() { // event handler bound in HTML meetApi.on("readyToClose", () => { switchVisibleContainers(); - // noinspection JSIgnoredPromiseFromCall - if (widgetApi) widgetApi.setAlwaysOnScreen(false); // ignored promise because we don't care if it works + if (widgetApi) { + // ignored promise because we don't care if it works + // noinspection JSIgnoredPromiseFromCall + widgetApi.setAlwaysOnScreen(false); + } document.getElementById("jitsiContainer").innerHTML = ""; });