Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix start_sso / start_cas URLs failing to redirect to a authentication prompt #11681

Merged
merged 7 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/components/structures/MatrixChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
return;
}

if (firstScreen === "login" || firstScreen === "register" || firstScreen === "forgot_password") {
// If the first screen is an auth screen, we don't want to wait for login.
if (firstScreen !== null && AUTH_SCREENS.includes(firstScreen)) {
this.showScreenAfterLogin();
}
}
Expand Down
62 changes: 62 additions & 0 deletions test/components/structures/MatrixChat-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
MockClientWithEventEmitter,
mockPlatformPeg,
resetJsDomAfterEach,
unmockClientPeg,
} from "../../test-utils";
import * as leaveRoomUtils from "../../../src/utils/leave-behaviour";
import * as voiceBroadcastUtils from "../../../src/voice-broadcast/utils/cleanUpBroadcasts";
Expand All @@ -51,6 +52,7 @@ import { PosthogAnalytics } from "../../../src/PosthogAnalytics";
import PlatformPeg from "../../../src/PlatformPeg";
import EventIndexPeg from "../../../src/indexing/EventIndexPeg";
import * as Lifecycle from "../../../src/Lifecycle";
import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../src/BasePlatform";

jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({
completeAuthorizationCodeGrant: jest.fn(),
Expand All @@ -69,6 +71,7 @@ describe("<MatrixChat />", () => {
setCanResetTimelineCallback: jest.fn(),
isInitialSyncComplete: jest.fn(),
getSyncState: jest.fn(),
getSsoLoginUrl: jest.fn(),
getSyncStateData: jest.fn().mockReturnValue(null),
getThirdpartyProtocols: jest.fn().mockResolvedValue({}),
getClientWellKnown: jest.fn().mockReturnValue({}),
Expand Down Expand Up @@ -1107,6 +1110,65 @@ describe("<MatrixChat />", () => {
});
});

describe("automatic SSO selection", () => {
let ssoClient: ReturnType<typeof getMockClientWithEventEmitter>;
let hrefSetter: jest.Mock<void, [string]>;
beforeEach(() => {
ssoClient = getMockClientWithEventEmitter({
...getMockClientMethods(),
getHomeserverUrl: jest.fn().mockReturnValue("matrix.example.com"),
getIdentityServerUrl: jest.fn().mockReturnValue("ident.example.com"),
getSsoLoginUrl: jest.fn().mockReturnValue("http://my-sso-url"),
});
// this is used to create a temporary client to cleanup after logout
jest.spyOn(MatrixJs, "createClient").mockClear().mockReturnValue(ssoClient);
mockPlatformPeg();
// Ensure we don't have a client peg as we aren't logged in.
unmockClientPeg();


hrefSetter = jest.fn();
const originalHref = window.location.href.toString();
Object.defineProperty(window, "location", {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This felt a little ugly but I borrowed the idea from another test.

value: {
get href() {
return originalHref;
},
set href(href) {
hrefSetter(href);
}
},
writable: true,
});
});

it("should automatically setup and redirect to SSO login", async () => {
getComponent({
initialScreenAfterLogin: {
screen: 'start_sso',
}
});
await flushPromises();
expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'sso', undefined, undefined);
expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com");
expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com");
expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url");
});

it("should automatically setup and redirect to CAS login", async () => {
getComponent({
initialScreenAfterLogin: {
screen: 'start_cas',
}
});
await flushPromises();
expect(ssoClient.getSsoLoginUrl).toHaveBeenCalledWith('http://localhost/', 'cas', undefined, undefined);
expect(window.localStorage.getItem(SSO_HOMESERVER_URL_KEY)).toEqual("matrix.example.com");
expect(window.localStorage.getItem(SSO_ID_SERVER_URL_KEY)).toEqual("ident.example.com");
expect(hrefSetter).toHaveBeenCalledWith("http://my-sso-url");
});
});

describe("Multi-tab lockout", () => {
afterEach(() => {
Lifecycle.setSessionLockNotStolen();
Expand Down