Fix Native OIDC for Element Desktop (#12253)
* Reuse exported common type Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve client metadata used for OIDC dynamic registration Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix Native OIDC for Element Desktop by including ssoid in the url_state of the /auth call Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Reuse exported common type Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve client metadata used for OIDC dynamic registration Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix typo Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Mock PlatformPeg Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Mock platform Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add comment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve comment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update src/BasePlatform.ts Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
This commit is contained in:
parent
c71b8fdf78
commit
618462ba06
6 changed files with 23 additions and 5 deletions
|
@ -313,7 +313,11 @@ export default abstract class BasePlatform {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getSSOCallbackUrl(fragmentAfterLogin = ""): URL {
|
/**
|
||||||
|
* The URL to return to after a successful SSO/OIDC authentication
|
||||||
|
* @param fragmentAfterLogin optional fragment for specific view to return to
|
||||||
|
*/
|
||||||
|
public getSSOCallbackUrl(fragmentAfterLogin = ""): URL {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
url.hash = fragmentAfterLogin;
|
url.hash = fragmentAfterLogin;
|
||||||
return url;
|
return url;
|
||||||
|
@ -478,4 +482,12 @@ export default abstract class BasePlatform {
|
||||||
policyUri: config.privacy_policy_url,
|
policyUri: config.privacy_policy_url,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suffix to append to the `state` parameter of OIDC /auth calls. Will be round-tripped to the callback URI.
|
||||||
|
* Currently only required for ElectronPlatform for passing element-desktop-ssoid.
|
||||||
|
*/
|
||||||
|
public getOidcClientState(): string {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -777,7 +777,7 @@ async function createOidcTokenRefresher(credentials: IMatrixClientCreds): Promis
|
||||||
try {
|
try {
|
||||||
const clientId = getStoredOidcClientId();
|
const clientId = getStoredOidcClientId();
|
||||||
const idTokenClaims = getStoredOidcIdTokenClaims();
|
const idTokenClaims = getStoredOidcIdTokenClaims();
|
||||||
const redirectUri = window.location.origin;
|
const redirectUri = PlatformPeg.get()!.getSSOCallbackUrl().href;
|
||||||
const deviceId = credentials.deviceId;
|
const deviceId = credentials.deviceId;
|
||||||
if (!deviceId) {
|
if (!deviceId) {
|
||||||
throw new Error("Expected deviceId in user credentials.");
|
throw new Error("Expected deviceId in user credentials.");
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { OidcClient } from "oidc-client-ts";
|
||||||
|
|
||||||
import { getStoredOidcTokenIssuer, getStoredOidcClientId } from "../../utils/oidc/persistOidcSettings";
|
import { getStoredOidcTokenIssuer, getStoredOidcClientId } from "../../utils/oidc/persistOidcSettings";
|
||||||
import { getDelegatedAuthAccountUrl } from "../../utils/oidc/getDelegatedAuthAccountUrl";
|
import { getDelegatedAuthAccountUrl } from "../../utils/oidc/getDelegatedAuthAccountUrl";
|
||||||
|
import PlatformPeg from "../../PlatformPeg";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @experimental
|
* @experimental
|
||||||
|
@ -139,7 +140,7 @@ export class OidcClientStore {
|
||||||
...metadata,
|
...metadata,
|
||||||
authority: metadata.issuer,
|
authority: metadata.issuer,
|
||||||
signingKeys,
|
signingKeys,
|
||||||
redirect_uri: window.location.origin,
|
redirect_uri: PlatformPeg.get()!.getSSOCallbackUrl().href,
|
||||||
client_id: clientId,
|
client_id: clientId,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||||
import { IdTokenClaims } from "oidc-client-ts";
|
import { IdTokenClaims } from "oidc-client-ts";
|
||||||
|
|
||||||
import { OidcClientError } from "./error";
|
import { OidcClientError } from "./error";
|
||||||
|
import PlatformPeg from "../../PlatformPeg";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start OIDC authorization code flow
|
* Start OIDC authorization code flow
|
||||||
|
@ -39,7 +40,7 @@ export const startOidcLogin = async (
|
||||||
identityServerUrl?: string,
|
identityServerUrl?: string,
|
||||||
isRegistration?: boolean,
|
isRegistration?: boolean,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const redirectUri = window.location.origin;
|
const redirectUri = PlatformPeg.get()!.getSSOCallbackUrl().href;
|
||||||
|
|
||||||
const nonce = randomString(10);
|
const nonce = randomString(10);
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ export const startOidcLogin = async (
|
||||||
identityServerUrl,
|
identityServerUrl,
|
||||||
nonce,
|
nonce,
|
||||||
prompt,
|
prompt,
|
||||||
|
urlState: PlatformPeg.get()?.getOidcClientState(),
|
||||||
});
|
});
|
||||||
|
|
||||||
window.location.href = authorizationUrl;
|
window.location.href = authorizationUrl;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { discoverAndValidateAuthenticationConfig } from "matrix-js-sdk/src/oidc/
|
||||||
import { OidcError } from "matrix-js-sdk/src/oidc/error";
|
import { OidcError } from "matrix-js-sdk/src/oidc/error";
|
||||||
|
|
||||||
import { OidcClientStore } from "../../../src/stores/oidc/OidcClientStore";
|
import { OidcClientStore } from "../../../src/stores/oidc/OidcClientStore";
|
||||||
import { flushPromises, getMockClientWithEventEmitter } from "../../test-utils";
|
import { flushPromises, getMockClientWithEventEmitter, mockPlatformPeg } from "../../test-utils";
|
||||||
import { mockOpenIdConfiguration } from "../../test-utils/oidc";
|
import { mockOpenIdConfiguration } from "../../test-utils/oidc";
|
||||||
|
|
||||||
jest.mock("matrix-js-sdk/src/oidc/discovery", () => ({
|
jest.mock("matrix-js-sdk/src/oidc/discovery", () => ({
|
||||||
|
@ -58,6 +58,7 @@ describe("OidcClientStore", () => {
|
||||||
jest.spyOn(logger, "error").mockClear();
|
jest.spyOn(logger, "error").mockClear();
|
||||||
|
|
||||||
fetchMock.get(`${metadata.issuer}.well-known/openid-configuration`, metadata);
|
fetchMock.get(`${metadata.issuer}.well-known/openid-configuration`, metadata);
|
||||||
|
mockPlatformPeg();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("isUserAuthenticatedWithOidc()", () => {
|
describe("isUserAuthenticatedWithOidc()", () => {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { mocked } from "jest-mock";
|
||||||
import { completeOidcLogin, startOidcLogin } from "../../../src/utils/oidc/authorize";
|
import { completeOidcLogin, startOidcLogin } from "../../../src/utils/oidc/authorize";
|
||||||
import { makeDelegatedAuthConfig } from "../../test-utils/oidc";
|
import { makeDelegatedAuthConfig } from "../../test-utils/oidc";
|
||||||
import { OidcClientError } from "../../../src/utils/oidc/error";
|
import { OidcClientError } from "../../../src/utils/oidc/error";
|
||||||
|
import { mockPlatformPeg } from "../../test-utils";
|
||||||
|
|
||||||
jest.unmock("matrix-js-sdk/src/randomstring");
|
jest.unmock("matrix-js-sdk/src/randomstring");
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ describe("OIDC authorization", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.spyOn(randomStringUtils, "randomString").mockRestore();
|
jest.spyOn(randomStringUtils, "randomString").mockRestore();
|
||||||
|
mockPlatformPeg();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
|
|
Loading…
Reference in a new issue