Repository: authts/oidc-client-ts
Pull request #1038 (2023-06-06 17:22:59)

Fix samples
<!-- Please link relevant issue numbers or provide context for this change -->
Closes/fixes --

- Pass callback URLs to login/logout requests to prevent fatal errors
- Add `client_id` to logout request to prevent fatal errors (tested against Keycloak - either "`id_token_hint`" (already available) or "`client_id`" (missing till now) are required when using `post_logout_redirect_uri`)

### Checklist

- [x] This PR makes changes to the public API
  - [x] Update API report (docs/oidc-client-ts.api.md)
- [x] I have included links for closing relevant issue numbers



Patch:
diff --git a/docs/oidc-client-ts.api.md b/docs/oidc-client-ts.api.md
index 1077f33e..ebbb47a0 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<SigninRequest>;
     // (undocumented)
-    createSignoutRequest({ state, id_token_hint, request_type, post_logout_redirect_uri, extraQueryParams, }?: CreateSignoutRequestArgs): Promise<SignoutRequest>;
+    createSignoutRequest({ state, id_token_hint, client_id, request_type, post_logout_redirect_uri, extraQueryParams, }?: CreateSignoutRequestArgs): Promise<SignoutRequest>;
     // (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<string, string | number | boolean>;
     // (undocumented)
diff --git a/package-lock.json b/package-lock.json
index baf528a5..d0496968 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1447,17 +1447,17 @@
       }
     },
     "node_modules/@microsoft/api-extractor": {
-      "version": "7.35.1",
-      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.35.1.tgz",
-      "integrity": "sha512-xGVf1lKCYKEyJsspLzQjo4Oo6PGDPH95Z5/te75xQWpcRHcfemb6zTSPtiFeVDHkg9Tan5HW2QXGLwQRkW199w==",
+      "version": "7.35.2",
+      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.35.2.tgz",
+      "integrity": "sha512-f3aM4hJkv5W04eLh6wdJ9fzscAmb+GgnT6j+pMlGVyz+0p2yQDndymvgUseFO6a+HqFDSH4yZXmkqT8bP7lVWQ==",
       "dev": true,
       "dependencies": {
-        "@microsoft/api-extractor-model": "7.27.1",
+        "@microsoft/api-extractor-model": "7.27.2",
         "@microsoft/tsdoc": "0.14.2",
         "@microsoft/tsdoc-config": "~0.16.1",
-        "@rushstack/node-core-library": "3.59.2",
-        "@rushstack/rig-package": "0.3.19",
-        "@rushstack/ts-command-line": "4.13.3",
+        "@rushstack/node-core-library": "3.59.3",
+        "@rushstack/rig-package": "0.3.20",
+        "@rushstack/ts-command-line": "4.14.0",
         "colors": "~1.2.1",
         "lodash": "~4.17.15",
         "resolve": "~1.22.1",
@@ -1470,14 +1470,14 @@
       }
     },
     "node_modules/@microsoft/api-extractor-model": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.27.1.tgz",
-      "integrity": "sha512-WgmuQwElTuRLATQxCx+pqk5FtUeRX3FW8WDo7tSDmrN/7+XAggeVg5t8ItiJt688jEdbiPvagZlvjAcJMpXspg==",
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.27.2.tgz",
+      "integrity": "sha512-JWhSfEb4UMYZgI4JsJOws1DjQrb7BaoXoWQV5XW23MWRn1krHVmRHky82Dby5rQPHdr/BBKvEjZV6joFmaGU4Q==",
       "dev": true,
       "dependencies": {
         "@microsoft/tsdoc": "0.14.2",
         "@microsoft/tsdoc-config": "~0.16.1",
-        "@rushstack/node-core-library": "3.59.2"
+        "@rushstack/node-core-library": "3.59.3"
       }
     },
     "node_modules/@microsoft/tsdoc": {
@@ -1544,9 +1544,9 @@
       }
     },
     "node_modules/@rushstack/node-core-library": {
-      "version": "3.59.2",
-      "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.59.2.tgz",
-      "integrity": "sha512-Od8i9ZXiRPHrnkuNOZ9IjEYRQ9JsBLNHlkWJr1wSQZrD2TVIc8APpIB/FnzEcjfpbJMT4XhtcCZaa0pVx+hTXw==",
+      "version": "3.59.3",
+      "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.59.3.tgz",
+      "integrity": "sha512-OGk0nQc+SvDkn+IQN16co691A/96gPoRIoWdIlpUds+sYPAGWdTcNVjKMwFOAsCSASqOeF2lh1GdPtWoWJCkPQ==",
       "dev": true,
       "dependencies": {
         "colors": "~1.2.1",
@@ -1567,9 +1567,9 @@
       }
     },
     "node_modules/@rushstack/rig-package": {
-      "version": "0.3.19",
-      "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.19.tgz",
-      "integrity": "sha512-2d0/Gn+qjOYneZbiHjn4SjyDwq9I0WagV37z0F1V71G+yONgH7wlt3K/UoNiDkhA8gTHYPRo2jz3CvttybwSag==",
+      "version": "0.3.20",
+      "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.20.tgz",
+      "integrity": "sha512-XemFRFbH9FOk1Es1kTjrYydenf3hXtrV3xxMCEWPuOSn2Lcll/dsLzEULbhCL0Nf5nGMe52ewEiVtX3odd5Ukg==",
       "dev": true,
       "dependencies": {
         "resolve": "~1.22.1",
@@ -1577,9 +1577,9 @@
       }
     },
     "node_modules/@rushstack/ts-command-line": {
-      "version": "4.13.3",
-      "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.13.3.tgz",
-      "integrity": "sha512-6aQIv/o1EgsC/+SpgUyRmzg2QIAL6sudEzw3sWzJKwWuQTc5XRsyZpyldfE7WAmIqMXDao9QG35/NYORjHm5Zw==",
+      "version": "4.14.0",
+      "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.14.0.tgz",
+      "integrity": "sha512-DWozCsKg+ALgrsul+6vJhyB7ZogqSycRlnqULjGsJ9dLRv+Pc0Wj6J7pX0xarmgX2kH3tTf0rXgBcl8QjJULIQ==",
       "dev": true,
       "dependencies": {
         "@types/argparse": "1.0.38",
@@ -7938,17 +7938,17 @@
       }
     },
     "@microsoft/api-extractor": {
-      "version": "7.35.1",
-      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.35.1.tgz",
-      "integrity": "sha512-xGVf1lKCYKEyJsspLzQjo4Oo6PGDPH95Z5/te75xQWpcRHcfemb6zTSPtiFeVDHkg9Tan5HW2QXGLwQRkW199w==",
+      "version": "7.35.2",
+      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.35.2.tgz",
+      "integrity": "sha512-f3aM4hJkv5W04eLh6wdJ9fzscAmb+GgnT6j+pMlGVyz+0p2yQDndymvgUseFO6a+HqFDSH4yZXmkqT8bP7lVWQ==",
       "dev": true,
       "requires": {
-        "@microsoft/api-extractor-model": "7.27.1",
+        "@microsoft/api-extractor-model": "7.27.2",
         "@microsoft/tsdoc": "0.14.2",
         "@microsoft/tsdoc-config": "~0.16.1",
-        "@rushstack/node-core-library": "3.59.2",
-        "@rushstack/rig-package": "0.3.19",
-        "@rushstack/ts-command-line": "4.13.3",
+        "@rushstack/node-core-library": "3.59.3",
+        "@rushstack/rig-package": "0.3.20",
+        "@rushstack/ts-command-line": "4.14.0",
         "colors": "~1.2.1",
         "lodash": "~4.17.15",
         "resolve": "~1.22.1",
@@ -7958,14 +7958,14 @@
       }
     },
     "@microsoft/api-extractor-model": {
-      "version": "7.27.1",
-      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.27.1.tgz",
-      "integrity": "sha512-WgmuQwElTuRLATQxCx+pqk5FtUeRX3FW8WDo7tSDmrN/7+XAggeVg5t8ItiJt688jEdbiPvagZlvjAcJMpXspg==",
+      "version": "7.27.2",
+      "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.27.2.tgz",
+      "integrity": "sha512-JWhSfEb4UMYZgI4JsJOws1DjQrb7BaoXoWQV5XW23MWRn1krHVmRHky82Dby5rQPHdr/BBKvEjZV6joFmaGU4Q==",
       "dev": true,
       "requires": {
         "@microsoft/tsdoc": "0.14.2",
         "@microsoft/tsdoc-config": "~0.16.1",
-        "@rushstack/node-core-library": "3.59.2"
+        "@rushstack/node-core-library": "3.59.3"
       }
     },
     "@microsoft/tsdoc": {
@@ -8022,9 +8022,9 @@
       }
     },
     "@rushstack/node-core-library": {
-      "version": "3.59.2",
-      "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.59.2.tgz",
-      "integrity": "sha512-Od8i9ZXiRPHrnkuNOZ9IjEYRQ9JsBLNHlkWJr1wSQZrD2TVIc8APpIB/FnzEcjfpbJMT4XhtcCZaa0pVx+hTXw==",
+      "version": "3.59.3",
+      "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.59.3.tgz",
+      "integrity": "sha512-OGk0nQc+SvDkn+IQN16co691A/96gPoRIoWdIlpUds+sYPAGWdTcNVjKMwFOAsCSASqOeF2lh1GdPtWoWJCkPQ==",
       "dev": true,
       "requires": {
         "colors": "~1.2.1",
@@ -8037,9 +8037,9 @@
       }
     },
     "@rushstack/rig-package": {
-      "version": "0.3.19",
-      "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.19.tgz",
-      "integrity": "sha512-2d0/Gn+qjOYneZbiHjn4SjyDwq9I0WagV37z0F1V71G+yONgH7wlt3K/UoNiDkhA8gTHYPRo2jz3CvttybwSag==",
+      "version": "0.3.20",
+      "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.3.20.tgz",
+      "integrity": "sha512-XemFRFbH9FOk1Es1kTjrYydenf3hXtrV3xxMCEWPuOSn2Lcll/dsLzEULbhCL0Nf5nGMe52ewEiVtX3odd5Ukg==",
       "dev": true,
       "requires": {
         "resolve": "~1.22.1",
@@ -8047,9 +8047,9 @@
       }
     },
     "@rushstack/ts-command-line": {
-      "version": "4.13.3",
-      "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.13.3.tgz",
-      "integrity": "sha512-6aQIv/o1EgsC/+SpgUyRmzg2QIAL6sudEzw3sWzJKwWuQTc5XRsyZpyldfE7WAmIqMXDao9QG35/NYORjHm5Zw==",
+      "version": "4.14.0",
+      "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.14.0.tgz",
+      "integrity": "sha512-DWozCsKg+ALgrsul+6vJhyB7ZogqSycRlnqULjGsJ9dLRv+Pc0Wj6J7pX0xarmgX2kH3tTf0rXgBcl8QjJULIQ==",
       "dev": true,
       "requires": {
         "@types/argparse": "1.0.38",
diff --git a/samples/Parcel/src/oidc-client/sample.js b/samples/Parcel/src/oidc-client/sample.js
index e20c403f..a63bf52a 100644
--- a/samples/Parcel/src/oidc-client/sample.js
+++ b/samples/Parcel/src/oidc-client/sample.js
@@ -49,7 +49,7 @@ function signin() {
 
 var signinResponse;
 function processSigninResponse() {
-    client.processSigninResponse().then(function(response) {
+    client.processSigninResponse(window.location.href).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, "<a href='" + req.url + "'>go signout</a>");
         if (followLinks()) {
             window.location = req.url;
@@ -68,7 +68,7 @@ function signout() {
 }
 
 function processSignoutResponse() {
-    client.processSignoutResponse().then(function(response) {
+    client.processSignoutResponse(window.location.href).then(function(response) {
         signinResponse = null;
         log("signout response", response);
     }).catch(function(err) {
diff --git a/src/OidcClient.ts b/src/OidcClient.ts
index cb3846c7..777a8b92 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,
@@ -232,9 +233,15 @@ 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,
+            client_id,
             post_logout_redirect_uri,
             state_data: state,
             extraQueryParams,
diff --git a/src/SignoutRequest.ts b/src/SignoutRequest.ts
index 4cb71830..a310f7dc 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<string, string | number | boolean>;
 
@@ -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);


Test patch:
diff --git a/src/OidcClient.test.ts b/src/OidcClient.test.ts
index d7968044..04fed861 100644
--- a/src/OidcClient.test.ts
+++ b/src/OidcClient.test.ts
@@ -563,6 +563,45 @@ describe("OidcClient", () => {
             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;
+            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;
+            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"));