From 877d379f8634227eef157b13e08a3884f6da7209 Mon Sep 17 00:00:00 2001 From: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:02:10 -0400 Subject: [PATCH] Auth/PM-8111 - LoginComponent Refactor Bug - Fix Extension SSO (#11699) * PM-8111 - LoginComponent Refactor - I broke the browser SSO flow - fixing it as clientId doesn't persist unless it is in state qParam. * PM-8111 - Fix DefaultLoginComponentService tests --- apps/web/src/connectors/sso.ts | 3 +-- .../angular/login/default-login-component.service.spec.ts | 8 +++++++- .../src/angular/login/default-login-component.service.ts | 7 ++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/web/src/connectors/sso.ts b/apps/web/src/connectors/sso.ts index 44ead1dc18..e049c64e5d 100644 --- a/apps/web/src/connectors/sso.ts +++ b/apps/web/src/connectors/sso.ts @@ -6,11 +6,10 @@ window.addEventListener("load", () => { const code = getQsParam("code"); const state = getQsParam("state"); const lastpass = getQsParam("lp"); - const clientId = getQsParam("clientId"); if (lastpass === "1") { initiateBrowserSso(code, state, true); - } else if (state != null && clientId == "browser") { + } else if (state != null && state.includes(":clientId=browser")) { initiateBrowserSso(code, state, false); } else { window.location.href = window.location.origin + "/#/sso?code=" + code + "&state=" + state; diff --git a/libs/auth/src/angular/login/default-login-component.service.spec.ts b/libs/auth/src/angular/login/default-login-component.service.spec.ts index 2b565ea67b..9878372801 100644 --- a/libs/auth/src/angular/login/default-login-component.service.spec.ts +++ b/libs/auth/src/angular/login/default-login-component.service.spec.ts @@ -83,12 +83,14 @@ describe("DefaultLoginComponentService", () => { describe("launchSsoBrowserWindow", () => { const email = "test@bitwarden.com"; - const state = "testState"; + let state = "testState"; const codeVerifier = "testCodeVerifier"; const codeChallenge = "testCodeChallenge"; const baseUrl = "https://webvault.bitwarden.com/#/sso"; beforeEach(() => { + state = "testState"; + passwordGenerationService.generatePassword.mockResolvedValueOnce(state); passwordGenerationService.generatePassword.mockResolvedValueOnce(codeVerifier); jest.spyOn(Utils, "fromBufferToUrlB64").mockReturnValue(codeChallenge); @@ -112,6 +114,10 @@ describe("DefaultLoginComponentService", () => { await service.launchSsoBrowserWindow(email, clientId as "browser" | "desktop"); + if (clientType === ClientType.Browser) { + state += ":clientId=browser"; + } + const expectedUrl = `${baseUrl}?clientId=${clientId}&redirectUri=${encodeURIComponent(expectedRedirectUri)}&state=${state}&codeChallenge=${codeChallenge}&email=${encodeURIComponent(email)}`; expect(ssoLoginService.setSsoEmail).toHaveBeenCalledWith(email); diff --git a/libs/auth/src/angular/login/default-login-component.service.ts b/libs/auth/src/angular/login/default-login-component.service.ts index 30ab55cc0e..a06ad1e653 100644 --- a/libs/auth/src/angular/login/default-login-component.service.ts +++ b/libs/auth/src/angular/login/default-login-component.service.ts @@ -50,7 +50,12 @@ export class DefaultLoginComponentService implements LoginComponentService { special: false, }; - const state = await this.passwordGenerationService.generatePassword(passwordOptions); + let state = await this.passwordGenerationService.generatePassword(passwordOptions); + + if (clientId === "browser") { + // Need to persist the clientId in the state for the extension + state += ":clientId=browser"; + } const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, "sha256");