Skip to content

Commit b317a5f

Browse files
committed
In force-verify mode, prevent bypassing by cancelling device verification
1 parent e44ca88 commit b317a5f

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

playwright/e2e/login/login-consent.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { selectHomeserver } from "../utils";
1313
import { type Credentials, type HomeserverInstance } from "../../plugins/homeserver";
1414
import { consentHomeserver } from "../../plugins/homeserver/synapse/consentHomeserver.ts";
1515
import { isDendrite } from "../../plugins/homeserver/dendrite";
16+
import { createBot } from "../crypto/utils.ts";
1617

1718
// This test requires fixed credentials for the device signing keys below to work
1819
const username = "user1234";
@@ -258,6 +259,31 @@ test.describe("Login", () => {
258259

259260
await expect(h1.locator(".mx_CompleteSecurity_skip")).toHaveCount(0);
260261
});
262+
263+
test("Continues to show verification prompt after cancelling device verification", async ({
264+
page,
265+
homeserver,
266+
credentials,
267+
}) => {
268+
// Create a different device which is cross-signed, meaning we need to verify this device
269+
await createBot(page, homeserver, credentials, true);
270+
271+
// Load the page and see that we are asked to verify
272+
await page.goto("/#/login");
273+
await login(page, homeserver, credentials);
274+
let h1 = page.getByRole("heading", { name: "Verify this device", level: 1 });
275+
await expect(h1).toBeVisible();
276+
277+
// Click "Verify with another device"
278+
await page.getByRole("button", { name: "Verify with another device" }).click();
279+
280+
// Cancel the new dialog
281+
await page.getByRole("button", { name: "Close dialog" }).click();
282+
283+
// Check that we are still being asked to verify
284+
h1 = page.getByRole("heading", { name: "Verify this device", level: 1 });
285+
await expect(h1).toBeVisible();
286+
});
261287
});
262288
});
263289
});

src/components/structures/MatrixChat.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,8 +2003,17 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
20032003
};
20042004

20052005
// complete security / e2e setup has finished
2006-
private onCompleteSecurityE2eSetupFinished = (): void => {
2007-
// This is async but we making this function async to wait for it isn't useful
2006+
private onCompleteSecurityE2eSetupFinished = async (): Promise<void> => {
2007+
const forceVerify = await this.shouldForceVerification();
2008+
if (forceVerify) {
2009+
const isVerified = await MatrixClientPeg.safeGet().getCrypto()?.isCrossSigningReady();
2010+
if (!isVerified) {
2011+
// We must verify but we haven't yet verified - don't continue logging in
2012+
return;
2013+
}
2014+
}
2015+
2016+
// (This is async but we making this function async to wait for it isn't useful)
20082017
this.onShowPostLoginScreen().catch((e) => {
20092018
logger.error("Exception showing post-login screen", e);
20102019
});

0 commit comments

Comments
 (0)