fix(signin): Fix redirect to /subscriptions after signin

Because:

* Redirect back to /subscriptions after signin was not working

This commit:

* Pass the redirectTo as search param
* Validate the redirectTo and if valid navigate there after signin

Closes #FXA-9826
This commit is contained in:
Valerie Pomerleau 2024-06-07 16:24:15 -07:00
Родитель e74a3c4b8e
Коммит 61698366c9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 33A451F0BB2180B4
8 изменённых файлов: 28 добавлений и 10 удалений

Просмотреть файл

@ -455,6 +455,10 @@ Router = Router.extend({
email: this.user.get('emailFromIndex'),
hasLinkedAccount: this.user.get('hasLinkedAccount'),
hasPassword: this.user.get('hasPassword'),
// for subplat redirect only
...(this.relier.get('redirectTo') && {
redirect_to: this.relier.get('redirectTo'),
}),
});
},
'signin_bounced(/)': function () {
@ -528,6 +532,7 @@ Router = Router.extend({
...(this.user.get('emailFromIndex') && {
emailStatusChecked: 'true',
}),
redirect_to: this.relier.get('redirectTo'),
});
},
'signup_confirmed(/)': function () {

Просмотреть файл

@ -14,8 +14,6 @@ import { useCallback } from 'react';
import { getSigninState } from '../utils';
import { SigninLocationState } from '../interfaces';
import { useFinishOAuthFlowHandler } from '../../../lib/oauth/hooks';
import { useValidatedQueryParams } from '../../../lib/hooks/useValidate';
import { SigninQueryParams } from '../../../models/pages/signin';
import { ConsumeRecoveryCodeResponse, SubmitRecoveryCode } from './interfaces';
import OAuthDataError from '../../../components/OAuthDataError';
import { AuthUiErrors } from '../../../lib/auth-errors/auth-errors';
@ -39,8 +37,6 @@ export const SigninRecoveryCodeContainer = ({
const location = useLocation() as ReturnType<typeof useLocation> & {
state: SigninLocationState;
};
const { queryParamModel } = useValidatedQueryParams(SigninQueryParams);
const { redirectTo } = queryParamModel;
const signinState = getSigninState(location.state);
@ -83,7 +79,6 @@ export const SigninRecoveryCodeContainer = ({
{...{
finishOAuthFlowHandler,
integration,
redirectTo,
serviceName,
signinState,
submitRecoveryCode,

Просмотреть файл

@ -20,13 +20,13 @@ import Banner, { BannerType } from '../../../components/Banner';
import { storeAccountData } from '../../../lib/storage-utils';
import { handleNavigation } from '../utils';
import { getLocalizedErrorMessage } from '../../../lib/error-utils';
import { useWebRedirect } from '../../../lib/hooks/useWebRedirect';
export const viewName = 'signin-recovery-code';
const SigninRecoveryCode = ({
finishOAuthFlowHandler,
integration,
redirectTo,
serviceName,
signinState,
submitRecoveryCode,
@ -44,6 +44,12 @@ const SigninRecoveryCode = ({
);
const location = useLocation();
const webRedirectCheck = useWebRedirect(integration.data.redirectTo);
const redirectTo = webRedirectCheck.isValid()
? integration.data.redirectTo
: '';
const formAttributes: FormAttributes = {
inputFtlId: 'signin-recovery-code-input-label',
inputLabelText: 'Enter 10-digit backup authentication code',

Просмотреть файл

@ -10,7 +10,6 @@ import { SigninIntegration, SigninLocationState } from '../interfaces';
export type SigninRecoveryCodeProps = {
finishOAuthFlowHandler: FinishOAuthFlowHandler;
integration: SigninIntegration;
redirectTo?: string;
serviceName?: MozServices;
signinState: SigninLocationState;
submitRecoveryCode: SubmitRecoveryCode;

Просмотреть файл

@ -25,6 +25,7 @@ import Banner, {
import { handleNavigation } from '../utils';
import firefox from '../../../lib/channels/firefox';
import { getLocalizedErrorMessage } from '../../../lib/error-utils';
import { useWebRedirect } from '../../../lib/hooks/useWebRedirect';
export const viewName = 'signin-token-code';
@ -56,6 +57,11 @@ const SigninTokenCode = ({
const [codeErrorMessage, setCodeErrorMessage] = useState<string>('');
const [resendCodeLoading, setResendCodeLoading] = useState<boolean>(false);
const webRedirectCheck = useWebRedirect(integration.data.redirectTo);
const redirectTo = webRedirectCheck.isValid()
? integration.data.redirectTo
: '';
const ftlMsgResolver = useFtlMsgResolver();
const localizedCustomCodeRequiredMessage = ftlMsgResolver.getMsg(
'signin-token-code-required-error',
@ -161,6 +167,7 @@ const SigninTokenCode = ({
integration,
finishOAuthFlowHandler,
queryParams: location.search,
redirectTo,
};
await GleanMetrics.isDone();
@ -199,6 +206,7 @@ const SigninTokenCode = ({
keyFetchToken,
localizedInvalidCode,
location.search,
redirectTo,
session,
sessionToken,
uid,

Просмотреть файл

@ -48,7 +48,6 @@ function mockSigninTotpModule() {
function mockUseValidateModule(opts: any = {}) {
jest.spyOn(UseValidateModule, 'useValidatedQueryParams').mockReturnValue({
queryParamModel: {
redirectTo: '',
verificationReason: 'login',
service: 'sync',
...opts,

Просмотреть файл

@ -18,6 +18,7 @@ import { hardNavigate } from 'fxa-react/lib/utils';
import LoadingSpinner from 'fxa-react/components/LoadingSpinner';
import OAuthDataError from '../../../components/OAuthDataError';
import { getHandledError } from '../../../lib/error-utils';
import { useWebRedirect } from '../../../lib/hooks/useWebRedirect';
export type SigninTotpCodeContainerProps = {
integration: Integration;
@ -41,7 +42,13 @@ export const SigninTotpCodeContainer = ({
const signinState = getSigninState(location.state);
const { queryParamModel } = useValidatedQueryParams(SigninQueryParams);
const { redirectTo, service } = queryParamModel;
const { service } = queryParamModel;
const webRedirectCheck = useWebRedirect(integration.data.redirectTo);
const redirectTo = webRedirectCheck.isValid()
? integration.data.redirectTo
: '';
const [verifyTotpCode] = useMutation(VERIFY_TOTP_CODE_MUTATION);

Просмотреть файл

@ -23,7 +23,6 @@ import {
MOCK_SESSION_TOKEN,
MOCK_UID,
MOCK_UNWRAP_BKEY,
MOCK_AUTHPW,
} from '../mocks';
import { MozServices } from '../../lib/types';
import * as utils from 'fxa-react/lib/utils';