diff --git a/src/extension/background-script/connectors/alby.ts b/src/extension/background-script/connectors/alby.ts index 38af1df487..2e5a9aa916 100644 --- a/src/extension/background-script/connectors/alby.ts +++ b/src/extension/background-script/connectors/alby.ts @@ -237,7 +237,8 @@ export default class Alby implements Connector { throw new Error("OAuth client credentials missing"); } - const redirectURL = browser.identity.getRedirectURL(); + const redirectURL = "https://getalby.com/extension/connect"; + const authClient = new auth.OAuth2User({ request_options: this._getRequestOptions(), client_id: clientId, @@ -273,8 +274,6 @@ export default class Alby implements Connector { } return authClient; } catch (error) { - // if auth token refresh fails, the refresh token has probably expired or is invalid - // the user will be asked to re-login console.error("Failed to request new auth token", error); } } @@ -285,28 +284,62 @@ export default class Alby implements Connector { }); authUrl += "&webln=false"; // stop getalby.com login modal launching lnurl auth - const authResult = await this.launchWebAuthFlow(authUrl); - const code = new URL(authResult).searchParams.get("code"); - if (!code) { - throw new Error("Authentication failed: missing authResult"); - } - const token = await authClient.requestAccessToken(code); - await this._updateOAuthToken(token.token); - return authClient; + const oAuthTab = await browser.tabs.create({ url: authUrl }); + + return new Promise((resolve, reject) => { + const handleTabUpdated = ( + tabId: number, + changeInfo: browser.Tabs.OnUpdatedChangeInfoType, + tab: browser.Tabs.Tab + ) => { + if (changeInfo.status === "complete" && tabId === oAuthTab.id) { + const authorizationCode = this.extractCodeFromTabUrl(tab.url); + + if (!authorizationCode) { + throw new Error("no authorization code"); + } + + authClient + .requestAccessToken(authorizationCode) + .then((token) => { + this._updateOAuthToken(token.token); + resolve(authClient); + }) + .catch((error) => { + console.error("Failed to request new auth token", error); + reject(error); + }) + .finally(() => { + browser.tabs.remove(tabId); + browser.tabs.onUpdated.removeListener(handleTabUpdated); + }); + } + }; + const handleTabRemoved = (tabId: number) => { + if (tabId === oAuthTab.id) { + // The user closed the authentication tab without completing the flow + const error = new Error("OAuth authentication canceled by user"); + reject(error); + browser.tabs.onRemoved.removeListener(handleTabRemoved); + } + }; + + browser.tabs.onUpdated.addListener(handleTabUpdated); + browser.tabs.onRemoved.addListener(handleTabRemoved); + }); } catch (error) { console.error(error); throw error; } } - async launchWebAuthFlow(authUrl: string) { - const authResult = await browser.identity.launchWebAuthFlow({ - interactive: true, - url: authUrl, - }); - - return authResult; + private extractCodeFromTabUrl(url: string | undefined): string | null { + if (!url) { + return null; + } + const urlSearchParams = new URLSearchParams(url.split("?")[1]); + return urlSearchParams.get("code"); } private async _request(func: (client: Client) => T) { diff --git a/webpack.config.js b/webpack.config.js index f1e002c544..0bf05a879d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -51,58 +51,24 @@ if (clientId && clientSecret) { ); } else { const oauthCredentials = { - development: { - testnet: { - chrome: { - id: "CLAp8AfS3W", - secret: "KwIxF0VbGX2ZHLbbbYgE", - }, - firefox: { - id: "zWdxnF04Hd", - secret: "wY5uLJJDjNWrDlB6lAj8", - }, - }, - mainnet: { - chrome: { - id: "Zf7u3Zlyxl", - secret: "7wtcdVi61emqwzAH9Nm6", - }, - firefox: { - id: "uQkyHFBkaC", - secret: "0agh0cKkGWQSXTGRz9oy", - }, - }, + testnet: { + id: "TliTCTtJ49", + secret: "35RixI2gv0xloVYA0Iq3", }, - production: { - testnet: { - // only chrome is used for E2E tests - chrome: { - id: "mI5TEUKCwD", - secret: "47lxj2WNCJyVpxiy6vgq", - }, - }, - mainnet: { - chrome: { - id: "R7lZBSqfQt", - secret: "W4yWprd5ib6OSfq27InN", - }, - firefox: { - id: "V682entasX", - secret: "GhL3g37I3NAwzavCB3A5", - }, - }, + mainnet: { + id: "NT8bFB23Sk", + secret: "wWp7BPpYOm1H0GwSVVpY", }, }; // setup ALBY_OAUTH_CLIENT_ID - const selectedOAuthCredentials = - oauthCredentials[nodeEnv]?.[network]?.[oauthBrowser]; + const selectedOAuthCredentials = oauthCredentials[network]; if (!selectedOAuthCredentials) { throw new Error( - `No OAuth credentials found for current configuration: NODE_ENV=${nodeEnv} network=${network} oauthBrowser=${oauthBrowser}` + `No OAuth credentials found for current configuration: network=${network}` ); } - console.info("Using OAuth credentials for", nodeEnv, oauthBrowser, network); + console.info("Using OAuth credentials for", network); process.env.ALBY_OAUTH_CLIENT_ID = selectedOAuthCredentials.id; process.env.ALBY_OAUTH_CLIENT_SECRET = selectedOAuthCredentials.secret; }