diff --git a/src/domain/navigation/URLRouter.ts b/src/domain/navigation/URLRouter.ts index dbd1ceeefe..a52f71a05c 100644 --- a/src/domain/navigation/URLRouter.ts +++ b/src/domain/navigation/URLRouter.ts @@ -32,6 +32,9 @@ export interface IURLRouter { urlForPath(path: Path): string; openRoomActionUrl(roomId: string): string; createSSOCallbackURL(): string; + createOIDCRedirectURL(): string; + absoluteAppUrl(): string; + absoluteUrlForAsset(asset: string): string; normalizeUrl(): void; } diff --git a/src/domain/navigation/index.ts b/src/domain/navigation/index.ts index 4801d9fae6..8ff0aa0b37 100644 --- a/src/domain/navigation/index.ts +++ b/src/domain/navigation/index.ts @@ -33,8 +33,16 @@ export type SegmentType = { "details": true; "members": true; "member": string; - "oidc-callback": (string | null)[]; - "oidc-error": (string | null)[]; + "oidc": { + state: string, + } & + ({ + code: string, + } | { + error: string, + errorDescription: string | null, + errorUri: string | null , + }); }; export function createNavigation(): Navigation { @@ -131,18 +139,21 @@ export function parseUrlPath(urlPath: string, currentNavPath: Path, // Special case for OIDC callback if (urlPath.includes("state")) { const params = new URLSearchParams(urlPath); - if (params.has("state")) { + const state = params.get("state"); + const code = params.get("code"); + const error = params.get("error"); + if (state) { // This is a proper OIDC callback - if (params.has("code")) { + if (code) { segments.push(new Segment("oidc", { - state: params.get("state"), - code: params.get("code"), + state, + code, })); return segments; - } else if (params.has("error")) { + } else if (error) { segments.push(new Segment("oidc", { - state: params.get("state"), - error: params.get("error"), + state, + error, errorDescription: params.get("error_description"), errorUri: params.get("error_uri"), })); @@ -514,19 +525,22 @@ export function tests() { assert.equal(newPath?.segments[1].value, "b"); }, "Parse OIDC callback": assert => { - const segments = parseUrlPath("state=tc9CnLU7&code=cnmUnwIYtY7V8RrWUyhJa4yvX72jJ5Yx"); + const path = createEmptyPath(); + const segments = parseUrlPath("state=tc9CnLU7&code=cnmUnwIYtY7V8RrWUyhJa4yvX72jJ5Yx", path); assert.equal(segments.length, 1); assert.equal(segments[0].type, "oidc"); assert.deepEqual(segments[0].value, {state: "tc9CnLU7", code: "cnmUnwIYtY7V8RrWUyhJa4yvX72jJ5Yx"}); }, "Parse OIDC error": assert => { - const segments = parseUrlPath("state=tc9CnLU7&error=invalid_request"); + const path = createEmptyPath(); + const segments = parseUrlPath("state=tc9CnLU7&error=invalid_request", path); assert.equal(segments.length, 1); assert.equal(segments[0].type, "oidc"); assert.deepEqual(segments[0].value, {state: "tc9CnLU7", error: "invalid_request", errorUri: null, errorDescription: null}); }, "Parse OIDC error with description": assert => { - const segments = parseUrlPath("state=tc9CnLU7&error=invalid_request&error_description=Unsupported%20response_type%20value"); + const path = createEmptyPath(); + const segments = parseUrlPath("state=tc9CnLU7&error=invalid_request&error_description=Unsupported%20response_type%20value", path); assert.equal(segments.length, 1); assert.equal(segments[0].type, "oidc"); assert.deepEqual(segments[0].value, {state: "tc9CnLU7", error: "invalid_request", errorDescription: "Unsupported response_type value", errorUri: null}); diff --git a/src/matrix/net/OidcApi.ts b/src/matrix/net/OidcApi.ts index 103aae82b3..b3bfd8170f 100644 --- a/src/matrix/net/OidcApi.ts +++ b/src/matrix/net/OidcApi.ts @@ -15,7 +15,8 @@ limitations under the License. */ import type {RequestFunction} from "../../platform/types/types"; -import type {URLRouter} from "../../domain/navigation/URLRouter.js"; +import type {IURLRouter} from "../../domain/navigation/URLRouter.js"; +import type {SegmentType} from "../../domain/navigation"; const WELL_KNOWN = ".well-known/openid-configuration"; @@ -69,12 +70,12 @@ const clientIds: Record = { }, }; -export class OidcApi { +export class OidcApi { _issuer: string; _requestFn: RequestFunction; _encoding: any; _crypto: any; - _urlCreator: URLRouter; + _urlCreator: IURLRouter; _metadataPromise: Promise; _registrationPromise: Promise;