Skip to content

Commit 4fce8d9

Browse files
committed
fix: in-app redirect existing email
1 parent 73efc7a commit 4fce8d9

3 files changed

Lines changed: 74 additions & 11 deletions

File tree

packages/shared/src/features/onboarding/shared/utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ export function shouldRedirectAuth(): boolean {
3030

3131
return brokenWebviewPatterns.some((pattern) => pattern.test(ua));
3232
}
33+
34+
export const AUTH_REDIRECT_KEY = 'auth_redirect';

packages/shared/src/features/onboarding/steps/FunnelRegistration.tsx

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ReactElement } from 'react';
2-
import React, { useEffect, useMemo, useRef } from 'react';
2+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
33
import { useRouter } from 'next/router';
44
import classNames from 'classnames';
55
import {
@@ -29,7 +29,11 @@ import { broadcastChannel } from '../../../lib/constants';
2929
import Logo, { LogoPosition } from '../../../components/Logo';
3030
import type { LoggedUser } from '../../../lib/user';
3131
import { FunnelStepTransitionType } from '../types/funnel';
32-
import { sanitizeMessage, shouldRedirectAuth } from '../shared';
32+
import {
33+
AUTH_REDIRECT_KEY,
34+
sanitizeMessage,
35+
shouldRedirectAuth,
36+
} from '../shared';
3337
import type { FunnelStepSignup } from '../types/funnel';
3438
import { useConsentCookie } from '../../../hooks/useCookieConsent';
3539
import { GdprConsentKey } from '../../../hooks/useCookieBanner';
@@ -50,15 +54,9 @@ const useRegistrationListeners = (
5054
const { logEvent } = useLogContext();
5155
const router = useRouter();
5256

53-
const onProviderMessage = async (e: MessageEvent) => {
54-
const isEventSupported = supportedEvents.includes(e.data?.eventKey);
55-
56-
if (!isEventSupported) {
57-
return undefined;
58-
}
59-
60-
if (e.data?.flow) {
61-
const connected = await getKratosFlow(AuthFlow.Registration, e.data.flow);
57+
const handleExistingFlow = useCallback(
58+
async (flow: string) => {
59+
const connected = await getKratosFlow(AuthFlow.Registration, flow);
6260

6361
logEvent({
6462
event_name: AuthEventNames.RegistrationError,
@@ -78,6 +76,19 @@ const useRegistrationListeners = (
7876
}
7977

8078
return displayToast(`${labels.auth.error.generic} Code: ${code}`);
79+
},
80+
[displayToast, logEvent],
81+
);
82+
83+
const onProviderMessage = async (e: MessageEvent) => {
84+
const isEventSupported = supportedEvents.includes(e.data?.eventKey);
85+
86+
if (!isEventSupported) {
87+
return undefined;
88+
}
89+
90+
if (e.data?.flow) {
91+
return handleExistingFlow(e.data.flow);
8192
}
8293

8394
const bootResponse = await refetchBoot();
@@ -100,6 +111,23 @@ const useRegistrationListeners = (
100111
useEventListener(broadcastChannel, 'message', onProviderMessage);
101112

102113
useEventListener(globalThis, 'message', onProviderMessage);
114+
115+
useEffect(() => {
116+
if (!router?.isReady || !router?.query?.flow) {
117+
return;
118+
}
119+
120+
const flowFn = async () => {
121+
await handleExistingFlow(router.query.flow as string);
122+
const url = new URL(window.location.href);
123+
const fullPath = url.origin + url.pathname;
124+
const { flow, ...rest } = router.query;
125+
const params = new URLSearchParams(rest as Record<string, string>);
126+
router.replace(`${fullPath}?${params}`);
127+
};
128+
129+
flowFn();
130+
}, [handleExistingFlow, router]);
103131
};
104132

105133
function InnerFunnelRegistration({
@@ -123,6 +151,7 @@ function InnerFunnelRegistration({
123151
},
124152
onRedirect: (redirect) => {
125153
if (shouldRedirect) {
154+
window.sessionStorage.setItem(AUTH_REDIRECT_KEY, window.location.href);
126155
window.location.href = redirect;
127156
} else {
128157
windowPopup.current.location.href = redirect;
@@ -142,6 +171,14 @@ function InnerFunnelRegistration({
142171

143172
const sanitizedHeading = useMemo(() => sanitizeMessage(headline), [headline]);
144173

174+
useEffect(() => {
175+
if (typeof window === 'undefined' || !shouldRedirect) {
176+
return;
177+
}
178+
179+
window.sessionStorage.removeItem(AUTH_REDIRECT_KEY);
180+
}, [shouldRedirect]);
181+
145182
return (
146183
<div className="relative flex w-full flex-1 flex-col items-center justify-center overflow-hidden">
147184
<div className="absolute inset-0">

packages/webapp/pages/callback.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { AuthEvent } from '@dailydotdev/shared/src/lib/kratos';
66
import type { ReactElement } from 'react';
77
import { useContext, useEffect } from 'react';
88
import LogContext from '@dailydotdev/shared/src/contexts/LogContext';
9+
import {
10+
AUTH_REDIRECT_KEY,
11+
shouldRedirectAuth,
12+
} from '@dailydotdev/shared/src/features/onboarding/shared';
913

1014
const checkShouldSendBroadcast = () => {
1115
const ua = navigator.userAgent;
@@ -17,6 +21,21 @@ const checkShouldSendBroadcast = () => {
1721
return conditions.some(Boolean);
1822
};
1923

24+
const handleRedirectAuth = (params: URLSearchParams) => {
25+
const href = window.sessionStorage.getItem(AUTH_REDIRECT_KEY);
26+
27+
if (href) {
28+
const [redirect, hrefParams] = href.split('?');
29+
const redirectParams = new URLSearchParams(hrefParams);
30+
31+
Object.entries(redirectParams).forEach(([key, value]) =>
32+
params.set(key, value),
33+
);
34+
35+
window.location.replace(`${redirect}?${params}`);
36+
}
37+
};
38+
2039
function CallbackPage(): ReactElement {
2140
const { logEvent } = useContext(LogContext);
2241
useEffect(() => {
@@ -36,6 +55,11 @@ function CallbackPage(): ReactElement {
3655
return;
3756
}
3857

58+
if (shouldRedirectAuth()) {
59+
handleRedirectAuth(urlSearchParams);
60+
return;
61+
}
62+
3963
if (checkShouldSendBroadcast()) {
4064
broadcastMessage({ ...params, eventKey });
4165
} else {

0 commit comments

Comments
 (0)