From 236fba9bf9caa1cd31076330335c9d7f07db5ffb Mon Sep 17 00:00:00 2001 From: Bill John Tran Date: Mon, 29 Jul 2024 06:12:16 -1000 Subject: [PATCH] Fix/asub 8551 apple signin redirect (#2184) * add localstorage to redirect url * add test for using localhost redirect * fix tests * add location.assign * update tests for login link * revision updates --- .../identity-block/components/login/index.jsx | 31 ++++++-- .../components/login/index.test.jsx | 79 ++++++++++++++----- .../social-sign-on/_children/AppleSignIn.jsx | 26 +++--- .../components/social-sign-on/index.jsx | 4 +- .../features/social-sign-on/default.jsx | 2 +- .../utils/validate-redirect-url.js | 1 + 6 files changed, 101 insertions(+), 42 deletions(-) diff --git a/blocks/identity-block/components/login/index.jsx b/blocks/identity-block/components/login/index.jsx index b72ed773a..1fc61c6ac 100644 --- a/blocks/identity-block/components/login/index.jsx +++ b/blocks/identity-block/components/login/index.jsx @@ -20,6 +20,16 @@ const useLogin = ({ const [isAppleAuthSuccess, setIsAppleAuthSuccess] = useState(false); const { loginByOIDC } = useOIDCLogin(); + const setRedirectUrl = (url) => { + setCurrentRedirectToURL(url); + sessionStorage.setItem('ArcXP_redirectUrl', url); + }; + + const getRedirectURL = () => { + const localStorageRedirectUrl = sessionStorage.getItem('ArcXP_redirectUrl'); + + return redirectQueryParam || localStorageRedirectUrl || currentRedirectToURL; + }; useEffect(() => { const askForloginWithApple = async (code) => { @@ -55,16 +65,17 @@ const useLogin = ({ if (redirectToPreviousPage && document?.referrer) { const redirectUrlLocation = new URL(document.referrer); + let newRedirectUrl = redirectUrlLocation.pathname.includes('/pagebuilder/') + ? redirectURL + : `${redirectUrlLocation.pathname}${redirectUrlLocation.search}`; if (searchParams.has('reset_password')) { - setCurrentRedirectToURL(`${redirectURL}${redirectUrlLocation.search}`); - } else { - const newRedirectUrl = redirectUrlLocation.pathname.includes('/pagebuilder/') - ? redirectURL - : `${redirectUrlLocation.pathname}${redirectUrlLocation.search}`; + newRedirectUrl = `${redirectURL}${redirectUrlLocation.search}`; - setCurrentRedirectToURL(newRedirectUrl); + setRedirectUrl(newRedirectUrl); } + + setRedirectUrl(newRedirectUrl); } }, [redirectQueryParam, redirectToPreviousPage, redirectURL]); @@ -88,7 +99,11 @@ const useLogin = ({ if (isOIDC) { loginByOIDC(); } else { - window.location = redirectQueryParam || validatedLoggedInPageLoc; + const localStorageRedirectUrl = sessionStorage.getItem('ArcXP_redirectUrl'); + const validatedLocalRedirectURL = validateURL(localStorageRedirectUrl); + const newRedirectUrl = redirectQueryParam || validatedLocalRedirectURL || validatedLoggedInPageLoc; + + window.location = newRedirectUrl; } } }; @@ -98,7 +113,7 @@ const useLogin = ({ }, [Identity, redirectQueryParam, loggedInPageLocation, isAdmin, loginByOIDC, isOIDC, isAppleAuthSuccess]); return { - loginRedirect: redirectQueryParam || currentRedirectToURL, + loginRedirect: getRedirectURL(), }; }; diff --git a/blocks/identity-block/components/login/index.test.jsx b/blocks/identity-block/components/login/index.test.jsx index a82ab82b5..6eb70b458 100644 --- a/blocks/identity-block/components/login/index.test.jsx +++ b/blocks/identity-block/components/login/index.test.jsx @@ -32,16 +32,18 @@ const Test = (props) => { ); }; +const windowLocationValues = { + origin: 'http://localhost', + href: 'http://localhost', + search: '', + pathname: '/', +} + describe("useLogin()", () => { beforeEach(() => { Object.defineProperty(window, "location", { writable: true, - value: { - origin: 'http://localhost', - href: 'http://localhost', - search: '', - pathname: '/', - } + value: windowLocationValues, }); useIdentity.mockImplementation(() => ({ isInitialized: true, @@ -64,6 +66,7 @@ describe("useLogin()", () => { it("uses redirect query", async () => { Object.defineProperty(window, "location", { + ...windowLocationValues, writable: true, value: { search: "?test=123&redirect=/new-account/", @@ -97,6 +100,7 @@ describe("useLogin()", () => { Object.defineProperty(window, "location", { writable: true, value: { + ...windowLocationValues, origin: 'http://localhost', href: 'http://localhost', search: '?reset_password=true', @@ -118,13 +122,15 @@ describe("useLogin()", () => { }, })); await render(); - expect(window.location).toBe(`http://localhost${defaultParams.loggedInPageLocation}`); + + expect(window.location).toBe(`http://localhost${defaultParams.redirectURL}`); }); it("replaces potentially unsafe URLs in query param", async () => { Object.defineProperty(window, "location", { writable: true, value: { + ...windowLocationValues, search: "?test=123&redirect=https://somewhere.com", pathname: "/", }, @@ -134,21 +140,23 @@ describe("useLogin()", () => { expect(window.location).toBe("/"); }); - it("replaces potentially unsafe URLs in redirectURL parameter", async () => { - await render(); + it("replaces potentially unsafe URLs in query param", async () => { + Object.defineProperty(window, "location", { + writable: true, + value: { + ...windowLocationValues, + search: "", + pathname: "/", + }, + }); + await render(); fireEvent.click(screen.getByRole("button")); expect(window.location).toBe("/"); }); - it("replaces potentially unsafe URLs in loggedInPageLocation parameter", async () => { - useIdentity.mockImplementation(() => ({ - isInitialized: true, - Identity: { - isLoggedIn: jest.fn(() => true), - getConfig: jest.fn(() => ({})), - }, - })); - await render(); + it("replaces potentially unsafe URLs in redirectURL parameter", async () => { + await render(); + fireEvent.click(screen.getByRole("button")); expect(window.location).toBe("/"); }); @@ -161,6 +169,7 @@ describe("useLogin()", () => { Object.defineProperty(window, "location", { writable: true, value: { + ...windowLocationValues, origin: 'http://localhost', href: 'http://localhost', search: '', @@ -172,4 +181,38 @@ describe("useLogin()", () => { expect(window.location).toBe("/account/"); delete document.referrer; }); + + it("should use redirectUrl from sessionStorage", async () => { + const referrerURL = "http://localhost/featured-articles/"; + Object.defineProperty(document, "referrer", { + value: referrerURL, + configurable: true, + }); + Object.defineProperty(window, "location", { + writable: true, + value: { + ...windowLocationValues, + origin: 'http://localhost', + href: 'http://localhost', + search: '', + pathname: '/' + } + }); + + useIdentity.mockImplementation(() => ({ + isInitialized: true, + Identity: { + isLoggedIn: jest.fn(() => true), + getConfig: jest.fn(() => ({})), + }, + })); + + await render(); + + expect(sessionStorage.getItem("ArcXP_redirectUrl")).toBe('/featured-articles/'); + + fireEvent.click(screen.getByRole("button")); + expect(window.location).toBe("/featured-articles/"); + delete document.referrer; + }); }); diff --git a/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx b/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx index c691bc94e..64c5eaa7e 100644 --- a/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx +++ b/blocks/identity-block/components/social-sign-on/_children/AppleSignIn.jsx @@ -14,19 +14,19 @@ function AppleSignIn({ socialSignOnIn, className }) { const { Identity } = useIdentity(); return ( - + ); } diff --git a/blocks/identity-block/components/social-sign-on/index.jsx b/blocks/identity-block/components/social-sign-on/index.jsx index 1d8e5f6a7..cce4c58d3 100644 --- a/blocks/identity-block/components/social-sign-on/index.jsx +++ b/blocks/identity-block/components/social-sign-on/index.jsx @@ -6,11 +6,11 @@ import AppleSignIn from "./_children/AppleSignIn"; import useSocialSignIn from "./utils/useSocialSignIn"; const SocialSignOn = ({ className, onError, redirectURL, isOIDC, socialSignOnIn }) => { - const { facebookAppId, googleClientId, appleTeamId, appleKeyId, appleUrlToReceiveAuthToken} = useSocialSignIn(redirectURL, isOIDC, socialSignOnIn, onError); + const { facebookAppId, googleClientId, appleTeamId, appleKeyId, appleUrlToReceiveAuthToken } = useSocialSignIn(redirectURL, isOIDC, socialSignOnIn, onError); return (
{googleClientId ? : null} - {facebookAppId ? : null} + {facebookAppId ? : null} {appleTeamId && appleKeyId && appleUrlToReceiveAuthToken ? : null}
); diff --git a/blocks/identity-block/features/social-sign-on/default.jsx b/blocks/identity-block/features/social-sign-on/default.jsx index 6f7a81f80..8c67371c7 100644 --- a/blocks/identity-block/features/social-sign-on/default.jsx +++ b/blocks/identity-block/features/social-sign-on/default.jsx @@ -60,7 +60,7 @@ const SocialSignOnBlock = ({ customFields }) => { return ( - {!hideDiv ?
{phrases.t("identity-block.or")}
: null} + {!hideDiv ?
{phrases.t("identity-block.or")}
: null} { return url; } + sessionStorage.setItem("ArcXP_redirectUrl", "/"); return "/"; };