From b0966fa45b7a51d1eadf63486acb07d197923138 Mon Sep 17 00:00:00 2001 From: Ian MacFarland Date: Tue, 10 Nov 2020 13:57:37 -0800 Subject: [PATCH] retain original URL when redirecting to/from login --- spotlight-client/src/stores/RootStore.ts | 2 +- spotlight-client/src/stores/UserStore.test.ts | 21 +++++++++++++++++++ spotlight-client/src/stores/UserStore.ts | 21 ++++++++++++------- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/spotlight-client/src/stores/RootStore.ts b/spotlight-client/src/stores/RootStore.ts index e23ee675..242a39f1 100644 --- a/spotlight-client/src/stores/RootStore.ts +++ b/spotlight-client/src/stores/RootStore.ts @@ -27,7 +27,7 @@ export function getAuthSettings(): Auth0ClientOptions | undefined { return { domain: "spotlight-login-staging.recidiviz.org", client_id: "ID9plpd8j4vaUin9rPTGxWlJoknSkDX1", - redirect_uri: `${window.location.protocol}//${window.location.host}`, + redirect_uri: `${window.location.origin}`, }; } return undefined; diff --git a/spotlight-client/src/stores/UserStore.test.ts b/spotlight-client/src/stores/UserStore.test.ts index a3482521..363fc5cb 100644 --- a/spotlight-client/src/stores/UserStore.test.ts +++ b/spotlight-client/src/stores/UserStore.test.ts @@ -87,6 +87,9 @@ test("redirect to Auth0 when unauthenticated", async () => { }); await store.authorize(); expect(mockLoginWithRedirect.mock.calls.length).toBe(1); + expect(mockLoginWithRedirect.mock.calls[0][0]).toEqual({ + appState: { targetUrl: window.location.href }, + }); }); test("requires email verification", async () => { @@ -106,6 +109,7 @@ test("requires email verification", async () => { }); test("handles Auth0 token params", async () => { + mockHandleRedirectCallback.mockResolvedValue({}); const auth0LoginParams = "code=123456&state=abcdef"; const urlWithToken = new URL(window.location.href); urlWithToken.search = `?${auth0LoginParams}`; @@ -123,3 +127,20 @@ test("handles Auth0 token params", async () => { expect(mockHandleRedirectCallback.mock.calls.length).toBe(1); expect(window.location.href).not.toMatch(auth0LoginParams); }); + +test("redirect to targetUrl after callback", async () => { + const targetUrl = "http://localhost/somePage?id=1"; + mockHandleRedirectCallback.mockResolvedValue({ appState: { targetUrl } }); + + const auth0LoginParams = "code=123456&state=abcdef"; + const urlWithToken = new URL(window.location.href); + urlWithToken.search = `?${auth0LoginParams}`; + window.history.pushState({}, "Test", urlWithToken.href); + + const store = new UserStore({ + authSettings: testAuthSettings, + isAuthRequired: true, + }); + await store.authorize(); + expect(window.location.href).toBe(targetUrl); +}); diff --git a/spotlight-client/src/stores/UserStore.ts b/spotlight-client/src/stores/UserStore.ts index 61e505cb..59633f27 100644 --- a/spotlight-client/src/stores/UserStore.ts +++ b/spotlight-client/src/stores/UserStore.ts @@ -88,13 +88,16 @@ export default class UserStore { ignoreQueryPrefix: true, }); if (urlQuery.code && urlQuery.state) { - await auth0.handleRedirectCallback(); - // auth0 params are single-use, must be removed or they'll cause errors - const newUrl = new URL(window.location.href); - delete urlQuery.code; - delete urlQuery.state; - newUrl.search = qs.stringify(urlQuery, { addQueryPrefix: true }); - window.history.replaceState({}, document.title, newUrl.href); + const { appState } = await auth0.handleRedirectCallback(); + // auth0 params are single-use, must be removed from history or they can cause errors + let replacementUrl; + if (appState && appState.targetUrl) { + replacementUrl = appState.targetUrl; + } else { + // strip away all query params just to be safe + replacementUrl = `${window.location.origin}${window.location.pathname}`; + } + window.history.replaceState({}, document.title, replacementUrl); } if (await auth0.isAuthenticated()) { @@ -110,7 +113,9 @@ export default class UserStore { } }); } else { - auth0.loginWithRedirect(); + auth0.loginWithRedirect({ + appState: { targetUrl: window.location.href }, + }); } } }