Switch OIDC primarily to new /auth_metadata API (#29019)

* Switch OIDC primarily to new `/auth_metadata` API

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Simplify the world

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-01-22 13:48:28 +00:00
committed by GitHub
parent e1e4d26154
commit ad01218942
17 changed files with 91 additions and 148 deletions

View File

@@ -15,7 +15,7 @@ import { OidcError } from "matrix-js-sdk/src/oidc/error";
import { OidcClientStore } from "../../../../src/stores/oidc/OidcClientStore";
import { flushPromises, getMockClientWithEventEmitter, mockPlatformPeg } from "../../../test-utils";
import { mockOpenIdConfiguration } from "../../../test-utils/oidc";
import { makeDelegatedAuthConfig } from "../../../test-utils/oidc";
jest.mock("matrix-js-sdk/src/matrix", () => ({
...jest.requireActual("matrix-js-sdk/src/matrix"),
@@ -24,28 +24,30 @@ jest.mock("matrix-js-sdk/src/matrix", () => ({
describe("OidcClientStore", () => {
const clientId = "test-client-id";
const metadata = mockOpenIdConfiguration();
const account = metadata.issuer + "account";
const authConfig = makeDelegatedAuthConfig();
const account = authConfig.issuer + "account";
const mockClient = getMockClientWithEventEmitter({
getAuthIssuer: jest.fn(),
getAuthMetadata: jest.fn(),
});
beforeEach(() => {
localStorage.clear();
localStorage.setItem("mx_oidc_client_id", clientId);
localStorage.setItem("mx_oidc_token_issuer", metadata.issuer);
localStorage.setItem("mx_oidc_token_issuer", authConfig.issuer);
mocked(discoverAndValidateOIDCIssuerWellKnown).mockClear().mockResolvedValue({
metadata,
accountManagementEndpoint: account,
authorizationEndpoint: "authorization-endpoint",
tokenEndpoint: "token-endpoint",
});
mocked(discoverAndValidateOIDCIssuerWellKnown)
.mockClear()
.mockResolvedValue({
...authConfig,
account_management_uri: account,
authorization_endpoint: "authorization-endpoint",
token_endpoint: "token-endpoint",
});
jest.spyOn(logger, "error").mockClear();
fetchMock.get(`${metadata.issuer}.well-known/openid-configuration`, metadata);
fetchMock.get(`${metadata.issuer}jwks`, { keys: [] });
fetchMock.get(`${authConfig.issuer}.well-known/openid-configuration`, authConfig);
fetchMock.get(`${authConfig.issuer}jwks`, { keys: [] });
mockPlatformPeg();
});
@@ -116,7 +118,7 @@ describe("OidcClientStore", () => {
const client = await store.getOidcClient();
expect(client?.settings.client_id).toEqual(clientId);
expect(client?.settings.authority).toEqual(metadata.issuer);
expect(client?.settings.authority).toEqual(authConfig.issuer);
});
it("should set account management endpoint when configured", async () => {
@@ -129,17 +131,19 @@ describe("OidcClientStore", () => {
});
it("should set account management endpoint to issuer when not configured", async () => {
mocked(discoverAndValidateOIDCIssuerWellKnown).mockClear().mockResolvedValue({
metadata,
accountManagementEndpoint: undefined,
authorizationEndpoint: "authorization-endpoint",
tokenEndpoint: "token-endpoint",
});
mocked(discoverAndValidateOIDCIssuerWellKnown)
.mockClear()
.mockResolvedValue({
...authConfig,
account_management_uri: undefined,
authorization_endpoint: "authorization-endpoint",
token_endpoint: "token-endpoint",
});
const store = new OidcClientStore(mockClient);
await store.readyPromise;
expect(store.accountManagementEndpoint).toEqual(metadata.issuer);
expect(store.accountManagementEndpoint).toEqual(authConfig.issuer);
});
it("should reuse initialised oidc client", async () => {
@@ -175,7 +179,7 @@ describe("OidcClientStore", () => {
fetchMock.resetHistory();
fetchMock.post(
metadata.revocation_endpoint,
authConfig.revocation_endpoint,
{
status: 200,
},
@@ -197,7 +201,7 @@ describe("OidcClientStore", () => {
await store.revokeTokens(accessToken, refreshToken);
expect(fetchMock).toHaveFetchedTimes(2, metadata.revocation_endpoint);
expect(fetchMock).toHaveFetchedTimes(2, authConfig.revocation_endpoint);
expect(OidcClient.prototype.revokeToken).toHaveBeenCalledWith(accessToken, "access_token");
expect(OidcClient.prototype.revokeToken).toHaveBeenCalledWith(refreshToken, "refresh_token");
});
@@ -206,14 +210,14 @@ describe("OidcClientStore", () => {
// fail once, then succeed
fetchMock
.postOnce(
metadata.revocation_endpoint,
authConfig.revocation_endpoint,
{
status: 404,
},
{ overwriteRoutes: true, sendAsJson: true },
)
.post(
metadata.revocation_endpoint,
authConfig.revocation_endpoint,
{
status: 200,
},
@@ -226,7 +230,7 @@ describe("OidcClientStore", () => {
"Failed to revoke tokens",
);
expect(fetchMock).toHaveFetchedTimes(2, metadata.revocation_endpoint);
expect(fetchMock).toHaveFetchedTimes(2, authConfig.revocation_endpoint);
expect(OidcClient.prototype.revokeToken).toHaveBeenCalledWith(accessToken, "access_token");
});
});
@@ -237,7 +241,10 @@ describe("OidcClientStore", () => {
});
it("should resolve account management endpoint", async () => {
mockClient.getAuthIssuer.mockResolvedValue({ issuer: metadata.issuer });
mockClient.getAuthMetadata.mockResolvedValue({
...authConfig,
account_management_uri: account,
});
const store = new OidcClientStore(mockClient);
await store.readyPromise;
expect(store.accountManagementEndpoint).toBe(account);