diff --git a/config.js b/config.js index f0e194791923..7b6eb07992c4 100644 --- a/config.js +++ b/config.js @@ -53,6 +53,8 @@ var config = { // websocketKeepAliveUrl: 'https://jitsi-meet.example.com/' + subdir + '_unlock', + // websocketWarmUpUrl: 'https://jitsi-meet.example.com/' + subdir + 'ws-warm-up'; + // Whether BOSH should be preferred over WebSocket if both are configured. // preferBosh: false, diff --git a/react/features/base/config/configType.ts b/react/features/base/config/configType.ts index 283bceadf3c3..6580e93f9af3 100644 --- a/react/features/base/config/configType.ts +++ b/react/features/base/config/configType.ts @@ -736,6 +736,7 @@ export interface IConfig { webrtcIceUdpDisable?: boolean; websocket?: string; websocketKeepAliveUrl?: string; + websocketWarmUpUrl?: string; welcomePage?: { customUrl?: string; disabled?: boolean; diff --git a/react/features/base/connection/actions.any.ts b/react/features/base/connection/actions.any.ts index 548726168989..b5d9ba2f7ff3 100644 --- a/react/features/base/connection/actions.any.ts +++ b/react/features/base/connection/actions.any.ts @@ -153,6 +153,9 @@ export function constructOptions(state: IReduxState) { if (options.conferenceRequestUrl) { options.conferenceRequestUrl = appendURLParam(options.conferenceRequestUrl, 'room', roomName ?? ''); } + if (options.websocketWarmUpUrl) { + options.websocketWarmUpUrl = appendURLParam(options.websocketWarmUpUrl, 'room', roomName ?? ''); + } } if (preferVisitor) { diff --git a/resources/prosody-plugins/mod_auth_token.lua b/resources/prosody-plugins/mod_auth_token.lua index c9f8abcaa533..2c0e6c56f665 100644 --- a/resources/prosody-plugins/mod_auth_token.lua +++ b/resources/prosody-plugins/mod_auth_token.lua @@ -60,7 +60,7 @@ function provider.delete_user(username) return nil; end -function first_stage_auth(session) +function first_stage_auth(session, skip_verify) -- retrieve custom public key from server and save it on the session local pre_event_result = prosody.events.fire_event("pre-jitsi-authentication-fetch-key", session); if pre_event_result ~= nil and pre_event_result.res == false then @@ -72,6 +72,9 @@ function first_stage_auth(session) end local res, error, reason = token_util:process_and_verify_token(session); + if skip_verify then + res = true; + end if res == false then module:log("warn", "Error verifying token err:%s, reason:%s tenant:%s room:%s user_agent:%s", @@ -107,17 +110,12 @@ function provider.get_sasl_handler(session) local function get_username_from_token(self, message) - local s1_result = first_stage_auth(session); - if s1_result.res == false then - return s1_result.res, s1_result.error, s1_result.reason; - end - - if s1_result.custom_username then - self.username = s1_result.custom_username; - elseif session.previd ~= nil then + local resuming_without_token = false; + if session.previd ~= nil then for _, session1 in pairs(sessions) do if (session1.resumption_token == session.previd) then self.username = session1.username; + resuming_without_token = not session.auth_token; break; end end @@ -125,6 +123,14 @@ function provider.get_sasl_handler(session) self.username = message; end + local s1_result = first_stage_auth(session, resuming_without_token); + if s1_result.res == false then + return s1_result.res, s1_result.error, s1_result.reason; + end + if s1_result.custom_username then + self.username = s1_result.custom_username; + end + local s2_result = second_stage_auth(session); if s2_result and s2_result.res ~= nil then return s2_result.res, s2_result.error, s2_result.reason; diff --git a/static/sso.html b/static/sso.html index 7e7642e2a0b8..b9332823c204 100644 --- a/static/sso.html +++ b/static/sso.html @@ -231,13 +231,27 @@ throw new Error('No authorization code received'); } - // Retrieve code_verifier and oauth_nonce from sessionStorage (set during login initiation) - const codeVerifier = sessionStorage.getItem('code_verifier'); + // Retrieve code_verifier and oauth_nonce from sessionStorage (set during login initiation). + // In popup mode the values were stored in the opener's sessionStorage, not in this popup's. + let openerStorage = null; + + try { + if (window.opener && window.opener.sessionStorage) { + openerStorage = window.opener.sessionStorage; + } + } catch (e) { + // Cross-origin opener – fall back to own sessionStorage. + } + const storage = openerStorage || sessionStorage; + + const codeVerifier = storage.getItem('code_verifier'); + if (!codeVerifier) { throw new Error('No PKCE code verifier found in session'); } - const oauthNonce = sessionStorage.getItem('oauth_nonce'); + const oauthNonce = storage.getItem('oauth_nonce'); + if (!oauthNonce) { throw new Error('No OAuth nonce found in session'); }