From 8e7d8b858683e61faf927af2f5afb01198eb1229 Mon Sep 17 00:00:00 2001 From: Brynley McDonald Date: Tue, 8 Oct 2024 17:16:48 +1300 Subject: [PATCH 1/3] Add flag whether to delete state for processSigninResponse --- docs/oidc-client-ts.api.md | 2 +- src/OidcClient.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/oidc-client-ts.api.md b/docs/oidc-client-ts.api.md index 6b4e6e4d..fb538ec2 100644 --- a/docs/oidc-client-ts.api.md +++ b/docs/oidc-client-ts.api.md @@ -346,7 +346,7 @@ export class OidcClient { // (undocumented) processResourceOwnerPasswordCredentials({ username, password, skipUserInfo, extraTokenParams, }: ProcessResourceOwnerPasswordCredentialsArgs): Promise; // (undocumented) - processSigninResponse(url: string, extraHeaders?: Record): Promise; + processSigninResponse(url: string, extraHeaders?: Record, removeState?: boolean): Promise; // (undocumented) processSignoutResponse(url: string): Promise; // (undocumented) diff --git a/src/OidcClient.ts b/src/OidcClient.ts index efab56b8..29f3a7cb 100644 --- a/src/OidcClient.ts +++ b/src/OidcClient.ts @@ -172,10 +172,10 @@ export class OidcClient { return { state, response }; } - public async processSigninResponse(url: string, extraHeaders?: Record): Promise { + public async processSigninResponse(url: string, extraHeaders?: Record, removeState = true): Promise { const logger = this._logger.create("processSigninResponse"); - const { state, response } = await this.readSigninResponseState(url, true); + const { state, response } = await this.readSigninResponseState(url, removeState); logger.debug("received state from storage; validating response"); if (this.settings.dpop && this.settings.dpop.store) { From 6da3e7bf5b12f7274d1ba2d17652708dbbe2a7b7 Mon Sep 17 00:00:00 2001 From: Brynley McDonald Date: Tue, 8 Oct 2024 17:23:15 +1300 Subject: [PATCH 2/3] Add tests --- src/OidcClient.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/OidcClient.test.ts b/src/OidcClient.test.ts index 8ee7b7b6..34e9de2c 100644 --- a/src/OidcClient.test.ts +++ b/src/OidcClient.test.ts @@ -465,6 +465,29 @@ describe("OidcClient", () => { expect(getDpopProofMock).toHaveBeenCalledTimes(2); expect(getDpopProofMock).toHaveBeenNthCalledWith(2, { "_dbName": "oidc", "_storeName": "dpop" }, "some-nonce"); }); + + it("should not delete state when removeState = false", async () => { + // arrange + const item = await SigninState.create({ + id: "1", + authority: "authority", + client_id: "client", + redirect_uri: "http://app/cb", + scope: "scope", + request_type: "type", + }); + const getStateMock = jest.spyOn(subject.settings.stateStore, "get") + .mockImplementation(async () => item.toStorageString()); + const removeStateMock = jest.spyOn(subject.settings.stateStore, "remove").mockImplementation(async () => item.toStorageString()); + jest.spyOn(subject["_validator"], "validateSigninResponse").mockResolvedValue(); + + // act + await subject.processSigninResponse("http://app/cb?state=1", undefined, false); + + // assert + expect(getStateMock).toHaveBeenCalled(); + expect(removeStateMock).not.toHaveBeenCalled(); + }); }); describe("processResourceOwnerPasswordCredentials", () => { From d7291570b3fd171c6912bbb2aad5fac8afcb781c Mon Sep 17 00:00:00 2001 From: Brynley McDonald Date: Tue, 8 Oct 2024 17:37:26 +1300 Subject: [PATCH 3/3] Formatting --- src/OidcClient.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OidcClient.test.ts b/src/OidcClient.test.ts index 34e9de2c..6af0e15a 100644 --- a/src/OidcClient.test.ts +++ b/src/OidcClient.test.ts @@ -478,7 +478,8 @@ describe("OidcClient", () => { }); const getStateMock = jest.spyOn(subject.settings.stateStore, "get") .mockImplementation(async () => item.toStorageString()); - const removeStateMock = jest.spyOn(subject.settings.stateStore, "remove").mockImplementation(async () => item.toStorageString()); + const removeStateMock = jest.spyOn(subject.settings.stateStore, "remove") + .mockImplementation(async () => item.toStorageString()); jest.spyOn(subject["_validator"], "validateSigninResponse").mockResolvedValue(); // act