diff --git a/plugins/rms.openwebrx.guard/index.js b/plugins/rms.openwebrx.guard/index.js index edac88e..9b2692e 100644 --- a/plugins/rms.openwebrx.guard/index.js +++ b/plugins/rms.openwebrx.guard/index.js @@ -58,10 +58,12 @@ function issueAccess(ctx, tickets, input) { expiresAtMs }); const openWebRxPath = String(ctx.getSetting("upstreamPath", ctx.env.OPENWEBRX_PATH || "/openwebrx/")).trim() || "/openwebrx/"; + const separator = openWebRxPath.includes("?") ? "&" : "?"; + const iframeUrl = `${openWebRxPath}${separator}ticket=${encodeURIComponent(ticket)}`; return { ticket, expiresAt: new Date(expiresAtMs).toISOString(), - iframeUrl: openWebRxPath, + iframeUrl, userId }; } diff --git a/public/app.js b/public/app.js index 8169de3..9120b23 100644 --- a/public/app.js +++ b/public/app.js @@ -1617,8 +1617,9 @@ async function openOpenWebRxSession() { try { const result = await requestOpenWebRxSessionWithRetry(); const session = result && result.session ? result.session : null; - state.openWebRx.sessionUrl = session && session.iframeUrl ? session.iframeUrl : ""; - state.openWebRx.sessionTicket = session && session.ticket ? String(session.ticket) : ""; + const sessionTicket = session && session.ticket ? String(session.ticket) : ""; + state.openWebRx.sessionUrl = buildOpenWebRxSessionUrl(session && session.iframeUrl ? session.iframeUrl : "", sessionTicket); + state.openWebRx.sessionTicket = sessionTicket; state.openWebRx.expiresAt = session && session.expiresAt ? session.expiresAt : null; syncOpenWebRxTicketCookie(state.openWebRx.sessionTicket, state.openWebRx.expiresAt); renderOpenWebRxSessionAccess(); @@ -1641,12 +1642,13 @@ async function openOpenWebRxExternal() { try { const result = await requestOpenWebRxSessionWithRetry(); const session = result && result.session ? result.session : null; - const sessionUrl = session && session.iframeUrl ? String(session.iframeUrl) : ""; + const sessionTicket = session && session.ticket ? String(session.ticket) : ""; + const sessionUrl = buildOpenWebRxSessionUrl(session && session.iframeUrl ? String(session.iframeUrl) : "", sessionTicket); if (!sessionUrl) { throw new Error("OpenWebRX Session konnte nicht erstellt werden"); } state.openWebRx.sessionUrl = sessionUrl; - state.openWebRx.sessionTicket = session && session.ticket ? String(session.ticket) : ""; + state.openWebRx.sessionTicket = sessionTicket; state.openWebRx.expiresAt = session && session.expiresAt ? session.expiresAt : null; syncOpenWebRxTicketCookie(state.openWebRx.sessionTicket, state.openWebRx.expiresAt); renderOpenWebRxSessionAccess(); @@ -1658,6 +1660,22 @@ async function openOpenWebRxExternal() { } } +function buildOpenWebRxSessionUrl(rawUrl, ticket) { + const baseUrl = String(rawUrl || "").trim(); + const normalizedTicket = String(ticket || "").trim(); + if (!baseUrl) { + return ""; + } + if (!normalizedTicket) { + return baseUrl; + } + if (/[?&]ticket=/.test(baseUrl)) { + return baseUrl; + } + const separator = baseUrl.includes("?") ? "&" : "?"; + return `${baseUrl}${separator}ticket=${encodeURIComponent(normalizedTicket)}`; +} + async function requestOpenWebRxSessionWithRetry() { const attempts = [0, 700, 1400, 2200]; let lastError = null; diff --git a/test/auth-methods.integration.test.js b/test/auth-methods.integration.test.js index 3d97ab5..7def689 100644 --- a/test/auth-methods.integration.test.js +++ b/test/auth-methods.integration.test.js @@ -1667,6 +1667,7 @@ test("openwebrx session is owner-bound and release disables tx first", async (t) }); assert.equal(session.ok, true); assert.ok(session.session.ticket); + assert.match(String(session.session.iframeUrl || ""), /[?&]ticket=/); const authOk = await fetch(`${baseUrl}/v1/openwebrx/authorize?ticket=${encodeURIComponent(session.session.ticket)}`); assert.equal(authOk.status, 200);