1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

short circuit well known URL check on all platforms but the browser (#14566)

This commit is contained in:
Nick Krantz
2025-05-05 13:48:16 -05:00
committed by GitHub
parent fd43222938
commit f3acfb29e5
2 changed files with 37 additions and 2 deletions

View File

@@ -6,6 +6,8 @@
import { mock } from "jest-mock-extended";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ClientType } from "@bitwarden/common/enums";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view";
@@ -19,7 +21,12 @@ describe("DefaultChangeLoginPasswordService", () => {
let mockShouldNotExistResponse: Response;
let mockWellKnownResponse: Response;
const getClientType = jest.fn(() => ClientType.Browser);
const mockApiService = mock<ApiService>();
const platformUtilsService = mock<PlatformUtilsService>({
getClientType,
});
beforeEach(() => {
mockApiService.nativeFetch.mockClear();
@@ -41,7 +48,7 @@ describe("DefaultChangeLoginPasswordService", () => {
throw new Error("Unexpected request");
});
service = new DefaultChangeLoginPasswordService(mockApiService);
service = new DefaultChangeLoginPasswordService(mockApiService, platformUtilsService);
});
it("should return null for non-login ciphers", async () => {
@@ -184,4 +191,20 @@ describe("DefaultChangeLoginPasswordService", () => {
expect(url).toBe("https://working.com/.well-known/change-password");
});
it("should return the first URI when the client type is not browser", async () => {
getClientType.mockReturnValue(ClientType.Web);
const cipher = {
type: CipherType.Login,
login: Object.assign(new LoginView(), {
uris: [{ uri: "https://example.com/" }, { uri: "https://example-2.com/" }],
}),
} as CipherView;
const url = await service.getChangePasswordUrl(cipher);
expect(mockApiService.nativeFetch).not.toHaveBeenCalled();
expect(url).toBe("https://example.com/");
});
});

View File

@@ -1,6 +1,7 @@
import { Injectable } from "@angular/core";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
@@ -9,7 +10,10 @@ import { ChangeLoginPasswordService } from "../abstractions/change-login-passwor
@Injectable()
export class DefaultChangeLoginPasswordService implements ChangeLoginPasswordService {
constructor(private apiService: ApiService) {}
constructor(
private apiService: ApiService,
private platformUtilsService: PlatformUtilsService,
) {}
/**
* @inheritDoc
@@ -29,6 +33,14 @@ export class DefaultChangeLoginPasswordService implements ChangeLoginPasswordSer
return null;
}
// CSP policies on the web and desktop restrict the application from making
// cross-origin requests, breaking the below .well-known URL checks.
// For those platforms, this will short circuit and return the first URL.
// PM-21024 will build a solution for the server side to handle this.
if (this.platformUtilsService.getClientType() !== "browser") {
return urls[0].href;
}
for (const url of urls) {
const [reliable, wellKnownChangeUrl] = await Promise.all([
this.hasReliableHttpStatusCode(url.origin),