From b311103347c6a26d05875e6f48ad2015c03228bc Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 2 Feb 2024 16:44:31 -0500 Subject: [PATCH 1/5] Add basic auth to extension --- build/UserALEWebExtension/background.js | 13 +++++++++---- build/UserALEWebExtension/content.js | 1 - build/UserALEWebExtension/options.js | 12 ++++++++++-- build/UserALEWebExtension/optionsPage.html | 10 +++++----- src/UserALEWebExtension/background.js | 10 +++++++--- src/UserALEWebExtension/messageTypes.js | 1 + src/UserALEWebExtension/options.js | 11 ++++++++++- src/UserALEWebExtension/optionsPage.html | 10 +++++----- 8 files changed, 47 insertions(+), 21 deletions(-) diff --git a/build/UserALEWebExtension/background.js b/build/UserALEWebExtension/background.js index d7d0bfc8..8b470959 100644 --- a/build/UserALEWebExtension/background.js +++ b/build/UserALEWebExtension/background.js @@ -17,6 +17,7 @@ var prefix = 'USERALE_'; var CONFIG_CHANGE = prefix + 'CONFIG_CHANGE'; +var AUTH_CHANGE = prefix + 'AUTH_CHANGE'; var ADD_LOG = prefix + 'ADD_LOG'; function _typeof(o) { @@ -1144,14 +1145,18 @@ function dispatchTabMessage(message) { } browser.runtime.onMessage.addListener(function (message) { switch (message.type) { + // Handles logs rerouted from content and option scripts + case ADD_LOG: + log(message.payload); + break; case CONFIG_CHANGE: options(message.payload); dispatchTabMessage(message); break; - - // Handles logs rerouted from content and option scripts - case ADD_LOG: - log(message.payload); + case AUTH_CHANGE: + options({ + authHeader: message.payload + }); break; default: console.log('got unknown message type ', message); diff --git a/build/UserALEWebExtension/content.js b/build/UserALEWebExtension/content.js index ee925724..53e6c599 100644 --- a/build/UserALEWebExtension/content.js +++ b/build/UserALEWebExtension/content.js @@ -1100,7 +1100,6 @@ function options(newConfig) { // browser is defined in firefox, but chrome uses the 'chrome' global. var browser = browser || chrome; function rerouteLog(log) { - console.log(log); browser.runtime.sendMessage({ type: ADD_LOG, payload: log diff --git a/build/UserALEWebExtension/options.js b/build/UserALEWebExtension/options.js index 813a934a..4add4cde 100644 --- a/build/UserALEWebExtension/options.js +++ b/build/UserALEWebExtension/options.js @@ -17,6 +17,7 @@ var prefix = 'USERALE_'; var CONFIG_CHANGE = prefix + 'CONFIG_CHANGE'; +var AUTH_CHANGE = prefix + 'AUTH_CHANGE'; var ADD_LOG = prefix + 'ADD_LOG'; var version = "2.4.0"; @@ -1100,7 +1101,6 @@ function options(newConfig) { // browser is defined in firefox, but chrome uses the 'chrome' global. var browser = browser || chrome; function rerouteLog(log) { - console.log(log); browser.runtime.sendMessage({ type: ADD_LOG, payload: log @@ -1131,16 +1131,24 @@ addCallbacks({ reroute: rerouteLog }); function setConfig(e) { + var user = document.getElementById("user").value; + var password = document.getElementById("password").value; browser.storage.local.set({ useraleConfig: { url: document.getElementById("url").value, - userId: document.getElementById("user").value, + userId: user, toolName: document.getElementById("tool").value, version: document.getElementById("version").value } }, function () { getConfig(); }); + if (user && password) { + browser.runtime.sendMessage({ + type: AUTH_CHANGE, + payload: "Basic " + btoa("".concat(user, ":").concat(password)) + }); + } } function getConfig() { browser.storage.local.get("useraleConfig", function (res) { diff --git a/build/UserALEWebExtension/optionsPage.html b/build/UserALEWebExtension/optionsPage.html index 6a49db38..ff92cf09 100644 --- a/build/UserALEWebExtension/optionsPage.html +++ b/build/UserALEWebExtension/optionsPage.html @@ -25,18 +25,18 @@

Options

- +
- - - -

+ + +
+
diff --git a/src/UserALEWebExtension/background.js b/src/UserALEWebExtension/background.js index d8aed77b..382244ed 100644 --- a/src/UserALEWebExtension/background.js +++ b/src/UserALEWebExtension/background.js @@ -45,14 +45,18 @@ function dispatchTabMessage(message) { browser.runtime.onMessage.addListener(function (message) { switch (message.type) { + // Handles logs rerouted from content and option scripts + case MessageTypes.ADD_LOG: + userale.log(message.payload); + break; + case MessageTypes.CONFIG_CHANGE: userale.options(message.payload) dispatchTabMessage(message); break; - // Handles logs rerouted from content and option scripts - case MessageTypes.ADD_LOG: - userale.log(message.payload); + case MessageTypes.AUTH_CHANGE: + userale.options({authHeader: message.payload}); break; default: diff --git a/src/UserALEWebExtension/messageTypes.js b/src/UserALEWebExtension/messageTypes.js index 8eaedbc2..7f49c53a 100644 --- a/src/UserALEWebExtension/messageTypes.js +++ b/src/UserALEWebExtension/messageTypes.js @@ -18,4 +18,5 @@ var prefix = 'USERALE_'; export var CONFIG_CHANGE = prefix + 'CONFIG_CHANGE'; +export var AUTH_CHANGE = prefix + 'AUTH_CHANGE'; export var ADD_LOG = prefix + 'ADD_LOG'; diff --git a/src/UserALEWebExtension/options.js b/src/UserALEWebExtension/options.js index dbb06ead..84499595 100644 --- a/src/UserALEWebExtension/options.js +++ b/src/UserALEWebExtension/options.js @@ -23,15 +23,24 @@ import { rerouteLog, browser } from './globals.js'; userale.addCallbacks({reroute: rerouteLog}); function setConfig(e) { + let user = document.getElementById("user").value; + let password = document.getElementById("password").value; + browser.storage.local.set( {useraleConfig: { url: document.getElementById("url").value, - userId: document.getElementById("user").value, + userId: user, toolName: document.getElementById("tool").value, version: document.getElementById("version").value }}, () => {getConfig()} ); + + if(user && password) { + browser.runtime.sendMessage({type: MessageTypes.AUTH_CHANGE, + payload: "Basic " + btoa(`${user}:${password}`) + }); + } } function getConfig() { diff --git a/src/UserALEWebExtension/optionsPage.html b/src/UserALEWebExtension/optionsPage.html index 6a49db38..ff92cf09 100644 --- a/src/UserALEWebExtension/optionsPage.html +++ b/src/UserALEWebExtension/optionsPage.html @@ -25,18 +25,18 @@

Options

- +
- - - -

+ + +
+
From 923be5400f84d18f58a08f3e1722f9738f4994ca Mon Sep 17 00:00:00 2001 From: Jason Young Date: Mon, 5 Feb 2024 16:36:32 -0500 Subject: [PATCH 2/5] add password to main script and persist in ext storage --- README.md | 2 ++ build/UserALEWebExtension/background.js | 12 ++++++------ build/UserALEWebExtension/content.js | 6 ++++++ build/UserALEWebExtension/options.js | 19 +++++++++---------- build/userale-2.4.0.js | 4 ++++ build/userale-2.4.0.min.js | 2 +- src/UserALEWebExtension/background.js | 6 +----- src/UserALEWebExtension/messageTypes.js | 7 +++---- src/UserALEWebExtension/options.js | 13 +++---------- src/getInitialSettings.js | 1 + src/sendLogs.js | 6 ++++++ test/main_spec.js | 1 + 12 files changed, 43 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index ae4e83ee..6d2abc12 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ The complete list of configurable parameters that can be configured via `userale | transmitInterval | Delay between transmit checks | 5000 (ms) | | logCountThreshold | Minimum number of logs to send | 5 | | userId | User identifier | null | +| password | Used with userId for basic authentication auth header, overwritten by authHeader | null | | sessionID | Session identifier | null | | version | Application version identifier | null | | logDetails | Toggle detailed logs (keys pressed and input/change values) | false | @@ -161,6 +162,7 @@ You have access to the same parameters listed above, however, naming conventions | data-interval | Delay between transmit checks | 5000 (ms) | | data-threshold | Minimum number of logs to send | 5 | | data-user | User identifier | null | +| data-password | Used with user for basic authentication auth header, overwritten by auth | null | | data-version | Application version identifier | null | | data-log-details | Toggle detailed logs (keys pressed and input/change values) | false | | data-resolution | Delay between instances of high frequency logs (mouseover, scroll, etc.) | 500 (ms) | diff --git a/build/UserALEWebExtension/background.js b/build/UserALEWebExtension/background.js index 8b470959..874f6074 100644 --- a/build/UserALEWebExtension/background.js +++ b/build/UserALEWebExtension/background.js @@ -17,7 +17,6 @@ var prefix = 'USERALE_'; var CONFIG_CHANGE = prefix + 'CONFIG_CHANGE'; -var AUTH_CHANGE = prefix + 'AUTH_CHANGE'; var ADD_LOG = prefix + 'ADD_LOG'; function _typeof(o) { @@ -73,6 +72,7 @@ function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; + settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -987,6 +987,11 @@ function sendLogs(logs, config, retries) { var req = new XMLHttpRequest(); var data = JSON.stringify(logs); req.open("POST", config.url); + + // Update headers + if (config.userId && config.password) { + req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); + } if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); } @@ -1153,11 +1158,6 @@ browser.runtime.onMessage.addListener(function (message) { options(message.payload); dispatchTabMessage(message); break; - case AUTH_CHANGE: - options({ - authHeader: message.payload - }); - break; default: console.log('got unknown message type ', message); } diff --git a/build/UserALEWebExtension/content.js b/build/UserALEWebExtension/content.js index 53e6c599..c79f5712 100644 --- a/build/UserALEWebExtension/content.js +++ b/build/UserALEWebExtension/content.js @@ -62,6 +62,7 @@ function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; + settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -1000,6 +1001,11 @@ function sendLogs(logs, config, retries) { var req = new XMLHttpRequest(); var data = JSON.stringify(logs); req.open("POST", config.url); + + // Update headers + if (config.userId && config.password) { + req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); + } if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); } diff --git a/build/UserALEWebExtension/options.js b/build/UserALEWebExtension/options.js index 4add4cde..5dc1f330 100644 --- a/build/UserALEWebExtension/options.js +++ b/build/UserALEWebExtension/options.js @@ -17,7 +17,6 @@ var prefix = 'USERALE_'; var CONFIG_CHANGE = prefix + 'CONFIG_CHANGE'; -var AUTH_CHANGE = prefix + 'AUTH_CHANGE'; var ADD_LOG = prefix + 'ADD_LOG'; var version = "2.4.0"; @@ -63,6 +62,7 @@ function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; + settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -1001,6 +1001,11 @@ function sendLogs(logs, config, retries) { var req = new XMLHttpRequest(); var data = JSON.stringify(logs); req.open("POST", config.url); + + // Update headers + if (config.userId && config.password) { + req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); + } if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); } @@ -1131,30 +1136,24 @@ addCallbacks({ reroute: rerouteLog }); function setConfig(e) { - var user = document.getElementById("user").value; - var password = document.getElementById("password").value; browser.storage.local.set({ useraleConfig: { url: document.getElementById("url").value, - userId: user, + userId: document.getElementById("user").value, + password: document.getElementById("password").value, toolName: document.getElementById("tool").value, version: document.getElementById("version").value } }, function () { getConfig(); }); - if (user && password) { - browser.runtime.sendMessage({ - type: AUTH_CHANGE, - payload: "Basic " + btoa("".concat(user, ":").concat(password)) - }); - } } function getConfig() { browser.storage.local.get("useraleConfig", function (res) { var config = res.useraleConfig; document.getElementById("url").value = config.url; document.getElementById("user").value = config.userId; + document.getElementById("password").value = config.password; document.getElementById("tool").value = config.toolName; document.getElementById("version").value = config.version; options(config); diff --git a/build/userale-2.4.0.js b/build/userale-2.4.0.js index c9a78243..c8b8a303 100644 --- a/build/userale-2.4.0.js +++ b/build/userale-2.4.0.js @@ -75,6 +75,7 @@ settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; + settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -1162,6 +1163,9 @@ req.open("POST", config.url); // Update headers + if (config.userId && config.password) { + req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); + } updateAuthHeader(config); if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); diff --git a/build/userale-2.4.0.min.js b/build/userale-2.4.0.min.js index e87a122b..a0a98a82 100644 --- a/build/userale-2.4.0.min.js +++ b/build/userale-2.4.0.min.js @@ -15,4 +15,4 @@ * limitations under the License. * @preserved */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).userale={})}(this,(function(e){"use strict";function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t(e)}var n="2.4.0",r=null;function o(e,t){var n=e.autostart,r=t.autostart;Object.keys(t).forEach((function(n){if("userFromParams"===n){var r=(o=t[n],i=new RegExp("[?&]"+o+"(=([^&#]*)|&|#|$)"),(a=window.location.href.match(i))&&a[2]?decodeURIComponent(a[2].replace(/\+/g," ")):null);r&&(e.userId=r)}var o,i,a;e[n]=t[n]})),!1!==n&&!1!==r||(e.autostart=!1)}var i=function(e,t,n){if(n||2===arguments.length)for(var r,o=0,i=t.length;o0?v.time(e.timeStamp):Date.now(),{milli:Math.floor(r),micro:Number((r%1).toFixed(3))}),i={target:M(e.target),path:B(e),pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),clientTime:o.milli,microTime:o.micro,location:C(e),scrnRes:D(),type:e.type,logType:"raw",userAction:!0,details:n,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID},a=0,l=Object.values(x);a0?v.time(e.timeStamp):Date.now());if(null==y&&(y=t,b=r,S=n,O=o,k=0),y!==t||b!==r){E={target:y,path:S,pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),count:k,duration:o-O,startTime:O,endTime:o,type:b,logType:"interval",targetChange:y!==t,typeChange:b!==r,userAction:!1,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID};for(var i=0,a=Object.values(x);ie.length)&&(t=e.length);for(var n=0,r=new Array(t);n=t.logCountThreshold&&(F(e.slice(0),t,0),e.splice(0))}),t.transmitInterval)}(e,t),function(e,t){window.addEventListener("pagehide",(function(){t.on&&e.length>0&&(navigator.sendBeacon(t.url,JSON.stringify(e)),e.splice(0))}))}(e,t)}function F(e,t,n){var r=new XMLHttpRequest,o=JSON.stringify(e);r.open("POST",t.url),function(e){if(H)try{e.authHeader=H()}catch(e){console.error("Error encountered while setting the auth header: ".concat(e))}}(t),t.authHeader&&r.setRequestHeader("Authorization",t.authHeader),r.setRequestHeader("Content-type","application/json;charset=UTF-8"),t.headers&&Object.entries(t.headers).forEach((function(e){var t=_(e,2),n=t[0],o=t[1];r.setRequestHeader(n,o)})),r.onreadystatechange=function(){4===r.readyState&&200!==r.status&&n>0&&F(e,t,n--)},r.send(o)}var Y,J={},q=[],G=Date.now();window.onload=function(){Y=Date.now()},e.started=!1,J.on=!1,J.useraleVersion=n,o(J,function(){var e={};null===r&&(r=function(e,t){if(null===window.sessionStorage.getItem(e))return window.sessionStorage.setItem(e,JSON.stringify(t)),t;return JSON.parse(window.sessionStorage.getItem(e))}("userAleSessionId","session_"+String(Date.now())));var t,n=document.currentScript||(t=document.getElementsByTagName("script"))[t.length-1],o=n?n.getAttribute.bind(n):function(){return null};return e.autostart="false"!==o("data-autostart"),e.url=o("data-url")||"http://localhost:8000",e.transmitInterval=+o("data-interval")||5e3,e.logCountThreshold=+o("data-threshold")||5,e.userId=o("data-user")||null,e.version=o("data-version")||null,e.logDetails="true"===o("data-log-details"),e.resolution=+o("data-resolution")||500,e.toolName=o("data-tool")||null,e.userFromParams=o("data-user-from-params")||null,e.time=function(e){var t;if(e.timeStamp&&e.timeStamp>0){var n=Date.now()-e.timeStamp;if(n<0)t=function(){return e.timeStamp/1e3};else if(n>e.timeStamp){var r=performance.timing.navigationStart;t=function(e){return e+r}}else t=function(e){return e}}else t=function(){return Date.now()};return t}(document.createEvent("CustomEvent")),e.sessionID=o("data-session")||r,e.authHeader=o("data-auth")||null,e.custIndex=o("data-index")||null,e.headers=o("data-headers")||null,e}()),g=q,v=J,x=[],y=null,b=null,S=null,O=null,k=0,E=null,J.autostart&&function t(n){e.started||setTimeout((function(){var r=document.readyState;!n.autostart||"interactive"!==r&&"complete"!==r?t(n):($(n),z(q,n),e.started=n.on=!0,j({type:"load",details:{pageLoadTime:Y-G}},(function(){}),!1))}),100)}(J);var Q=n;e.addCallbacks=function(){for(var e=arguments.length,t=new Array(e),n=0;n0?v.time(e.timeStamp):Date.now(),{milli:Math.floor(r),micro:Number((r%1).toFixed(3))}),i={target:M(e.target),path:B(e),pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),clientTime:o.milli,microTime:o.micro,location:C(e),scrnRes:D(),type:e.type,logType:"raw",userAction:!0,details:n,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID},a=0,s=Object.values(x);a0?v.time(e.timeStamp):Date.now());if(null==y&&(y=t,b=r,S=n,O=o,k=0),y!==t||b!==r){E={target:y,path:S,pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),count:k,duration:o-O,startTime:O,endTime:o,type:b,logType:"interval",targetChange:y!==t,typeChange:b!==r,userAction:!1,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID};for(var i=0,a=Object.values(x);ie.length)&&(t=e.length);for(var n=0,r=new Array(t);n=t.logCountThreshold&&(F(e.slice(0),t,0),e.splice(0))}),t.transmitInterval)}(e,t),function(e,t){window.addEventListener("pagehide",(function(){t.on&&e.length>0&&(navigator.sendBeacon(t.url,JSON.stringify(e)),e.splice(0))}))}(e,t)}function F(e,t,n){var r=new XMLHttpRequest,o=JSON.stringify(e);r.open("POST",t.url),t.userId&&t.password&&r.setRequestHeader("Authorization","Basic "+btoa("".concat(t.userId,":").concat(t.password))),function(e){if(H)try{e.authHeader=H()}catch(e){console.error("Error encountered while setting the auth header: ".concat(e))}}(t),t.authHeader&&r.setRequestHeader("Authorization",t.authHeader),r.setRequestHeader("Content-type","application/json;charset=UTF-8"),t.headers&&Object.entries(t.headers).forEach((function(e){var t=_(e,2),n=t[0],o=t[1];r.setRequestHeader(n,o)})),r.onreadystatechange=function(){4===r.readyState&&200!==r.status&&n>0&&F(e,t,n--)},r.send(o)}var Y,J={},q=[],G=Date.now();window.onload=function(){Y=Date.now()},e.started=!1,J.on=!1,J.useraleVersion=n,o(J,function(){var e={};null===r&&(r=function(e,t){if(null===window.sessionStorage.getItem(e))return window.sessionStorage.setItem(e,JSON.stringify(t)),t;return JSON.parse(window.sessionStorage.getItem(e))}("userAleSessionId","session_"+String(Date.now())));var t,n=document.currentScript||(t=document.getElementsByTagName("script"))[t.length-1],o=n?n.getAttribute.bind(n):function(){return null};return e.autostart="false"!==o("data-autostart"),e.url=o("data-url")||"http://localhost:8000",e.transmitInterval=+o("data-interval")||5e3,e.logCountThreshold=+o("data-threshold")||5,e.userId=o("data-user")||null,e.password=o("data-password")||null,e.version=o("data-version")||null,e.logDetails="true"===o("data-log-details"),e.resolution=+o("data-resolution")||500,e.toolName=o("data-tool")||null,e.userFromParams=o("data-user-from-params")||null,e.time=function(e){var t;if(e.timeStamp&&e.timeStamp>0){var n=Date.now()-e.timeStamp;if(n<0)t=function(){return e.timeStamp/1e3};else if(n>e.timeStamp){var r=performance.timing.navigationStart;t=function(e){return e+r}}else t=function(e){return e}}else t=function(){return Date.now()};return t}(document.createEvent("CustomEvent")),e.sessionID=o("data-session")||r,e.authHeader=o("data-auth")||null,e.custIndex=o("data-index")||null,e.headers=o("data-headers")||null,e}()),g=q,v=J,x=[],y=null,b=null,S=null,O=null,k=0,E=null,J.autostart&&function t(n){e.started||setTimeout((function(){var r=document.readyState;!n.autostart||"interactive"!==r&&"complete"!==r?t(n):($(n),U(q,n),e.started=n.on=!0,j({type:"load",details:{pageLoadTime:Y-G}},(function(){}),!1))}),100)}(J);var Q=n;e.addCallbacks=function(){for(var e=arguments.length,t=new Array(e),n=0;n {getConfig()} ); - - if(user && password) { - browser.runtime.sendMessage({type: MessageTypes.AUTH_CHANGE, - payload: "Basic " + btoa(`${user}:${password}`) - }); - } } function getConfig() { @@ -49,6 +41,7 @@ function getConfig() { document.getElementById("url").value = config.url; document.getElementById("user").value = config.userId; + document.getElementById("password").value = config.password; document.getElementById("tool").value = config.toolName; document.getElementById("version").value = config.version; diff --git a/src/getInitialSettings.js b/src/getInitialSettings.js index b9624ebe..e3dd41b8 100644 --- a/src/getInitialSettings.js +++ b/src/getInitialSettings.js @@ -42,6 +42,7 @@ export function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; + settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; diff --git a/src/sendLogs.js b/src/sendLogs.js index 5985644d..1d2ed83d 100644 --- a/src/sendLogs.js +++ b/src/sendLogs.js @@ -89,6 +89,12 @@ export function sendLogs(logs, config, retries) { req.open("POST", config.url); // Update headers + if( config.userId && config.password) { + req.setRequestHeader( + "Authorization", "Basic " + btoa(`${config.userId}:${config.password}`) + ); + } + updateAuthHeader(config); if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); diff --git a/test/main_spec.js b/test/main_spec.js index 5bc045ab..b787fa13 100644 --- a/test/main_spec.js +++ b/test/main_spec.js @@ -31,6 +31,7 @@ describe('Userale API', () => { 'transmitInterval', 'logCountThreshold', 'userId', + 'password', 'sessionID', 'version', 'logDetails', From 3ee604a0b309096df29e0ec3946cb3cf227cf305 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Tue, 6 Feb 2024 14:46:04 -0500 Subject: [PATCH 3/5] Remove password from main script --- README.md | 2 -- build/UserALEWebExtension/background.js | 6 ------ build/UserALEWebExtension/content.js | 6 ------ build/UserALEWebExtension/options.js | 6 ------ build/userale-2.4.0.js | 4 ---- build/userale-2.4.0.min.js | 2 +- src/getInitialSettings.js | 1 - src/sendLogs.js | 6 ------ test/main_spec.js | 1 - 9 files changed, 1 insertion(+), 33 deletions(-) diff --git a/README.md b/README.md index 6d2abc12..ae4e83ee 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,6 @@ The complete list of configurable parameters that can be configured via `userale | transmitInterval | Delay between transmit checks | 5000 (ms) | | logCountThreshold | Minimum number of logs to send | 5 | | userId | User identifier | null | -| password | Used with userId for basic authentication auth header, overwritten by authHeader | null | | sessionID | Session identifier | null | | version | Application version identifier | null | | logDetails | Toggle detailed logs (keys pressed and input/change values) | false | @@ -162,7 +161,6 @@ You have access to the same parameters listed above, however, naming conventions | data-interval | Delay between transmit checks | 5000 (ms) | | data-threshold | Minimum number of logs to send | 5 | | data-user | User identifier | null | -| data-password | Used with user for basic authentication auth header, overwritten by auth | null | | data-version | Application version identifier | null | | data-log-details | Toggle detailed logs (keys pressed and input/change values) | false | | data-resolution | Delay between instances of high frequency logs (mouseover, scroll, etc.) | 500 (ms) | diff --git a/build/UserALEWebExtension/background.js b/build/UserALEWebExtension/background.js index 874f6074..f844a934 100644 --- a/build/UserALEWebExtension/background.js +++ b/build/UserALEWebExtension/background.js @@ -72,7 +72,6 @@ function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; - settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -987,11 +986,6 @@ function sendLogs(logs, config, retries) { var req = new XMLHttpRequest(); var data = JSON.stringify(logs); req.open("POST", config.url); - - // Update headers - if (config.userId && config.password) { - req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); - } if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); } diff --git a/build/UserALEWebExtension/content.js b/build/UserALEWebExtension/content.js index c79f5712..53e6c599 100644 --- a/build/UserALEWebExtension/content.js +++ b/build/UserALEWebExtension/content.js @@ -62,7 +62,6 @@ function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; - settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -1001,11 +1000,6 @@ function sendLogs(logs, config, retries) { var req = new XMLHttpRequest(); var data = JSON.stringify(logs); req.open("POST", config.url); - - // Update headers - if (config.userId && config.password) { - req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); - } if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); } diff --git a/build/UserALEWebExtension/options.js b/build/UserALEWebExtension/options.js index 5dc1f330..a075371b 100644 --- a/build/UserALEWebExtension/options.js +++ b/build/UserALEWebExtension/options.js @@ -62,7 +62,6 @@ function getInitialSettings() { settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; - settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -1001,11 +1000,6 @@ function sendLogs(logs, config, retries) { var req = new XMLHttpRequest(); var data = JSON.stringify(logs); req.open("POST", config.url); - - // Update headers - if (config.userId && config.password) { - req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); - } if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); } diff --git a/build/userale-2.4.0.js b/build/userale-2.4.0.js index c8b8a303..c9a78243 100644 --- a/build/userale-2.4.0.js +++ b/build/userale-2.4.0.js @@ -75,7 +75,6 @@ settings.transmitInterval = +get('data-interval') || 5000; settings.logCountThreshold = +get('data-threshold') || 5; settings.userId = get('data-user') || null; - settings.password = get('data-password') || null; settings.version = get('data-version') || null; settings.logDetails = get('data-log-details') === 'true' ? true : false; settings.resolution = +get('data-resolution') || 500; @@ -1163,9 +1162,6 @@ req.open("POST", config.url); // Update headers - if (config.userId && config.password) { - req.setRequestHeader("Authorization", "Basic " + btoa("".concat(config.userId, ":").concat(config.password))); - } updateAuthHeader(config); if (config.authHeader) { req.setRequestHeader("Authorization", config.authHeader); diff --git a/build/userale-2.4.0.min.js b/build/userale-2.4.0.min.js index a0a98a82..e87a122b 100644 --- a/build/userale-2.4.0.min.js +++ b/build/userale-2.4.0.min.js @@ -15,4 +15,4 @@ * limitations under the License. * @preserved */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).userale={})}(this,(function(e){"use strict";function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t(e)}var n="2.4.0",r=null;function o(e,t){var n=e.autostart,r=t.autostart;Object.keys(t).forEach((function(n){if("userFromParams"===n){var r=(o=t[n],i=new RegExp("[?&]"+o+"(=([^&#]*)|&|#|$)"),(a=window.location.href.match(i))&&a[2]?decodeURIComponent(a[2].replace(/\+/g," ")):null);r&&(e.userId=r)}var o,i,a;e[n]=t[n]})),!1!==n&&!1!==r||(e.autostart=!1)}var i=function(e,t,n){if(n||2===arguments.length)for(var r,o=0,i=t.length;o0?v.time(e.timeStamp):Date.now(),{milli:Math.floor(r),micro:Number((r%1).toFixed(3))}),i={target:M(e.target),path:B(e),pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),clientTime:o.milli,microTime:o.micro,location:C(e),scrnRes:D(),type:e.type,logType:"raw",userAction:!0,details:n,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID},a=0,s=Object.values(x);a0?v.time(e.timeStamp):Date.now());if(null==y&&(y=t,b=r,S=n,O=o,k=0),y!==t||b!==r){E={target:y,path:S,pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),count:k,duration:o-O,startTime:O,endTime:o,type:b,logType:"interval",targetChange:y!==t,typeChange:b!==r,userAction:!1,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID};for(var i=0,a=Object.values(x);ie.length)&&(t=e.length);for(var n=0,r=new Array(t);n=t.logCountThreshold&&(F(e.slice(0),t,0),e.splice(0))}),t.transmitInterval)}(e,t),function(e,t){window.addEventListener("pagehide",(function(){t.on&&e.length>0&&(navigator.sendBeacon(t.url,JSON.stringify(e)),e.splice(0))}))}(e,t)}function F(e,t,n){var r=new XMLHttpRequest,o=JSON.stringify(e);r.open("POST",t.url),t.userId&&t.password&&r.setRequestHeader("Authorization","Basic "+btoa("".concat(t.userId,":").concat(t.password))),function(e){if(H)try{e.authHeader=H()}catch(e){console.error("Error encountered while setting the auth header: ".concat(e))}}(t),t.authHeader&&r.setRequestHeader("Authorization",t.authHeader),r.setRequestHeader("Content-type","application/json;charset=UTF-8"),t.headers&&Object.entries(t.headers).forEach((function(e){var t=_(e,2),n=t[0],o=t[1];r.setRequestHeader(n,o)})),r.onreadystatechange=function(){4===r.readyState&&200!==r.status&&n>0&&F(e,t,n--)},r.send(o)}var Y,J={},q=[],G=Date.now();window.onload=function(){Y=Date.now()},e.started=!1,J.on=!1,J.useraleVersion=n,o(J,function(){var e={};null===r&&(r=function(e,t){if(null===window.sessionStorage.getItem(e))return window.sessionStorage.setItem(e,JSON.stringify(t)),t;return JSON.parse(window.sessionStorage.getItem(e))}("userAleSessionId","session_"+String(Date.now())));var t,n=document.currentScript||(t=document.getElementsByTagName("script"))[t.length-1],o=n?n.getAttribute.bind(n):function(){return null};return e.autostart="false"!==o("data-autostart"),e.url=o("data-url")||"http://localhost:8000",e.transmitInterval=+o("data-interval")||5e3,e.logCountThreshold=+o("data-threshold")||5,e.userId=o("data-user")||null,e.password=o("data-password")||null,e.version=o("data-version")||null,e.logDetails="true"===o("data-log-details"),e.resolution=+o("data-resolution")||500,e.toolName=o("data-tool")||null,e.userFromParams=o("data-user-from-params")||null,e.time=function(e){var t;if(e.timeStamp&&e.timeStamp>0){var n=Date.now()-e.timeStamp;if(n<0)t=function(){return e.timeStamp/1e3};else if(n>e.timeStamp){var r=performance.timing.navigationStart;t=function(e){return e+r}}else t=function(e){return e}}else t=function(){return Date.now()};return t}(document.createEvent("CustomEvent")),e.sessionID=o("data-session")||r,e.authHeader=o("data-auth")||null,e.custIndex=o("data-index")||null,e.headers=o("data-headers")||null,e}()),g=q,v=J,x=[],y=null,b=null,S=null,O=null,k=0,E=null,J.autostart&&function t(n){e.started||setTimeout((function(){var r=document.readyState;!n.autostart||"interactive"!==r&&"complete"!==r?t(n):($(n),U(q,n),e.started=n.on=!0,j({type:"load",details:{pageLoadTime:Y-G}},(function(){}),!1))}),100)}(J);var Q=n;e.addCallbacks=function(){for(var e=arguments.length,t=new Array(e),n=0;n0?v.time(e.timeStamp):Date.now(),{milli:Math.floor(r),micro:Number((r%1).toFixed(3))}),i={target:M(e.target),path:B(e),pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),clientTime:o.milli,microTime:o.micro,location:C(e),scrnRes:D(),type:e.type,logType:"raw",userAction:!0,details:n,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID},a=0,l=Object.values(x);a0?v.time(e.timeStamp):Date.now());if(null==y&&(y=t,b=r,S=n,O=o,k=0),y!==t||b!==r){E={target:y,path:S,pageUrl:window.location.href,pageTitle:document.title,pageReferrer:document.referrer,browser:P(),count:k,duration:o-O,startTime:O,endTime:o,type:b,logType:"interval",targetChange:y!==t,typeChange:b!==r,userAction:!1,userId:v.userId,toolVersion:v.version,toolName:v.toolName,useraleVersion:v.useraleVersion,sessionID:v.sessionID};for(var i=0,a=Object.values(x);ie.length)&&(t=e.length);for(var n=0,r=new Array(t);n=t.logCountThreshold&&(F(e.slice(0),t,0),e.splice(0))}),t.transmitInterval)}(e,t),function(e,t){window.addEventListener("pagehide",(function(){t.on&&e.length>0&&(navigator.sendBeacon(t.url,JSON.stringify(e)),e.splice(0))}))}(e,t)}function F(e,t,n){var r=new XMLHttpRequest,o=JSON.stringify(e);r.open("POST",t.url),function(e){if(H)try{e.authHeader=H()}catch(e){console.error("Error encountered while setting the auth header: ".concat(e))}}(t),t.authHeader&&r.setRequestHeader("Authorization",t.authHeader),r.setRequestHeader("Content-type","application/json;charset=UTF-8"),t.headers&&Object.entries(t.headers).forEach((function(e){var t=_(e,2),n=t[0],o=t[1];r.setRequestHeader(n,o)})),r.onreadystatechange=function(){4===r.readyState&&200!==r.status&&n>0&&F(e,t,n--)},r.send(o)}var Y,J={},q=[],G=Date.now();window.onload=function(){Y=Date.now()},e.started=!1,J.on=!1,J.useraleVersion=n,o(J,function(){var e={};null===r&&(r=function(e,t){if(null===window.sessionStorage.getItem(e))return window.sessionStorage.setItem(e,JSON.stringify(t)),t;return JSON.parse(window.sessionStorage.getItem(e))}("userAleSessionId","session_"+String(Date.now())));var t,n=document.currentScript||(t=document.getElementsByTagName("script"))[t.length-1],o=n?n.getAttribute.bind(n):function(){return null};return e.autostart="false"!==o("data-autostart"),e.url=o("data-url")||"http://localhost:8000",e.transmitInterval=+o("data-interval")||5e3,e.logCountThreshold=+o("data-threshold")||5,e.userId=o("data-user")||null,e.version=o("data-version")||null,e.logDetails="true"===o("data-log-details"),e.resolution=+o("data-resolution")||500,e.toolName=o("data-tool")||null,e.userFromParams=o("data-user-from-params")||null,e.time=function(e){var t;if(e.timeStamp&&e.timeStamp>0){var n=Date.now()-e.timeStamp;if(n<0)t=function(){return e.timeStamp/1e3};else if(n>e.timeStamp){var r=performance.timing.navigationStart;t=function(e){return e+r}}else t=function(e){return e}}else t=function(){return Date.now()};return t}(document.createEvent("CustomEvent")),e.sessionID=o("data-session")||r,e.authHeader=o("data-auth")||null,e.custIndex=o("data-index")||null,e.headers=o("data-headers")||null,e}()),g=q,v=J,x=[],y=null,b=null,S=null,O=null,k=0,E=null,J.autostart&&function t(n){e.started||setTimeout((function(){var r=document.readyState;!n.autostart||"interactive"!==r&&"complete"!==r?t(n):($(n),z(q,n),e.started=n.on=!0,j({type:"load",details:{pageLoadTime:Y-G}},(function(){}),!1))}),100)}(J);var Q=n;e.addCallbacks=function(){for(var e=arguments.length,t=new Array(e),n=0;n { 'transmitInterval', 'logCountThreshold', 'userId', - 'password', 'sessionID', 'version', 'logDetails', From d2bc4adf254b83c9e4925f4fc82bba22f6ab4dd3 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Tue, 6 Feb 2024 17:47:45 -0500 Subject: [PATCH 4/5] Set auth header with password --- build/UserALEWebExtension/background.js | 1 + build/UserALEWebExtension/options.js | 37 +++++++++++++---------- src/UserALEWebExtension/background.js | 1 + src/UserALEWebExtension/options.js | 40 ++++++++++++++----------- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/build/UserALEWebExtension/background.js b/build/UserALEWebExtension/background.js index f844a934..d9372d05 100644 --- a/build/UserALEWebExtension/background.js +++ b/build/UserALEWebExtension/background.js @@ -1149,6 +1149,7 @@ browser.runtime.onMessage.addListener(function (message) { log(message.payload); break; case CONFIG_CHANGE: + console.log(message); options(message.payload); dispatchTabMessage(message); break; diff --git a/build/UserALEWebExtension/options.js b/build/UserALEWebExtension/options.js index a075371b..acd305a0 100644 --- a/build/UserALEWebExtension/options.js +++ b/build/UserALEWebExtension/options.js @@ -1129,35 +1129,40 @@ function rerouteLog(log) { addCallbacks({ reroute: rerouteLog }); -function setConfig(e) { +function setConfig() { + var config = { + url: document.getElementById("url").value, + userId: document.getElementById("user").value, + toolName: document.getElementById("tool").value, + version: document.getElementById("version").value + }; + + // Set a basic auth header if given credentials. + var password = document.getElementById("password").value; + if (config.userId && password) { + config.authHeader = "Basic " + btoa("".concat(config.userId, ":").concat(password)); + } browser.storage.local.set({ - useraleConfig: { - url: document.getElementById("url").value, - userId: document.getElementById("user").value, - password: document.getElementById("password").value, - toolName: document.getElementById("tool").value, - version: document.getElementById("version").value - } + useraleConfig: config }, function () { - getConfig(); + options(config); + browser.runtime.sendMessage({ + type: CONFIG_CHANGE, + payload: config + }); }); } function getConfig() { browser.storage.local.get("useraleConfig", function (res) { var config = res.useraleConfig; + options(config); document.getElementById("url").value = config.url; document.getElementById("user").value = config.userId; - document.getElementById("password").value = config.password; document.getElementById("tool").value = config.toolName; document.getElementById("version").value = config.version; - options(config); - browser.runtime.sendMessage({ - type: CONFIG_CHANGE, - payload: config - }); }); } -document.addEventListener('DOMContentLoaded', getConfig); +document.addEventListener("DOMContentLoaded", getConfig); document.addEventListener("submit", setConfig); /* eslint-enable */ diff --git a/src/UserALEWebExtension/background.js b/src/UserALEWebExtension/background.js index 99f15231..5987938b 100644 --- a/src/UserALEWebExtension/background.js +++ b/src/UserALEWebExtension/background.js @@ -51,6 +51,7 @@ browser.runtime.onMessage.addListener(function (message) { break; case MessageTypes.CONFIG_CHANGE: + console.log(message); userale.options(message.payload); dispatchTabMessage(message); break; diff --git a/src/UserALEWebExtension/options.js b/src/UserALEWebExtension/options.js index 2207ed3a..b2ecbdb9 100644 --- a/src/UserALEWebExtension/options.js +++ b/src/UserALEWebExtension/options.js @@ -22,36 +22,42 @@ import { rerouteLog, browser } from './globals.js'; userale.addCallbacks({reroute: rerouteLog}); -function setConfig(e) { - browser.storage.local.set( - {useraleConfig: { - url: document.getElementById("url").value, - userId: document.getElementById("user").value, - password: document.getElementById("password").value, - toolName: document.getElementById("tool").value, - version: document.getElementById("version").value - }}, - () => {getConfig()} - ); +// TODO: Warn users when setting credentials with unsecured connection. +const mitmWarning = "Setting credentials with http will expose you to a MITM attack. Are you sure you want to continue?"; + +function setConfig() { + let config = { + url: document.getElementById("url").value, + userId: document.getElementById("user").value, + toolName: document.getElementById("tool").value, + version: document.getElementById("version").value + }; + + // Set a basic auth header if given credentials. + const password = document.getElementById("password").value; + if(config.userId && password) { + config.authHeader = "Basic " + btoa(`${config.userId}:${password}`); + } + + browser.storage.local.set({useraleConfig: config}, () => { + userale.options(config); + browser.runtime.sendMessage({ type: MessageTypes.CONFIG_CHANGE, payload: config }); + }); } function getConfig() { browser.storage.local.get("useraleConfig", (res) => { let config = res.useraleConfig; + userale.options(config); document.getElementById("url").value = config.url; document.getElementById("user").value = config.userId; - document.getElementById("password").value = config.password; document.getElementById("tool").value = config.toolName; document.getElementById("version").value = config.version; - - userale.options(config); - browser.runtime.sendMessage({ type: MessageTypes.CONFIG_CHANGE, payload: config }); - }); } -document.addEventListener('DOMContentLoaded', getConfig); +document.addEventListener("DOMContentLoaded", getConfig); document.addEventListener("submit", setConfig); /* eslint-enable */ \ No newline at end of file From 24a5ccd44c1dda10dc3b31af79655138b2b68b63 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Tue, 6 Feb 2024 18:39:08 -0500 Subject: [PATCH 5/5] Get auth header on ext boot --- build/UserALEWebExtension/background.js | 1 + src/UserALEWebExtension/background.js | 1 + 2 files changed, 2 insertions(+) diff --git a/build/UserALEWebExtension/background.js b/build/UserALEWebExtension/background.js index d9372d05..389f5a8d 100644 --- a/build/UserALEWebExtension/background.js +++ b/build/UserALEWebExtension/background.js @@ -1128,6 +1128,7 @@ var defaultConfig = { useraleConfig: { url: 'http://localhost:8000', userId: 'pluginUser', + authHeader: null, toolName: 'useralePlugin', version: version } diff --git a/src/UserALEWebExtension/background.js b/src/UserALEWebExtension/background.js index 5987938b..28a7ab11 100644 --- a/src/UserALEWebExtension/background.js +++ b/src/UserALEWebExtension/background.js @@ -27,6 +27,7 @@ import { browser } from './globals.js'; const defaultConfig = {useraleConfig: { url: 'http://localhost:8000', userId: 'pluginUser', + authHeader: null, toolName: 'useralePlugin', version: userale.version, }};