diff --git a/apps/web/src/connectors/duo-redirect.ts b/apps/web/src/connectors/duo-redirect.ts index 842bd8c0064..5275984f329 100644 --- a/apps/web/src/connectors/duo-redirect.ts +++ b/apps/web/src/connectors/duo-redirect.ts @@ -1,5 +1,6 @@ import { getQsParam } from "./common"; import { TranslationService } from "./translation.service"; +import { buildMobileCallbackUri } from "./utils/callbackUri"; const mobileDesktopCallback = "bitwarden://duo-callback"; let localeService: TranslationService | null = null; @@ -41,14 +42,22 @@ window.addEventListener("load", async () => { } else if (client === "mobile" || client === "desktop") { if (client === "desktop") { displayHandoffMessage(client); + document.location.replace( + mobileDesktopCallback + + "?code=" + + encodeURIComponent(code) + + "&state=" + + encodeURIComponent(state), + ); + } else { + document.location.replace( + buildMobileCallbackUri("duo") + + "?code=" + + encodeURIComponent(code) + + "&state=" + + encodeURIComponent(state), + ); } - document.location.replace( - mobileDesktopCallback + - "?code=" + - encodeURIComponent(code) + - "&state=" + - encodeURIComponent(state), - ); } }); diff --git a/apps/web/src/connectors/utils/callbackUri.ts b/apps/web/src/connectors/utils/callbackUri.ts new file mode 100644 index 00000000000..f3d4e9931a0 --- /dev/null +++ b/apps/web/src/connectors/utils/callbackUri.ts @@ -0,0 +1,13 @@ +const SELF_HOSTED = (process.env.SELF_HOSTED || "false").toLowerCase() === "true"; + +function appLinkHost(): string { + const h = window.location.hostname || ""; + if (h.endsWith("bitwarden.eu")) {return "bitwarden.eu";} + if (h.endsWith("bitwarden.pw")) {return "bitwarden.pw";} + return "bitwarden.com"; +} + +export function buildMobileCallbackUri(kind: "sso" | "duo" | "webauthn"): string { + const path = `${kind}-callback`; + return SELF_HOSTED ? `bitwarden://${path}` : `https://${appLinkHost()}/${path}`; +} diff --git a/apps/web/src/connectors/webauthn.ts b/apps/web/src/connectors/webauthn.ts index fe400c7f0cd..4309c5df981 100644 --- a/apps/web/src/connectors/webauthn.ts +++ b/apps/web/src/connectors/webauthn.ts @@ -2,8 +2,7 @@ // @ts-strict-ignore import { b64Decode, getQsParam } from "./common"; import { buildDataString, parseWebauthnJson } from "./common-webauthn"; - -const mobileCallbackUri = "bitwarden://webauthn-callback"; +import { buildMobileCallbackUri } from "./utils/callbackUri"; let parsed = false; let webauthnJson: any; @@ -216,8 +215,9 @@ function onMessage() { function error(message: string) { if (mobileResponse) { - document.location.replace(mobileCallbackUri + "?error=" + encodeURIComponent(message)); - returnButton(mobileCallbackUri + "?error=" + encodeURIComponent(message)); + const callbackUri = buildMobileCallbackUri("webauthn"); + document.location.replace(callbackUri + "?error=" + encodeURIComponent(message)); + returnButton(callbackUri + "?error=" + encodeURIComponent(message)); } else { parent.postMessage("error|" + message, parentUrl); setDefaultWebAuthnButtonState(); @@ -232,8 +232,9 @@ function success(assertedCredential: PublicKeyCredential) { const dataString = buildDataString(assertedCredential); if (mobileResponse) { - document.location.replace(mobileCallbackUri + "?data=" + encodeURIComponent(dataString)); - returnButton(mobileCallbackUri + "?data=" + encodeURIComponent(dataString)); + const callbackUri = buildMobileCallbackUri("webauthn"); + document.location.replace(callbackUri + "?data=" + encodeURIComponent(dataString)); + returnButton(callbackUri + "?data=" + encodeURIComponent(dataString)); } else { parent.postMessage("success|" + dataString, parentUrl); sentSuccess = true; diff --git a/apps/web/webpack.base.js b/apps/web/webpack.base.js index cc17b3b7cfd..c2554603c9c 100644 --- a/apps/web/webpack.base.js +++ b/apps/web/webpack.base.js @@ -215,6 +215,7 @@ module.exports.buildConfig = function buildConfig(params) { NODE_ENV: NODE_ENV === "production" ? "production" : "development", APPLICATION_VERSION: pjson.version, CACHE_TAG: Math.random().toString(36).substring(7), + SELF_HOSTED: process.env.SELF_HOSTED ?? (ENV === "selfhosted" ? "true" : "false"), URLS: envConfig["urls"] ?? {}, STRIPE_KEY: envConfig["stripeKey"] ?? "", BRAINTREE_KEY: envConfig["braintreeKey"] ?? "",