From 08d2c445ef4920c5a7deb3218988d987e197658c Mon Sep 17 00:00:00 2001 From: Per Guth Date: Tue, 6 Jun 2023 17:17:52 +0000 Subject: [PATCH 1/5] Pass URLs and client_id --- samples/Parcel/src/oidc-client/sample.js | 14 +++++++------- src/OidcClient.ts | 2 ++ src/SignoutRequest.ts | 6 +++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/samples/Parcel/src/oidc-client/sample.js b/samples/Parcel/src/oidc-client/sample.js index e20c403f3..269a07f9e 100644 --- a/samples/Parcel/src/oidc-client/sample.js +++ b/samples/Parcel/src/oidc-client/sample.js @@ -48,8 +48,8 @@ function signin() { } var signinResponse; -function processSigninResponse() { - client.processSigninResponse().then(function(response) { +function processSigninResponse(url) { + client.processSigninResponse(url).then(function(response) { signinResponse = response; log("signin response", signinResponse); }).catch(function(err) { @@ -59,7 +59,7 @@ function processSigninResponse() { } function signout() { - client.createSignoutRequest({ state: { foo: 5 } }).then(function(req) { + client.createSignoutRequest({ state: { foo: 5 }, client_id: settings.client_id }).then(function(req) { log("signout request", req, "go signout"); if (followLinks()) { window.location = req.url; @@ -67,8 +67,8 @@ function signout() { }); } -function processSignoutResponse() { - client.processSignoutResponse().then(function(response) { +function processSignoutResponse(url) { + client.processSignoutResponse(url).then(function(response) { signinResponse = null; log("signout response", response); }).catch(function(err) { @@ -99,10 +99,10 @@ document.getElementById("processSignout").style.display = display; if (followLinks()) { if (window.location.href.indexOf("#") >= 0) { - processSigninResponse(); + processSigninResponse(window.location.href); } else if (window.location.href.indexOf("?") >= 0) { - processSignoutResponse(); + processSignoutResponse(window.location.href); } } diff --git a/src/OidcClient.ts b/src/OidcClient.ts index cb3846c74..0d1a56533 100644 --- a/src/OidcClient.ts +++ b/src/OidcClient.ts @@ -218,6 +218,7 @@ export class OidcClient { public async createSignoutRequest({ state, id_token_hint, + client_id, request_type, post_logout_redirect_uri = this.settings.post_logout_redirect_uri, extraQueryParams = this.settings.extraQueryParams, @@ -235,6 +236,7 @@ export class OidcClient { const request = new SignoutRequest({ url, id_token_hint, + client_id, post_logout_redirect_uri, state_data: state, extraQueryParams, diff --git a/src/SignoutRequest.ts b/src/SignoutRequest.ts index 4cb718300..a310f7dc6 100644 --- a/src/SignoutRequest.ts +++ b/src/SignoutRequest.ts @@ -14,6 +14,7 @@ export interface SignoutRequestArgs { // optional id_token_hint?: string; + client_id?: string; post_logout_redirect_uri?: string; extraQueryParams?: Record; @@ -34,7 +35,7 @@ export class SignoutRequest { public constructor({ url, - state_data, id_token_hint, post_logout_redirect_uri, extraQueryParams, request_type, + state_data, id_token_hint, post_logout_redirect_uri, extraQueryParams, request_type, client_id, }: SignoutRequestArgs) { if (!url) { this._logger.error("ctor: No url passed"); @@ -45,6 +46,9 @@ export class SignoutRequest { if (id_token_hint) { parsedUrl.searchParams.append("id_token_hint", id_token_hint); } + if (client_id) { + parsedUrl.searchParams.append("client_id", client_id); + } if (post_logout_redirect_uri) { parsedUrl.searchParams.append("post_logout_redirect_uri", post_logout_redirect_uri); From b6e91007475a6a3c2f00cbe3363db8ae434184ac Mon Sep 17 00:00:00 2001 From: Per Guth Date: Tue, 6 Jun 2023 17:27:51 +0000 Subject: [PATCH 2/5] Regenerate docs --- docs/oidc-client-ts.api.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/oidc-client-ts.api.md b/docs/oidc-client-ts.api.md index 1077f33e6..ebbb47a02 100644 --- a/docs/oidc-client-ts.api.md +++ b/docs/oidc-client-ts.api.md @@ -265,7 +265,7 @@ export class OidcClient { // (undocumented) createSigninRequest({ state, request, request_uri, request_type, id_token_hint, login_hint, skipUserInfo, nonce, response_type, scope, redirect_uri, prompt, display, max_age, ui_locales, acr_values, resource, response_mode, extraQueryParams, extraTokenParams, }: CreateSigninRequestArgs): Promise; // (undocumented) - createSignoutRequest({ state, id_token_hint, request_type, post_logout_redirect_uri, extraQueryParams, }?: CreateSignoutRequestArgs): Promise; + createSignoutRequest({ state, id_token_hint, client_id, request_type, post_logout_redirect_uri, extraQueryParams, }?: CreateSignoutRequestArgs): Promise; // (undocumented) protected readonly _logger: Logger; // (undocumented) @@ -720,7 +720,7 @@ export type SignoutRedirectArgs = RedirectParams & ExtraSignoutRequestArgs; // @public (undocumented) export class SignoutRequest { - constructor({ url, state_data, id_token_hint, post_logout_redirect_uri, extraQueryParams, request_type, }: SignoutRequestArgs); + constructor({ url, state_data, id_token_hint, post_logout_redirect_uri, extraQueryParams, request_type, client_id, }: SignoutRequestArgs); // (undocumented) readonly state?: State; // (undocumented) @@ -729,6 +729,8 @@ export class SignoutRequest { // @public (undocumented) export interface SignoutRequestArgs { + // (undocumented) + client_id?: string; // (undocumented) extraQueryParams?: Record; // (undocumented) From 491eba470fe030c7c375babd7175f0bda1930181 Mon Sep 17 00:00:00 2001 From: Per Guth Date: Sat, 10 Jun 2023 15:18:09 +0000 Subject: [PATCH 3/5] Set client_id as fallback; add tests --- src/OidcClient.test.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ src/OidcClient.ts | 5 +++++ 2 files changed, 47 insertions(+) diff --git a/src/OidcClient.test.ts b/src/OidcClient.test.ts index d79680444..29ca76403 100644 --- a/src/OidcClient.test.ts +++ b/src/OidcClient.test.ts @@ -558,11 +558,53 @@ describe("OidcClient", () => { expect(request.state).toBeDefined(); expect(request.state?.data).toEqual("foo"); const url = request.url; + console.log("url", url); expect(url).toContain("http://sts/signout"); expect(url).toContain("post_logout_redirect_uri=bar"); expect(url).toContain("id_token_hint=baz"); }); + it("should pass params to SignoutRequest w/o id_token_hint and client_id", async () => { + // arrange + jest.spyOn(subject.metadataService, "getEndSessionEndpoint").mockImplementation(() => Promise.resolve("http://sts/signout")); + + // act + const request = await subject.createSignoutRequest({ + state: "foo", + post_logout_redirect_uri: "bar", + }); + + // assert + expect(request.state).toBeDefined(); + expect(request.state?.data).toEqual("foo"); + const url = request.url; + console.log("url", url); + expect(url).toContain("http://sts/signout"); + expect(url).toContain("post_logout_redirect_uri=bar"); + expect(url).toContain("client_id=client"); + }); + + it("should pass params to SignoutRequest with client_id", async () => { + // arrange + jest.spyOn(subject.metadataService, "getEndSessionEndpoint").mockImplementation(() => Promise.resolve("http://sts/signout")); + + // act + const request = await subject.createSignoutRequest({ + state: "foo", + post_logout_redirect_uri: "bar", + client_id: "baz", + }); + + // assert + expect(request.state).toBeDefined(); + expect(request.state?.data).toEqual("foo"); + const url = request.url; + console.log("url", url); + expect(url).toContain("http://sts/signout"); + expect(url).toContain("post_logout_redirect_uri=bar"); + expect(url).toContain("client_id=baz"); + }); + it("should fail if metadata fails", async () => { // arrange jest.spyOn(subject.metadataService, "getEndSessionEndpoint").mockRejectedValue(new Error("test")); diff --git a/src/OidcClient.ts b/src/OidcClient.ts index 0d1a56533..777a8b923 100644 --- a/src/OidcClient.ts +++ b/src/OidcClient.ts @@ -233,6 +233,11 @@ export class OidcClient { logger.debug("Received end session endpoint", url); + // specify the client identifier when post_logout_redirect_uri is used but id_token_hint is not + if (!client_id && post_logout_redirect_uri && !id_token_hint) { + client_id = this.settings.client_id; + } + const request = new SignoutRequest({ url, id_token_hint, From 097b3974a9fa9a6ef77ea3f94a9abb05ea5cb680 Mon Sep 17 00:00:00 2001 From: Per Guth Date: Sat, 10 Jun 2023 17:20:56 +0200 Subject: [PATCH 4/5] Apply suggestions from code review Remove logs --- src/OidcClient.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/OidcClient.test.ts b/src/OidcClient.test.ts index 29ca76403..04fed8610 100644 --- a/src/OidcClient.test.ts +++ b/src/OidcClient.test.ts @@ -558,7 +558,6 @@ describe("OidcClient", () => { expect(request.state).toBeDefined(); expect(request.state?.data).toEqual("foo"); const url = request.url; - console.log("url", url); expect(url).toContain("http://sts/signout"); expect(url).toContain("post_logout_redirect_uri=bar"); expect(url).toContain("id_token_hint=baz"); @@ -578,7 +577,6 @@ describe("OidcClient", () => { expect(request.state).toBeDefined(); expect(request.state?.data).toEqual("foo"); const url = request.url; - console.log("url", url); expect(url).toContain("http://sts/signout"); expect(url).toContain("post_logout_redirect_uri=bar"); expect(url).toContain("client_id=client"); @@ -599,7 +597,6 @@ describe("OidcClient", () => { expect(request.state).toBeDefined(); expect(request.state?.data).toEqual("foo"); const url = request.url; - console.log("url", url); expect(url).toContain("http://sts/signout"); expect(url).toContain("post_logout_redirect_uri=bar"); expect(url).toContain("client_id=baz"); From 674b21eac83fea60506541afdf9751afd6666c75 Mon Sep 17 00:00:00 2001 From: Per Guth Date: Sun, 11 Jun 2023 15:41:25 +0000 Subject: [PATCH 5/5] Properly determine URL The listeners in line 9-13 are passing in an event object as first parameter. So the previous code worked when using the `followLinks` flow but not the manual one. --- samples/Parcel/src/oidc-client/sample.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/Parcel/src/oidc-client/sample.js b/samples/Parcel/src/oidc-client/sample.js index 269a07f9e..a63bf52a8 100644 --- a/samples/Parcel/src/oidc-client/sample.js +++ b/samples/Parcel/src/oidc-client/sample.js @@ -48,8 +48,8 @@ function signin() { } var signinResponse; -function processSigninResponse(url) { - client.processSigninResponse(url).then(function(response) { +function processSigninResponse() { + client.processSigninResponse(window.location.href).then(function(response) { signinResponse = response; log("signin response", signinResponse); }).catch(function(err) { @@ -67,8 +67,8 @@ function signout() { }); } -function processSignoutResponse(url) { - client.processSignoutResponse(url).then(function(response) { +function processSignoutResponse() { + client.processSignoutResponse(window.location.href).then(function(response) { signinResponse = null; log("signout response", response); }).catch(function(err) { @@ -99,10 +99,10 @@ document.getElementById("processSignout").style.display = display; if (followLinks()) { if (window.location.href.indexOf("#") >= 0) { - processSigninResponse(window.location.href); + processSigninResponse(); } else if (window.location.href.indexOf("?") >= 0) { - processSignoutResponse(window.location.href); + processSignoutResponse(); } }