Adapt OAuth2 implementation to Matrix Spec v1.18 (#34026)
* Adapt OAuth2 implementation to Matrix Spec v1.18 * Handle more cases of oidc->oauth * Fix test * Fix read back of oauth2 context * Iterate * Fix tests * Discard changes to apps/web/playwright/e2e/settings/account-user-settings-tab.spec.ts * Fix test * Fix test * Fix test * Potential fix for pull request finding 'Unused variable, import, function or class' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * Iterate * Iterate * Fix test --------- Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
parent
38e29c51c4
commit
2bc9656957
@@ -9,22 +9,26 @@ import React from "react";
|
||||
import { fireEvent, render, screen, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { DELEGATED_OIDC_COMPATIBILITY, IdentityProviderBrand, type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
OAUTH_AWARE_PREFERRED_FLOW_FIELD,
|
||||
IdentityProviderBrand,
|
||||
type ValidatedAuthMetadata,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import * as Matrix from "matrix-js-sdk/src/matrix";
|
||||
import { OidcError } from "matrix-js-sdk/src/oidc/error";
|
||||
import { OAuth2Error } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import SdkConfig from "../../../../../src/SdkConfig";
|
||||
import { mkServerConfig, mockPlatformPeg, unmockPlatformPeg } from "../../../../test-utils";
|
||||
import Login from "../../../../../src/components/structures/auth/Login";
|
||||
import type BasePlatform from "../../../../../src/BasePlatform";
|
||||
import * as registerClientUtils from "../../../../../src/utils/oidc/registerClient";
|
||||
import { makeDelegatedAuthConfig } from "../../../../test-utils/oidc";
|
||||
import * as registerClientUtils from "../../../../../src/utils/oauth/registerClient";
|
||||
import { makeDelegatedAuthMetadata } from "../../../../test-utils/auth";
|
||||
import { ModuleApi } from "../../../../../src/modules/Api.ts";
|
||||
|
||||
jest.useRealTimers();
|
||||
|
||||
const oidcStaticClientsConfig = {
|
||||
const oauthStaticClientsConfig = {
|
||||
"https://staticallyregisteredissuer.org/": {
|
||||
client_id: "static-clientId-123",
|
||||
},
|
||||
@@ -42,7 +46,7 @@ describe("Login", function () {
|
||||
SdkConfig.put({
|
||||
brand: "test-brand",
|
||||
disable_custom_urls: true,
|
||||
oidc_static_clients: oidcStaticClientsConfig,
|
||||
oidc_static_clients: oauthStaticClientsConfig,
|
||||
});
|
||||
mockClient.login.mockClear().mockResolvedValue({
|
||||
access_token: "TOKEN",
|
||||
@@ -72,7 +76,7 @@ describe("Login", function () {
|
||||
function getRawComponent(
|
||||
hsUrl = "https://matrix.org",
|
||||
isUrl = "https://vector.im",
|
||||
delegatedAuthentication?: OidcClientConfig,
|
||||
delegatedAuthentication?: ValidatedAuthMetadata,
|
||||
) {
|
||||
return (
|
||||
<Login
|
||||
@@ -84,7 +88,7 @@ describe("Login", function () {
|
||||
);
|
||||
}
|
||||
|
||||
function getComponent(hsUrl?: string, isUrl?: string, delegatedAuthentication?: OidcClientConfig) {
|
||||
function getComponent(hsUrl?: string, isUrl?: string, delegatedAuthentication?: ValidatedAuthMetadata) {
|
||||
return render(getRawComponent(hsUrl, isUrl, delegatedAuthentication));
|
||||
}
|
||||
|
||||
@@ -269,7 +273,7 @@ describe("Login", function () {
|
||||
flows: [
|
||||
{
|
||||
type: "m.login.sso",
|
||||
[DELEGATED_OIDC_COMPATIBILITY.name]: true,
|
||||
[OAUTH_AWARE_PREFERRED_FLOW_FIELD.name]: true,
|
||||
},
|
||||
{
|
||||
type: "m.login.password",
|
||||
@@ -393,7 +397,7 @@ describe("Login", function () {
|
||||
const hsUrl = "https://matrix.org";
|
||||
const isUrl = "https://vector.im";
|
||||
const issuer = "https://test.com/";
|
||||
const delegatedAuth = makeDelegatedAuthConfig(issuer);
|
||||
const delegatedAuth = makeDelegatedAuthMetadata(issuer);
|
||||
beforeEach(() => {
|
||||
jest.spyOn(logger, "error");
|
||||
});
|
||||
@@ -402,9 +406,9 @@ describe("Login", function () {
|
||||
jest.spyOn(logger, "error").mockRestore();
|
||||
});
|
||||
|
||||
it("should attempt to register oidc client", async () => {
|
||||
it("should attempt to register oauth client", async () => {
|
||||
// dont mock, spy so we can check config values were correctly passed
|
||||
jest.spyOn(registerClientUtils, "getOidcClientId");
|
||||
jest.spyOn(registerClientUtils, "getOAuthClientId");
|
||||
fetchMock.post(delegatedAuth.registration_endpoint!, { status: 500 });
|
||||
getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
@@ -413,7 +417,7 @@ describe("Login", function () {
|
||||
// tried to register
|
||||
expect(fetchMock).toHaveFetched(delegatedAuth.registration_endpoint);
|
||||
// called with values from config
|
||||
expect(registerClientUtils.getOidcClientId).toHaveBeenCalledWith(delegatedAuth, oidcStaticClientsConfig);
|
||||
expect(registerClientUtils.getOAuthClientId).toHaveBeenCalledWith(delegatedAuth, oauthStaticClientsConfig);
|
||||
});
|
||||
|
||||
it("should fallback to normal login when client registration fails", async () => {
|
||||
@@ -425,8 +429,8 @@ describe("Login", function () {
|
||||
// tried to register
|
||||
expect(fetchMock).toHaveFetched(delegatedAuth.registration_endpoint);
|
||||
expect(logger.error).toHaveBeenCalledWith(
|
||||
"Failed to get oidc native flow",
|
||||
new Error(OidcError.DynamicRegistrationFailed),
|
||||
"Failed to get OAuth2 native flow",
|
||||
new Error(OAuth2Error.DynamicRegistrationFailed),
|
||||
);
|
||||
|
||||
// continued with normal setup
|
||||
@@ -436,7 +440,7 @@ describe("Login", function () {
|
||||
});
|
||||
|
||||
// short term during active development, UI will be added in next PRs
|
||||
it("should show continue button when oidc native flow is correctly configured", async () => {
|
||||
it("should show continue button when oauth native flow is correctly configured", async () => {
|
||||
fetchMock.post(delegatedAuth.registration_endpoint!, { client_id: "abc123" });
|
||||
getComponent(hsUrl, isUrl, delegatedAuth);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import { createClient, type MatrixClient, MatrixError, type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { createClient, type MatrixClient, MatrixError, type ValidatedAuthMetadata } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
@@ -21,11 +21,11 @@ import {
|
||||
unmockPlatformPeg,
|
||||
} from "../../../../test-utils";
|
||||
import Registration from "../../../../../src/components/structures/auth/Registration";
|
||||
import { makeDelegatedAuthConfig } from "../../../../test-utils/oidc";
|
||||
import { startOidcLogin } from "../../../../../src/utils/oidc/authorize";
|
||||
import { makeDelegatedAuthMetadata } from "../../../../test-utils/auth";
|
||||
import { startOAuthLogin } from "../../../../../src/utils/oauth/authorize";
|
||||
|
||||
jest.mock("../../../../../src/utils/oidc/authorize", () => ({
|
||||
startOidcLogin: jest.fn(),
|
||||
jest.mock("../../../../../src/utils/oauth/authorize", () => ({
|
||||
startOAuthLogin: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("matrix-js-sdk/src/matrix", () => ({
|
||||
@@ -92,7 +92,7 @@ describe("Registration", function () {
|
||||
function getRawComponent(
|
||||
hsUrl = defaultHsUrl,
|
||||
isUrl = defaultIsUrl,
|
||||
authConfig?: OidcClientConfig,
|
||||
authConfig?: ValidatedAuthMetadata,
|
||||
mobileRegister?: boolean,
|
||||
) {
|
||||
return (
|
||||
@@ -104,7 +104,12 @@ describe("Registration", function () {
|
||||
);
|
||||
}
|
||||
|
||||
function getComponent(hsUrl?: string, isUrl?: string, authConfig?: OidcClientConfig, mobileRegister?: boolean) {
|
||||
function getComponent(
|
||||
hsUrl?: string,
|
||||
isUrl?: string,
|
||||
authConfig?: ValidatedAuthMetadata,
|
||||
mobileRegister?: boolean,
|
||||
) {
|
||||
return render(getRawComponent(hsUrl, isUrl, authConfig, mobileRegister));
|
||||
}
|
||||
|
||||
@@ -155,7 +160,7 @@ describe("Registration", function () {
|
||||
});
|
||||
|
||||
describe("when delegated authentication is configured and enabled", () => {
|
||||
const authConfig = makeDelegatedAuthConfig();
|
||||
const authConfig = makeDelegatedAuthMetadata();
|
||||
const clientId = "test-client-id";
|
||||
authConfig.prompt_values_supported = ["create"];
|
||||
|
||||
@@ -168,15 +173,6 @@ describe("Registration", function () {
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
fetchMock.get(`${defaultHsUrl}/_matrix/client/unstable/org.matrix.msc2965/auth_issuer`, {
|
||||
issuer: authConfig.issuer,
|
||||
});
|
||||
fetchMock.get("https://auth.org/.well-known/openid-configuration", {
|
||||
...authConfig,
|
||||
signingKeys: undefined,
|
||||
});
|
||||
fetchMock.get(authConfig.jwks_uri!, { keys: [] });
|
||||
});
|
||||
|
||||
it("should display oidc-native continue button", async () => {
|
||||
@@ -194,7 +190,7 @@ describe("Registration", function () {
|
||||
|
||||
fireEvent.click(await screen.findByText("Continue"));
|
||||
|
||||
expect(startOidcLogin).toHaveBeenCalledWith(
|
||||
expect(startOAuthLogin).toHaveBeenCalledWith(
|
||||
authConfig,
|
||||
clientId,
|
||||
defaultHsUrl,
|
||||
|
||||
Reference in New Issue
Block a user