diff --git a/containerize.js b/containerize.js index 2c2eeba..bb3f3dd 100644 --- a/containerize.js +++ b/containerize.js @@ -28,6 +28,8 @@ const availableContainerColors = [ ] let containerNameTemplate = "name role"; +let containerNameLength = 0; +let containerNameSlug = ""; let accountMap = {}; @@ -55,104 +57,121 @@ async function prepareContainer({ name, color, icon }) { } } -function listener(details) { - - // Temporarily commenting out as users seem to not like this - // https://github.com/pyro2927/AWS_SSO_Containers/issues/6 - /* - if (details.cookieStoreId != "firefox-default") { - return {}; - }*/ +function containerNameFromParams(params) { + let name = containerNameTemplate; - // Intercept our response + for (const [key, value] of Object.entries(params)) { + name = name.replace(key, value); + } + if (containerNameSlug) { + name = name.replaceAll(containerNameSlug, ""); + } + if (containerNameLength && name.length > containerNameLength) { + name = name.substring(0, containerNameLength - 2) + "..."; + } + return name; +} - let filter = browser.webRequest.filterResponseData(details.requestId); +function listener(details) { + async function process(result) { + onGot(result); - const queryString = new URL(details.url).searchParams; - const originParams = new URLSearchParams(details.originUrl.split('?').slice(1).join('?')); + // Temporarily commenting out as users seem to not like this + // https://github.com/pyro2927/AWS_SSO_Containers/issues/6 + /* + if (details.cookieStoreId != "firefox-default") { + return {}; + }*/ - // Parse some params for container name - let accountRole = queryString.get("role_name"); - let accountNumber = queryString.get("account_id"); + // Intercept our response - // pull subdomain for folks that might have multiple SSO - // portals that have access to the same account and role names - const host = new URL(details.originUrl).host; - let subdomain = host.split(".")[0]; + let filter = browser.webRequest.filterResponseData(details.requestId); - let params = { - 'number': accountNumber, - 'role': accountRole, - 'subdomain': subdomain - }; - if(accountMap[accountNumber] !== undefined){ - params["name"] = accountMap[accountNumber]["name"]; - params["email"] = accountMap[accountNumber]["email"]; - } + const queryString = new URL(details.url).searchParams; + const originParams = new URLSearchParams(details.originUrl.split('?').slice(1).join('?')); - let name = containerNameTemplate; + // Parse some params for container name + let accountRole = queryString.get("role_name"); + let accountNumber = queryString.get("account_id"); - for (const [key, value] of Object.entries(params)) { - name = name.replace(key, value); - } - let originDestination = originParams.get("destination"); - let str = ''; - let decoder = new TextDecoder("utf-8"); - let encoder = new TextEncoder(); + // pull subdomain for folks that might have multiple SSO + // portals that have access to the same account and role names + const host = new URL(details.originUrl).host; + let subdomain = host.split(".")[0]; - filter.ondata = event => { - str += decoder.decode(event.data, { stream: true }); - }; + let params = { + 'number': accountNumber, + 'role': accountRole, + 'subdomain': subdomain + }; + if(accountMap[accountNumber] !== undefined){ + params["name"] = accountMap[accountNumber]["name"]; + params["email"] = accountMap[accountNumber]["email"]; + } - filter.onstop = async event => { + let name = containerNameFromParams(params); + let originDestination = originParams.get("destination"); + let str = ''; + let decoder = new TextDecoder("utf-8"); + let encoder = new TextEncoder(); - // The first OPTIONS request has no response body - if (str.length > 0) { - // signInToken - // signInFederationLocation - // destination - const object = JSON.parse(str); + filter.ondata = event => { + str += decoder.decode(event.data, { stream: true }); + }; - // If we have a sign-in token, hijack this into a container - if (object.signInToken) { - let destination = object.destination; - if (!originDestination) { - if (!object.destination) { - if (object.signInFederationLocation.includes("amazonaws-us-gov.com")) { - destination = "https://console.amazonaws-us-gov.com"; - } else { - destination = "https://console.aws.amazon.com"; + filter.onstop = async event => { + + // The first OPTIONS request has no response body + if (str.length > 0) { + // signInToken + // signInFederationLocation + // destination + const object = JSON.parse(str); + + // If we have a sign-in token, hijack this into a container + if (object.signInToken) { + let destination = object.destination; + if (!originDestination) { + if (!object.destination) { + if (object.signInFederationLocation.includes("amazonaws-us-gov.com")) { + destination = "https://console.amazonaws-us-gov.com"; + } else { + destination = "https://console.aws.amazon.com"; + } } } - } - else { - destination = originDestination; - } + else { + destination = originDestination; + } - // Generate our federation URI and open it in a container - const url = object.signInFederationLocation + "?Action=login&SigninToken=" + object.signInToken + "&Issuer=" + encodeURIComponent(details.originUrl) + "&Destination=" + encodeURIComponent(destination); + // Generate our federation URI and open it in a container + const url = object.signInFederationLocation + "?Action=login&SigninToken=" + object.signInToken + "&Issuer=" + encodeURIComponent(details.originUrl) + "&Destination=" + encodeURIComponent(destination); - const container = await prepareContainer({ name }); + const container = await prepareContainer({ name }); - // get index of tab we're about to remove, put ours at that spot - const tab = await browser.tabs.get(details.tabId); + // get index of tab we're about to remove, put ours at that spot + const tab = await browser.tabs.get(details.tabId); - const createTabParams = { - cookieStoreId: container.cookieStoreId, - url: url, - pinned: false, - index: tab.index, - }; + const createTabParams = { + cookieStoreId: container.cookieStoreId, + url: url, + pinned: false, + index: tab.index, + }; - await browser.tabs.create(createTabParams); + await browser.tabs.create(createTabParams); - await browser.tabs.remove(details.tabId); - } else { - filter.write(encoder.encode(str)); + await browser.tabs.remove(details.tabId); + } else { + filter.write(encoder.encode(str)); + } } - } - filter.close(); - }; + filter.close(); + }; + } + + let getting = browser.storage.sync.get(["template", "length", "slug"]); + getting.then(process); return {}; } @@ -187,114 +206,117 @@ function accountNameListener(details) { } filter.close(); } - + return {}; } async function samlListener(details) { - if (details.statusCode != 302) { - return {}; - } + async function process(result) { + onGot(result); - const setCookie = details.responseHeaders.find(header => header.name == "set-cookie"); - const redirectUrl = details.responseHeaders.find(header => header.name == "location").value; + if (details.statusCode != 302) { + return {}; + } - const cookies = setCookie.value.split('\n').map(fullCookie => fullCookie.split("; ").map(cookiePart => cookiePart.split('='))); + const setCookie = details.responseHeaders.find(header => header.name == "set-cookie"); + const redirectUrl = details.responseHeaders.find(header => header.name == "location").value; - const encodedUserInfo = cookies.find(cookie => cookie[0][0] == "aws-userInfo")[0][1]; - const userInfo = JSON.parse(decodeURIComponent(encodedUserInfo)); - const roleArn = userInfo.arn; - const splitArn = roleArn.split(':'); - const splitRole = splitArn[5].split('/'); + const cookies = setCookie.value.split('\n').map(fullCookie => fullCookie.split("; ").map(cookiePart => cookiePart.split('='))); - const name = userInfo.alias; - const number = splitArn[4]; - const role = splitRole[1]; - const email = splitRole[2]; - const subdomain = 'saml'; + const encodedUserInfo = cookies.find(cookie => cookie[0][0] == "aws-userInfo")[0][1]; + const userInfo = JSON.parse(decodeURIComponent(encodedUserInfo)); + const roleArn = userInfo.arn; + const splitArn = roleArn.split(':'); + const splitRole = splitArn[5].split('/'); - let params = { name, number, role, email, subdomain }; + const name = userInfo.alias; + const number = splitArn[4]; + const role = splitRole[1]; + const email = splitRole[2]; + const subdomain = 'saml'; - let containerName = containerNameTemplate; + let params = {name, number, role, email, subdomain}; - for (const [key, value] of Object.entries(params)) { - containerName = containerName.replace(key, value); - } + let containerName = containerNameFromParams(params); - const container = await prepareContainer({ name: containerName }); + const container = await prepareContainer({name: containerName}); - const cookieAttributeMapping = { - Path: 'path', - SameSite: 'sameSite', - Secure: 'secure', - Domain: 'domain', - Expires: 'expirationDate', - HttpOnly: 'httpOnly', - } + const cookieAttributeMapping = { + Path: 'path', + SameSite: 'sameSite', + Secure: 'secure', + Domain: 'domain', + Expires: 'expirationDate', + HttpOnly: 'httpOnly', + } - const sameSiteMapping = { - None: 'no_restriction', - Lax: 'lax', - Strict: 'strict', - } + const sameSiteMapping = { + None: 'no_restriction', + Lax: 'lax', + Strict: 'strict', + } - for (const cookie of cookies) { - for (const cookieAttribute of cookie.slice(1)) { - if (cookieAttribute[0] == 'SameSite') { - cookieAttribute[1] = sameSiteMapping[cookieAttribute[1]]; - } + for (const cookie of cookies) { + for (const cookieAttribute of cookie.slice(1)) { + if (cookieAttribute[0] == 'SameSite') { + cookieAttribute[1] = sameSiteMapping[cookieAttribute[1]]; + } - if (cookieAttribute[0] == 'Max-Age') { - cookieAttribute[0] = 'expirationDate'; - cookieAttribute[1] = Date.now() + parseInt(cookieAttribute[1]); - } + if (cookieAttribute[0] == 'Max-Age') { + cookieAttribute[0] = 'expirationDate'; + cookieAttribute[1] = Date.now() + parseInt(cookieAttribute[1]); + } - if (cookieAttribute[0] == 'Expires') { - cookieAttribute[0] = 'expirationDate'; - cookieAttribute[1] = Date.parse(cookieAttribute[1]); - } + if (cookieAttribute[0] == 'Expires') { + cookieAttribute[0] = 'expirationDate'; + cookieAttribute[1] = Date.parse(cookieAttribute[1]); + } - if (cookieAttribute.length == 1) { - cookieAttribute.push(true); - } + if (cookieAttribute.length == 1) { + cookieAttribute.push(true); + } - if (cookieAttributeMapping[cookieAttribute[0]]) { - cookieAttribute[0] = cookieAttributeMapping[cookieAttribute[0]]; + if (cookieAttributeMapping[cookieAttribute[0]]) { + cookieAttribute[0] = cookieAttributeMapping[cookieAttribute[0]]; + } } } - } - - const cookiesToSet = cookies.map(cookie => { - const [name, value] = cookie[0]; - return { - ...Object.fromEntries(cookie.slice(1)), - name, - value, - }; - }); + const cookiesToSet = cookies.map(cookie => { + const [name, value] = cookie[0]; - for (const cookie of cookiesToSet) { - browser.cookies.set({ - ...cookie, - url: details.url, - storeId: container.cookieStoreId, + return { + ...Object.fromEntries(cookie.slice(1)), + name, + value, + }; }); - } - const tab = await browser.tabs.get(details.tabId); + for (const cookie of cookiesToSet) { + browser.cookies.set({ + ...cookie, + url: details.url, + storeId: container.cookieStoreId, + }); + } - const createTabParams = { - cookieStoreId: container.cookieStoreId, - url: redirectUrl, - pinned: false, - index: tab.index, - }; + const tab = await browser.tabs.get(details.tabId); - await browser.tabs.create(createTabParams); + const createTabParams = { + cookieStoreId: container.cookieStoreId, + url: redirectUrl, + pinned: false, + index: tab.index, + }; + + await browser.tabs.create(createTabParams); + + await browser.tabs.remove(details.tabId); + } - await browser.tabs.remove(details.tabId); + let getting = browser.storage.sync.get(["template", "length", "slug"]); + getting.then(process); return { cancel: true }; } @@ -302,13 +324,15 @@ async function samlListener(details) { // Fetch our custom defined container name template function onGot(item) { containerNameTemplate = item.template || "name role"; + containerNameLength = parseInt(item.length, 10) || 0; + containerNameSlug = item.slug || ""; } function onError(error) { console.log("No custom template for AWS SSO containers, using default"); } -let getting = browser.storage.sync.get("template"); +let getting = browser.storage.sync.get(["template", "length", "slug"]); getting.then(onGot, onError); browser.webRequest.onBeforeRequest.addListener( diff --git a/options.html b/options.html index 18791b6..1f421fe 100644 --- a/options.html +++ b/options.html @@ -2,14 +2,33 @@
+ - \ No newline at end of file +