From 63dc42befff9b097029ac6dbc1a632b3d34fa161 Mon Sep 17 00:00:00 2001 From: slinkymanbyday Date: Sun, 14 Jan 2024 08:46:01 +0800 Subject: [PATCH] feat: fix to work with new SSO experience (#14) Co-authored-by: Sean Meyer --- containerize.js | 111 +++++++++++++++++++++++++++++++++++------------- manifest.json | 7 ++- options.html | 6 +-- options.js | 3 +- 4 files changed, 91 insertions(+), 36 deletions(-) diff --git a/containerize.js b/containerize.js index 04611cf..76df846 100644 --- a/containerize.js +++ b/containerize.js @@ -29,6 +29,8 @@ const availableContainerColors = [ let containerNameTemplate = "name role"; +let accountMap = {}; + function randomIcon() { return availableContainerIcons[Math.random() * availableContainerIcons.length | 0] } @@ -40,7 +42,7 @@ function randomColor() { function prepareContainer({ name, color, icon, cb }) { browser.contextualIdentities.query({ name: name, - }).then(function(containers) { + }).then(function (containers) { if (containers.length >= 1) { cb(containers[0]); } else { @@ -48,7 +50,7 @@ function prepareContainer({ name, color, icon, cb }) { name: name, color: color || randomColor(), icon: icon || randomIcon(), - }).then(function(container) { + }).then(function (container) { cb(container); }); } @@ -65,27 +67,28 @@ function listener(details) { }*/ // Intercept our response + let filter = browser.webRequest.filterResponseData(details.requestId); + let queryString = new URLSearchParams(details.url.split("?")[1]); // Parse some params for container name - let accountRole = details.url.split("=")[2]; - // account is account ID and account name in parens - let account = decodeURIComponent(details.originUrl.split("/")[7]); - // getting fancy w/ regex to capture account names with parens - let capture = /^(\d+) \((.+)\)$/.exec(account); - let accountNumber = capture[1]; - let accountName = capture[2]; + let accountRole = queryString.get("role_name"); + let accountNumber = queryString.get("account_id"); + // pull subdomain for folks that might have multiple SSO // portals that have access to the same account and role names let host = /:\/\/([^\/]+)/.exec(details.originUrl)[1]; let subdomain = host.split(".")[0]; - const params = { - 'name': accountName, + let params = { 'number': accountNumber, 'role': accountRole, 'subdomain': subdomain }; + if(accountMap[accountNumber] !== undefined){ + params["name"] = accountMap[accountNumber]["name"]; + params["email"] = accountMap[accountNumber]["email"]; + } let name = containerNameTemplate; @@ -98,7 +101,7 @@ function listener(details) { let encoder = new TextEncoder(); filter.ondata = event => { - str += decoder.decode(event.data, {stream: true}); + str += decoder.decode(event.data, { stream: true }); }; filter.onstop = event => { @@ -119,19 +122,21 @@ function listener(details) { // 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); - prepareContainer({name: name, cb: function(container) { - const createTabParams = { - cookieStoreId: container.cookieStoreId, - url: url, - pinned: false - }; - // get index of tab we're about to remove, put ours at that spot - browser.tabs.get(details.tabId).then(function(tab) { - createTabParams.index = tab.index; - browser.tabs.create(createTabParams); - }); - browser.tabs.remove(details.tabId); - }}); + prepareContainer({ + name: name, cb: function (container) { + const createTabParams = { + cookieStoreId: container.cookieStoreId, + url: url, + pinned: false + }; + // get index of tab we're about to remove, put ours at that spot + browser.tabs.get(details.tabId).then(function (tab) { + createTabParams.index = tab.index; + browser.tabs.create(createTabParams); + }); + browser.tabs.remove(details.tabId); + } + }); } else { filter.write(encoder.encode(str)); } @@ -141,6 +146,41 @@ function listener(details) { return {}; } +function accountNameListener(details) { + // Intercept our response + let filter = browser.webRequest.filterResponseData(details.requestId); + + let str = ''; + let decoder = new TextDecoder("utf-8"); + let encoder = new TextEncoder(); + + filter.ondata = event => { + str += decoder.decode(event.data, { stream: true }); + }; + filter.onstop = event => { + filter.write(encoder.encode(str)); + // The first OPTIONS request has no response body + if (str.length > 0) { + // signInToken + // signInFederationLocation + // destination + const object = JSON.parse(str); + + for (result of object.result) { + if(result["searchMetadata"]){ + accountMap[result["searchMetadata"]["AccountId"]] = { + "name": result["searchMetadata"]["AccountName"], + "email": result["searchMetadata"]["AccountEmail"] + } + } + } + } + filter.close(); + } + + return {}; + +} // Fetch our custom defined container name template function onGot(item) { @@ -156,10 +196,21 @@ getting.then(onGot, onError); browser.webRequest.onBeforeRequest.addListener( listener, - {urls: [ - "https://*.amazonaws.com/federation/console?*", - "https://*.amazonaws-us-gov.com/federation/console?*", - "https://*.amazonaws.cn/federation/console?*" - ], types: ["xmlhttprequest"]}, + { + urls: [ + "https://*.amazonaws.com/federation/console?*", + "https://*.amazonaws-us-gov.com/federation/console?*", + "https://*.amazonaws.cn/federation/console?*" + ], types: ["xmlhttprequest"] + }, + ["blocking"] +); +browser.webRequest.onBeforeRequest.addListener( + accountNameListener, + { + urls: [ + "https://*.amazonaws.com/instance/appinstances" + ], types: ["xmlhttprequest"] + }, ["blocking"] ); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 836a469..2f421a3 100644 --- a/manifest.json +++ b/manifest.json @@ -17,10 +17,13 @@ "storage", "webRequest", "webRequestBlocking", - "https://*.awsapps.com/start/*", + "https://*.awsapps.com/*", "https://*.amazonaws.com/federation/console?*", "https://*.amazonaws-us-gov.com/federation/console?*", - "https://*.amazonaws.cn/federation/console?*" + "https://*.amazonaws.cn/federation/console?*", + "https://*.amazonaws.com/federation/instance/appinstances", + "https://*.amazonaws-us-gov.com/federation/instance/appinstances", + "https://*.amazonaws.cn/federation/instance/appinstances" ], "background": { "scripts": [ diff --git a/options.html b/options.html index 6a6a6e5..18791b6 100644 --- a/options.html +++ b/options.html @@ -12,8 +12,9 @@

Available variables:

@@ -23,5 +24,4 @@ - - + \ No newline at end of file diff --git a/options.js b/options.js index 715c0b8..851b83f 100644 --- a/options.js +++ b/options.js @@ -1,5 +1,6 @@ let examples = { 'name': 'Prod', + 'email': 'Prod@example.com', 'number': '123456', 'role': 'InfraEng', 'subdomain': 'MegaCorp' @@ -38,4 +39,4 @@ document.addEventListener("DOMContentLoaded", restoreOptions); document.querySelector("form").addEventListener("submit", saveOptions); document.querySelector("#template").addEventListener("input", function(evt) { populatePreview(this.value); -}); +}); \ No newline at end of file