From 6ab6682b489b6410105f4d792621229c3737f330 Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Tue, 29 Oct 2024 17:53:14 -0700 Subject: [PATCH 1/2] PORTALS-3299 --- apps/SageAccountWeb/src/App.tsx | 2 +- .../src/AppInitializer.tsx | 1 - apps/synapse-oauth-signin/src/OAuth2Form.tsx | 5 ++++ .../src/components/RedirectToURL.tsx | 1 - .../src/components/RedirectWithQuery.tsx | 1 - .../src/utils/AppUtils/AppUtils.ts | 27 ++++++++++++------- .../session/ApplicationSessionManager.tsx | 6 ++--- 7 files changed, 26 insertions(+), 17 deletions(-) diff --git a/apps/SageAccountWeb/src/App.tsx b/apps/SageAccountWeb/src/App.tsx index 644f052f13..a7558cad6a 100644 --- a/apps/SageAccountWeb/src/App.tsx +++ b/apps/SageAccountWeb/src/App.tsx @@ -53,7 +53,7 @@ function LoggedInRedirector() { // take user back to page they came from in the source app, if stored in a cookie const isProcessed = processRedirectURLInOneSage() if (!isProcessed && appContext?.redirectURL) { - // if not in the cookie, take them to + // if not in the cookie, take them to the app redirect URL window.location.replace(appContext?.redirectURL) } } diff --git a/apps/synapse-oauth-signin/src/AppInitializer.tsx b/apps/synapse-oauth-signin/src/AppInitializer.tsx index 8b7adff464..7f85260c64 100644 --- a/apps/synapse-oauth-signin/src/AppInitializer.tsx +++ b/apps/synapse-oauth-signin/src/AppInitializer.tsx @@ -25,7 +25,6 @@ function AppInitializer( if (!accountSitePrompted && maxAgeURLParam && parseInt(maxAgeURLParam)) { maxAge = parseInt(maxAgeURLParam) } - const clientId = urlSearchParams.get('client_id') ?? undefined useEffect(() => { diff --git a/apps/synapse-oauth-signin/src/OAuth2Form.tsx b/apps/synapse-oauth-signin/src/OAuth2Form.tsx index 04d9914568..8be076d5e4 100644 --- a/apps/synapse-oauth-signin/src/OAuth2Form.tsx +++ b/apps/synapse-oauth-signin/src/OAuth2Form.tsx @@ -28,7 +28,9 @@ import { import { OAuthClientError } from './OAuthClientError' import { StyledInnerContainer } from './StyledInnerContainer' import { getStateParam, handleErrorRedirect } from './URLUtils' +import UniversalCookies from 'universal-cookie' +const cookies = new UniversalCookies() const sendGTagEvent = (event: string) => { // send event to Google Analytics // (casting to 'any' type to get compile-time access to gtag()) @@ -197,6 +199,9 @@ export function OAuth2Form() { // done! redirect with access code. setShowPendingRedirectUI(true) const redirectUri = queryParams.get('redirect_uri')! + cookies.remove( + SynapseConstants.ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, + ) redirectToURL( `${redirectUri}?${getStateParam()}code=${encodeURIComponent( accessCode.access_code, diff --git a/apps/synapse-portal-framework/src/components/RedirectToURL.tsx b/apps/synapse-portal-framework/src/components/RedirectToURL.tsx index e8fee6b6f1..96c94e2bf9 100644 --- a/apps/synapse-portal-framework/src/components/RedirectToURL.tsx +++ b/apps/synapse-portal-framework/src/components/RedirectToURL.tsx @@ -17,7 +17,6 @@ export default function RedirectToURL(props: RedirectToURLProps) { const { toURL, search } = props const isSearchMatch = search == undefined ? true : `?${search}` == currentSearch - if (isSearchMatch) { window.location.replace(toURL) } diff --git a/apps/synapse-portal-framework/src/components/RedirectWithQuery.tsx b/apps/synapse-portal-framework/src/components/RedirectWithQuery.tsx index 1b23df21ae..b20f71a2a3 100644 --- a/apps/synapse-portal-framework/src/components/RedirectWithQuery.tsx +++ b/apps/synapse-portal-framework/src/components/RedirectWithQuery.tsx @@ -9,7 +9,6 @@ import { Redirect, RedirectProps, useLocation } from 'react-router-dom' export default function RedirectWithQuery(props: RedirectProps) { const { search } = useLocation() const hash = window.location.hash - return ( { + return window.location.hostname.toLowerCase().endsWith('.synapse.org') ? '.synapse.org' : undefined +} +export function storeRedirectURLForOneSageLoginAndGotoURL(href: string) { + // save current URL in a cookie that One Sage will use to send you back to the correct page const twoHoursFromNow = new Date() twoHoursFromNow.setTime(twoHoursFromNow.getTime() + 60 * 60 * 1000) cookies.set(ONE_SAGE_REDIRECT_COOKIE_KEY, window.location.href, { path: '/', - domain: domainValue, + domain: getCookieDomain(), expires: twoHoursFromNow, }) setTimeout(() => { @@ -39,17 +39,24 @@ export function processRedirectURLInOneSage() { // PORTALS-3299 : Indicate that we have completed the login workflow (cookie expires in a minute) to break out of a cycle const expireDate = new Date() expireDate.setMinutes(expireDate.getMinutes() + 1) - const hostname = window.location.hostname.toLowerCase() cookies.set(ACCOUNT_SITE_PROMPTED_FOR_LOGIN_COOKIE_KEY, 'true', { path: '/', expires: expireDate, - domain: hostname.endsWith('.synapse.org') ? 'synapse.org' : undefined, + domain: getCookieDomain(), }) if (cookies.get(ONE_SAGE_REDIRECT_COOKIE_KEY)) { const href = cookies.get(ONE_SAGE_REDIRECT_COOKIE_KEY) - cookies.remove(ONE_SAGE_REDIRECT_COOKIE_KEY) - window.location.assign(href) + // instead of removing, set the expiration to 10 seconds to avoid race condition with SageAccountWeb LoggedInRedirector + const tenSecondsFromNow = new Date() + tenSecondsFromNow.setTime(tenSecondsFromNow.getTime() + 10 * 1000) + cookies.set(ONE_SAGE_REDIRECT_COOKIE_KEY, href, { + path: '/', + domain: getCookieDomain(), + expires: tenSecondsFromNow, + }) + + window.location.replace(href) return true } //else diff --git a/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSessionManager.tsx b/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSessionManager.tsx index c5e1a4000a..0cf9788716 100644 --- a/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSessionManager.tsx +++ b/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSessionManager.tsx @@ -91,7 +91,7 @@ export function ApplicationSessionManager( initAnonymousUserState() return } - if (maxAge) { + if (maxAge !== undefined && !!token) { // SWC-5597: if max_age is defined, then return if the user last authenticated more than max_age seconds ago const authenticatedOnResponse = await SynapseClient.getAuthenticatedOn( token, @@ -101,8 +101,8 @@ export function ApplicationSessionManager( ) const now = dayjs.utc() if (now.diff(lastAuthenticatedOn, 'seconds') > maxAge) { - // Don't set the token so the user must re-authenticate to use this app - setHasInitializedSession(true) + // Invalidate the token (if present) so the user must re-authenticate to use this app + initAnonymousUserState() return } } From c5bc86d686da53a1998c66b4a701b8f98c222c57 Mon Sep 17 00:00:00 2001 From: jay-hodgson Date: Tue, 29 Oct 2024 20:01:45 -0700 Subject: [PATCH 2/2] if authenticatedOn difference is greater than maxAge then we should sign out --- .../src/utils/AppUtils/session/ApplicationSession.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSession.test.tsx b/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSession.test.tsx index 05b68df76a..32baa2dec6 100644 --- a/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSession.test.tsx +++ b/packages/synapse-react-client/src/utils/AppUtils/session/ApplicationSession.test.tsx @@ -371,8 +371,8 @@ describe('ApplicationSessionManager tests', () => { await waitFor(() => { expect(mockGetAccessToken).toHaveBeenCalled() expect(mockAuthenticatedOn).toHaveBeenCalled() + expect(signOutSpy).toHaveBeenCalled() expect(mockTermsOfServiceStatus).not.toHaveBeenCalled() - expect(signOutSpy).not.toHaveBeenCalled() expect(context.result.current).toMatchObject(EXPECTED_ANONYMOUS_STATE) }) })