Support for stable MSC4191 account management action parameter (#31701)

* Support for stable MSC4191 account management action parameter

* Pass accountManagementActionsSupported around and refactor name

* Iterate

* Iterate

* Attempt to improve clarity of action fallback

* Use name "actions supported" consistently

* Update test cases for revised default behaviour
This commit is contained in:
Hugh Nimmo-Smith
2026-01-14 14:53:44 +00:00
committed by GitHub
parent 9cc80c5f36
commit 7f408bd6cf
8 changed files with 164 additions and 35 deletions

View File

@@ -26,6 +26,7 @@ describe("OidcClientStore", () => {
const clientId = "test-client-id";
const authConfig = makeDelegatedAuthConfig();
const account = authConfig.issuer + "account";
const accountManagementActionsSupported = ["action1", "action2"];
const mockClient = getMockClientWithEventEmitter({
getAuthMetadata: jest.fn(),
@@ -41,6 +42,7 @@ describe("OidcClientStore", () => {
.mockResolvedValue({
...authConfig,
account_management_uri: account,
account_management_actions_supported: accountManagementActionsSupported,
authorization_endpoint: "authorization-endpoint",
token_endpoint: "token-endpoint",
});
@@ -130,6 +132,15 @@ describe("OidcClientStore", () => {
expect(store.accountManagementEndpoint).toEqual(account);
});
it("should set account management actions supported when configured", async () => {
const store = new OidcClientStore(mockClient);
// @ts-ignore private property
await store.getOidcClient();
expect(store.accountManagementActionsSupported).toEqual(accountManagementActionsSupported);
});
it("should set account management endpoint to issuer when not configured", async () => {
mocked(discoverAndValidateOIDCIssuerWellKnown)
.mockClear()
@@ -244,10 +255,12 @@ describe("OidcClientStore", () => {
mockClient.getAuthMetadata.mockResolvedValue({
...authConfig,
account_management_uri: account,
account_management_actions_supported: accountManagementActionsSupported,
});
const store = new OidcClientStore(mockClient);
await store.readyPromise;
expect(store.accountManagementEndpoint).toBe(account);
expect(store.accountManagementActionsSupported).toEqual(accountManagementActionsSupported);
});
});
});

View File

@@ -0,0 +1,48 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { getManageDeviceUrl } from "../../../../src/utils/oidc/urls";
describe("OIDC urls", () => {
const accountManagementEndpoint = "https://auth.com/manage";
const deviceId = "DEVICEID1234";
describe("getManageDeviceUrl()", () => {
it("prefers stable action", async () => {
expect(
getManageDeviceUrl(
accountManagementEndpoint,
["org.matrix.session_view", "session_view", "org.matrix.device_view"],
deviceId,
),
).toEqual("https://auth.com/manage?action=org.matrix.device_view&device_id=DEVICEID1234");
});
it("defaults to stable action when no known action is supported", async () => {
expect(getManageDeviceUrl(accountManagementEndpoint, [], deviceId)).toEqual(
"https://auth.com/manage?action=org.matrix.device_view&device_id=DEVICEID1234",
);
expect(getManageDeviceUrl(accountManagementEndpoint, ["foo"], deviceId)).toEqual(
"https://auth.com/manage?action=org.matrix.device_view&device_id=DEVICEID1234",
);
});
it("defaults to backwards compatible action when no supported actions are provided", async () => {
expect(getManageDeviceUrl(accountManagementEndpoint, undefined, deviceId)).toEqual(
"https://auth.com/manage?action=org.matrix.session_view&device_id=DEVICEID1234",
);
});
it("uses unstable org.matrix.session_view", async () => {
expect(getManageDeviceUrl(accountManagementEndpoint, ["org.matrix.session_view"], deviceId)).toEqual(
"https://auth.com/manage?action=org.matrix.session_view&device_id=DEVICEID1234",
);
});
it("uses unstable session_view", async () => {
expect(getManageDeviceUrl(accountManagementEndpoint, ["session_view"], deviceId)).toEqual(
"https://auth.com/manage?action=session_view&device_id=DEVICEID1234",
);
});
});
});