Skip to content

Commit 832d49a

Browse files
committed
fix(settings): Redirect from React email first with email param
Because: * Navigating to react email first with an email param was causing an infinite redirect This commit: * If an email is provided, check email status and redirect appropriately to signin or signup Closes #FXA-11327
1 parent ddc76fa commit 832d49a

File tree

2 files changed

+68
-43
lines changed

2 files changed

+68
-43
lines changed

packages/functional-tests/tests/oauth/oauthPromptNone.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ test.describe('severity-1 #smoke', () => {
5050

5151
const query = new URLSearchParams({
5252
login_hint: email,
53-
return_on_error: 'false',
53+
// return_on_error: 'false',
5454
});
5555
await page.goto(`http://localhost:10139` + `/?${query.toString()}`);
5656
await relier.signInPromptNone();

packages/fxa-settings/src/pages/Index/container.tsx

+67-42
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import { RouteComponentProps, useLocation, useNavigate } from '@reach/router';
6-
import { useNavigateWithQuery } from '../../lib/hooks/useNavigateWithQuery';
76
import Index from '.';
87
import { IndexContainerProps, LocationState } from './interfaces';
98
import { useCallback, useEffect } from 'react';
@@ -36,7 +35,6 @@ export const IndexContainer = ({
3635
// TODO, more strict validation for bad oauth params, FXA-11297
3736
const authClient = useAuthClient();
3837
const navigate = useNavigate();
39-
const navigateWithQuery = useNavigateWithQuery();
4038
const location = useLocation() as ReturnType<typeof useLocation> & {
4139
state?: LocationState;
4240
};
@@ -49,25 +47,76 @@ export const IndexContainer = ({
4947
const isWebChannelIntegration =
5048
integration.isSync() || integration.isDesktopRelay();
5149

52-
// 'email' query param followed by 'login_hint' should take precedence
53-
const email =
50+
// 'email' query param should take precedence, followed by 'login_hint'
51+
const suggestedEmail =
5452
queryParamModel.email ||
5553
integration.data.loginHint ||
5654
currentAccount()?.email;
57-
const shouldRedirectToSignin = email && !prefillEmail;
55+
56+
const hasEmailSuggestion = suggestedEmail && !prefillEmail;
57+
58+
const handleNavigation = useCallback(
59+
(
60+
exists: boolean,
61+
hasLinkedAccount: boolean,
62+
hasPassword: boolean,
63+
email: string
64+
) => {
65+
const params = new URLSearchParams(location.search);
66+
// We delete 'email' if it is present because otherwise, that param will take
67+
// precedence and the user will be unable to create an account with a different
68+
// email. Remove for signin as well as it is unnecessary. This is a byproduct
69+
// of backwards compatibility between Backbone and React since we pass this
70+
// param from content-server, TODO: FXA-10567
71+
// We can also use useNavigateWithQuery after addressing the above.
72+
params.delete('email');
73+
const hasParams = params.size > 0;
74+
const isOAuth = location.pathname.startsWith('/oauth');
75+
if (!exists) {
76+
const signupRoute = isOAuth ? '/oauth/signup' : '/signup';
77+
console.log(
78+
`${signupRoute}${hasParams ? `?${params.toString()}` : ''}`
79+
);
80+
navigate(`${signupRoute}${hasParams ? `?${params.toString()}` : ''}`, {
81+
state: {
82+
email,
83+
emailStatusChecked: true,
84+
},
85+
});
86+
} else {
87+
const signinRoute = isOAuth ? '/oauth/signin' : '/signin';
88+
navigate(`${signinRoute}${hasParams ? `?${params.toString()}` : ''}`, {
89+
state: {
90+
email,
91+
hasLinkedAccount,
92+
hasPassword,
93+
},
94+
});
95+
}
96+
},
97+
[location.pathname, location.search, navigate]
98+
);
5899

59100
useEffect(() => {
60-
if (shouldRedirectToSignin) {
61-
const route = location.pathname.startsWith('/oauth')
62-
? '/oauth/signin'
63-
: '/signin';
64-
navigateWithQuery(route, {
65-
state: {
66-
email,
67-
},
68-
});
101+
if (!hasEmailSuggestion) {
102+
return;
69103
}
70-
});
104+
105+
const checkEmailAndNavigate = async () => {
106+
const { exists, hasLinkedAccount, hasPassword } =
107+
await authClient.accountStatusByEmail(suggestedEmail, {
108+
thirdPartyAuthStatus: true,
109+
});
110+
111+
handleNavigation(exists, hasLinkedAccount, hasPassword, suggestedEmail);
112+
};
113+
114+
checkEmailAndNavigate();
115+
}, [authClient, handleNavigation, hasEmailSuggestion, suggestedEmail]);
116+
117+
useEffect(() => {
118+
console.log('Location state changed', location.state);
119+
}, [location.state]);
71120

72121
const signUpOrSignInHandler = useCallback(
73122
async (email: string) => {
@@ -112,37 +161,13 @@ export const IndexContainer = ({
112161
}
113162
}
114163

115-
const params = new URLSearchParams(location.search);
116-
// We delete 'email' if it is present because otherwise, that param will take
117-
// precedence and the user will be unable to create an account with a different
118-
// email. Remove for signin as well as it is unnecessary. This is a byproduct
119-
// of backwards compatibility between Backbone and React since we pass this
120-
// param from content-server, TODO: FXA-10567
121-
// We can also use useNavigateWithQuery after addressing the above.
122-
params.delete('email');
123-
const hasParams = params.size > 0;
124-
if (!exists) {
125-
navigate(`/signup${hasParams ? `?${params.toString()}` : ''}`, {
126-
state: {
127-
email,
128-
emailStatusChecked: true,
129-
},
130-
});
131-
} else {
132-
navigate(`/signin${hasParams ? `?${params.toString()}` : ''}`, {
133-
state: {
134-
email,
135-
hasLinkedAccount,
136-
hasPassword,
137-
},
138-
});
139-
}
164+
handleNavigation(exists, hasLinkedAccount, hasPassword, email);
140165
return { error: null };
141166
} catch (error) {
142167
return getHandledError(error);
143168
}
144169
},
145-
[authClient, navigate, isWebChannelIntegration, location.search]
170+
[authClient, handleNavigation, isWebChannelIntegration]
146171
);
147172

148173
if (validationError) {
@@ -155,7 +180,7 @@ export const IndexContainer = ({
155180
return <LoadingSpinner fullScreen />;
156181
}
157182

158-
if (shouldRedirectToSignin) {
183+
if (hasEmailSuggestion) {
159184
return <LoadingSpinner fullScreen />;
160185
}
161186

0 commit comments

Comments
 (0)