Skip to content

Commit

Permalink
Switch OIDC primarily to new /auth_metadata API
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Telatynski <[email protected]>
  • Loading branch information
t3chguy committed Jan 17, 2025
1 parent bdd4d82 commit f88789f
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
54 changes: 54 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ limitations under the License.
*/

import { Optional } from "matrix-events-sdk";
import { MetadataService, OidcClientSettingsStore, OidcMetadata } from "oidc-client-ts";

import type { IDeviceKeys, IMegolmSessionData, IOneTimeKey } from "./@types/crypto.ts";
import { ISyncStateData, SetPresence, SyncApi, SyncApiOptions, SyncState } from "./sync.ts";
Expand Down Expand Up @@ -247,6 +248,12 @@ import { ImageInfo } from "./@types/media.ts";
import { Capabilities, ServerCapabilities } from "./serverCapabilities.ts";
import { sha256 } from "./digest.ts";
import { keyFromAuthData } from "./common-crypto/key-passphrase.ts";
import {
discoverAndValidateOIDCIssuerWellKnown,
isValidatedIssuerMetadata,
OidcClientConfig,
validateOIDCIssuerWellKnown,
} from "./oidc/index.ts";

export type Store = IStore;

Expand Down Expand Up @@ -10328,6 +10335,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @returns Resolves: A promise of an object containing the OIDC issuer if configured
* @returns Rejects: when the request fails (module:http-api.MatrixError)
* @experimental - part of MSC2965
* @deprecated in favour of getAuthMetadata
*/
public async getAuthIssuer(): Promise<{
issuer: string;
Expand All @@ -10336,6 +10344,52 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
prefix: ClientPrefix.Unstable + "/org.matrix.msc2965",
});
}

/**
* Discover and validate delegated auth configuration
* - delegated auth issuer openid-configuration is reachable
* - delegated auth issuer openid-configuration is configured correctly for us
* Fetches /auth_metadata falling back to legacy implementation using /auth_issuer followed by
* https://oidc-issuer.example.com/.well-known/openid-configuration and other files linked therein.
* When successful, validated metadata is returned
* @returns validated authentication metadata and optionally signing keys
* @throws when delegated auth config is invalid or unreachable
* @experimental - part of MSC2965
*/
public async getAuthMetadata(): Promise<OidcClientConfig> {
let authMetadata: OidcMetadata | undefined;
try {
authMetadata = await this.http.request<OidcMetadata>(Method.Get, "/auth_metadata", undefined, undefined, {
prefix: ClientPrefix.Unstable + "/org.matrix.msc2965",
});
} catch (e) {
if (e instanceof MatrixError && e.errcode === "M_UNRECOGNIZED") {
const { issuer } = await this.getAuthIssuer();
return discoverAndValidateOIDCIssuerWellKnown(issuer);
}
throw e;
}

const validatedIssuerConfig = validateOIDCIssuerWellKnown(authMetadata);

// create a temporary settings store, so we can use metadata service for discovery
const settings = new OidcClientSettingsStore({
authority: validatedIssuerConfig.issuer,
redirect_uri: "", // Not known yet, this is here to make the type checker happy
client_id: "", // Not known yet, this is here to make the type checker happy
});
const metadataService = new MetadataService(settings);
const metadata = await metadataService.getMetadata();
const signingKeys = (await metadataService.getSigningKeys()) ?? undefined;

isValidatedIssuerMetadata(metadata);

return {
...validatedIssuerConfig,
metadata,
signingKeys,
};
}
}

function getUnstableDelayQueryOpts(delayOpts: SendDelayedEventRequestOpts): QueryDict {
Expand Down
1 change: 1 addition & 0 deletions src/oidc/discovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { OidcClientConfig } from "./index.ts";
* @param issuer - the OIDC issuer as returned by the /auth_issuer API
* @returns validated authentication metadata and optionally signing keys
* @throws when delegated auth config is invalid or unreachable
* @deprecated in favour of {@link MatrixClient#getAuthMetadata}
*/
export const discoverAndValidateOIDCIssuerWellKnown = async (issuer: string): Promise<OidcClientConfig> => {
const issuerOpenIdConfigUrl = new URL(".well-known/openid-configuration", issuer);
Expand Down
3 changes: 3 additions & 0 deletions src/oidc/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { logger } from "../logger.ts";
import { OidcError } from "./error.ts";

export type ValidatedIssuerConfig = {
issuer: string;
authorizationEndpoint: string;
tokenEndpoint: string;
registrationEndpoint?: string;
Expand Down Expand Up @@ -78,6 +79,7 @@ export const validateOIDCIssuerWellKnown = (wellKnown: unknown): ValidatedIssuer
}

const isInvalid = [
requiredStringProperty(wellKnown, "issuer"),
requiredStringProperty(wellKnown, "authorization_endpoint"),
requiredStringProperty(wellKnown, "token_endpoint"),
requiredStringProperty(wellKnown, "revocation_endpoint"),
Expand All @@ -92,6 +94,7 @@ export const validateOIDCIssuerWellKnown = (wellKnown: unknown): ValidatedIssuer

if (!isInvalid) {
return {
issuer: <string>wellKnown["issuer"],
authorizationEndpoint: <string>wellKnown["authorization_endpoint"],
tokenEndpoint: <string>wellKnown["token_endpoint"],
registrationEndpoint: <string>wellKnown["registration_endpoint"],
Expand Down
5 changes: 2 additions & 3 deletions src/rendezvous/MSC4108SignInWithQR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { logger } from "../logger.ts";
import { MSC4108SecureChannel } from "./channels/MSC4108SecureChannel.ts";
import { MatrixError } from "../http-api/index.ts";
import { sleep } from "../utils.ts";
import { DEVICE_CODE_SCOPE, discoverAndValidateOIDCIssuerWellKnown, OidcClientConfig } from "../oidc/index.ts";
import { DEVICE_CODE_SCOPE, OidcClientConfig } from "../oidc/index.ts";
import { CryptoApi } from "../crypto-api/index.ts";

/**
Expand Down Expand Up @@ -189,8 +189,7 @@ export class MSC4108SignInWithQR {
// MSC4108-Flow: NewScanned -send protocols message
let oidcClientConfig: OidcClientConfig | undefined;
try {
const { issuer } = await this.client!.getAuthIssuer();
oidcClientConfig = await discoverAndValidateOIDCIssuerWellKnown(issuer);
oidcClientConfig = await this.client!.getAuthMetadata();
} catch (e) {
logger.error("Failed to discover OIDC metadata", e);
}
Expand Down

0 comments on commit f88789f

Please sign in to comment.