MSC4108 support OIDC QR code login (#12370)

Co-authored-by: Hugh Nimmo-Smith <hughns@matrix.org>
This commit is contained in:
Michael Telatynski 2024-06-06 09:57:28 +01:00 committed by GitHub
parent ca7760789b
commit 1677ed1be0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 1558 additions and 733 deletions

View file

@ -34,6 +34,7 @@ import {
MatrixClient,
} from "matrix-js-sdk/src/matrix";
import { mocked, MockedObject } from "jest-mock";
import fetchMock from "fetch-mock-jest";
import {
clearAllModals,
@ -53,6 +54,8 @@ import SettingsStore from "../../../../../../src/settings/SettingsStore";
import { getClientInformationEventType } from "../../../../../../src/utils/device/clientInformation";
import { SDKContext, SdkContextClass } from "../../../../../../src/contexts/SDKContext";
import { OidcClientStore } from "../../../../../../src/stores/oidc/OidcClientStore";
import { mockOpenIdConfiguration } from "../../../../../test-utils/oidc";
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
mockPlatformPeg();
@ -119,6 +122,8 @@ describe("<SessionManagerTab />", () => {
getDeviceVerificationStatus: jest.fn(),
getUserDeviceInfo: jest.fn(),
requestDeviceVerification: jest.fn().mockResolvedValue(mockVerificationRequest),
supportsSecretsForQrLogin: jest.fn().mockReturnValue(false),
isCrossSigningReady: jest.fn().mockReturnValue(true),
} as unknown as CryptoApi);
let mockClient!: MockedObject<MatrixClient>;
@ -127,7 +132,9 @@ describe("<SessionManagerTab />", () => {
const defaultProps = {};
const getComponent = (props = {}): React.ReactElement => (
<SDKContext.Provider value={sdkContext}>
<SessionManagerTab {...defaultProps} {...props} />
<MatrixClientContext.Provider value={mockClient}>
<SessionManagerTab {...defaultProps} {...props} />
</MatrixClientContext.Provider>
</SDKContext.Provider>
);
@ -207,6 +214,7 @@ describe("<SessionManagerTab />", () => {
getPushers: jest.fn(),
setPusher: jest.fn(),
setLocalNotificationSettings: jest.fn(),
getAuthIssuer: jest.fn().mockReturnValue(new Promise(() => {})),
});
jest.clearAllMocks();
jest.spyOn(logger, "error").mockRestore();
@ -1664,7 +1672,7 @@ describe("<SessionManagerTab />", () => {
expect(checkbox.getAttribute("aria-checked")).toEqual("false");
});
describe("QR code login", () => {
describe("MSC3906 QR code login", () => {
const settingsValueSpy = jest.spyOn(SettingsStore, "getValue");
beforeEach(() => {
@ -1694,13 +1702,71 @@ describe("<SessionManagerTab />", () => {
});
it("enters qr code login section when show QR code button clicked", async () => {
const { getByText, getByTestId } = render(getComponent());
const { getByText, findByTestId } = render(getComponent());
// wait for versions call to settle
await flushPromises();
fireEvent.click(getByText("Show QR code"));
expect(getByTestId("login-with-qr")).toBeTruthy();
await expect(findByTestId("login-with-qr")).resolves.toBeTruthy();
});
});
describe("MSC4108 QR code login", () => {
const settingsValueSpy = jest.spyOn(SettingsStore, "getValue");
const issuer = "https://issuer.org";
const openIdConfiguration = mockOpenIdConfiguration(issuer);
beforeEach(() => {
settingsValueSpy.mockClear().mockReturnValue(true);
// enable server support for qr login
mockClient.getVersions.mockResolvedValue({
versions: [],
unstable_features: {
"org.matrix.msc4108": true,
},
});
mockClient.getCapabilities.mockResolvedValue({
[GET_LOGIN_TOKEN_CAPABILITY.name]: {
enabled: true,
},
});
mockClient.getAuthIssuer.mockResolvedValue({ issuer });
mockCrypto.exportSecretsBundle = jest.fn();
fetchMock.mock(`${issuer}/.well-known/openid-configuration`, {
...openIdConfiguration,
grant_types_supported: [
...openIdConfiguration.grant_types_supported,
"urn:ietf:params:oauth:grant-type:device_code",
],
});
fetchMock.mock(openIdConfiguration.jwks_uri!, {
status: 200,
headers: {
"Content-Type": "application/json",
},
keys: [],
});
});
it("renders qr code login section", async () => {
const { getByText } = render(getComponent());
// wait for versions call to settle
await flushPromises();
expect(getByText("Link new device")).toBeTruthy();
expect(getByText("Show QR code")).toBeTruthy();
});
it("enters qr code login section when show QR code button clicked", async () => {
const { getByText, findByTestId } = render(getComponent());
// wait for versions call to settle
await flushPromises();
fireEvent.click(getByText("Show QR code"));
await expect(findByTestId("login-with-qr")).resolves.toBeTruthy();
});
});
});