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

* Show screen before login if using start_sso or start_cas

* Add tests

* Fix lint

* Fix lint

* Add one for CAS

* prettier
This commit is contained in:
Will Hunt 2023-10-03 16:19:54 +01:00 committed by GitHub
parent 54a4875e15
commit 677854d318
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 1 deletions

View file

@ -393,7 +393,8 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
return; 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(); this.showScreenAfterLogin();
} }
} }

View file

@ -41,6 +41,7 @@ import {
MockClientWithEventEmitter, MockClientWithEventEmitter,
mockPlatformPeg, mockPlatformPeg,
resetJsDomAfterEach, resetJsDomAfterEach,
unmockClientPeg,
} from "../../test-utils"; } from "../../test-utils";
import * as leaveRoomUtils from "../../../src/utils/leave-behaviour"; import * as leaveRoomUtils from "../../../src/utils/leave-behaviour";
import * as voiceBroadcastUtils from "../../../src/voice-broadcast/utils/cleanUpBroadcasts"; import * as voiceBroadcastUtils from "../../../src/voice-broadcast/utils/cleanUpBroadcasts";
@ -51,6 +52,7 @@ import { PosthogAnalytics } from "../../../src/PosthogAnalytics";
import PlatformPeg from "../../../src/PlatformPeg"; import PlatformPeg from "../../../src/PlatformPeg";
import EventIndexPeg from "../../../src/indexing/EventIndexPeg"; import EventIndexPeg from "../../../src/indexing/EventIndexPeg";
import * as Lifecycle from "../../../src/Lifecycle"; 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", () => ({ jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({
completeAuthorizationCodeGrant: jest.fn(), completeAuthorizationCodeGrant: jest.fn(),
@ -69,6 +71,7 @@ describe("<MatrixChat />", () => {
setCanResetTimelineCallback: jest.fn(), setCanResetTimelineCallback: jest.fn(),
isInitialSyncComplete: jest.fn(), isInitialSyncComplete: jest.fn(),
getSyncState: jest.fn(), getSyncState: jest.fn(),
getSsoLoginUrl: jest.fn(),
getSyncStateData: jest.fn().mockReturnValue(null), getSyncStateData: jest.fn().mockReturnValue(null),
getThirdpartyProtocols: jest.fn().mockResolvedValue({}), getThirdpartyProtocols: jest.fn().mockResolvedValue({}),
getClientWellKnown: jest.fn().mockReturnValue({}), getClientWellKnown: jest.fn().mockReturnValue({}),
@ -1107,6 +1110,64 @@ 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", {
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", () => { describe("Multi-tab lockout", () => {
afterEach(() => { afterEach(() => {
Lifecycle.setSessionLockNotStolen(); Lifecycle.setSessionLockNotStolen();