Skip to content

Commit 776cdc6

Browse files
authored
Merge pull request #19531 from mozilla/polish-better-error-msg-for-invalid-token
polish(settings): Provide hint about what to do in invalid session state
2 parents 31f4964 + f1ab1b8 commit 776cdc6

9 files changed

Lines changed: 90 additions & 14 deletions

File tree

packages/fxa-react/components/AppErrorBoundary/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import React from 'react';
66
import AppErrorDialog from '../AppErrorDialog';
77
import * as Sentry from '@sentry/browser';
88

9-
interface AppErrorBoundaryProps {
9+
type AppErrorBoundaryProps = {
1010
children?: React.ReactNode;
11-
}
11+
};
1212

13-
interface AppErrorBoundaryState {
13+
type AppErrorBoundaryState = {
1414
error: Error | undefined;
15-
}
15+
};
1616

1717
class AppErrorBoundary extends React.Component<
1818
AppErrorBoundaryProps,
@@ -22,7 +22,7 @@ class AppErrorBoundary extends React.Component<
2222
error: undefined | Error;
2323
};
2424

25-
constructor(props: {}) {
25+
constructor(props: AppErrorBoundaryProps) {
2626
super(props);
2727
this.state = { error: undefined };
2828
}
@@ -38,7 +38,7 @@ class AppErrorBoundary extends React.Component<
3838

3939
render() {
4040
const { error } = this.state;
41-
return error ? <AppErrorDialog /> : (this.props as any).children;
41+
return error ? <AppErrorDialog /> : this.props.children;
4242
}
4343
}
4444

packages/fxa-react/components/AppErrorDialog/en.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,8 @@ app-general-err-message = Something went wrong. Please try again later.
55
66
# Specific handling for issues when bad or missing query parameters are detected
77
app-query-parameter-err-heading = Bad Request: Invalid Query Parameters
8+
9+
# Specific handler for issues where something went side with the session. Maybe it did't have proper permissions,
10+
# or maybe the session token is stale and the user needs to sign back in again.
11+
app-invalid-session-err-heading = Invalid Session
12+
app-invalid-session-err-message = Please sign out and sign in again.

packages/fxa-react/components/AppErrorDialog/index.stories.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,12 @@ storiesOf('Components/AppErrorDialog', module)
3131
>
3232
<AppErrorDialog errorType="query-parameter-violation" />
3333
</AppLocalizationProvider>
34+
))
35+
.add('invalid session', () => (
36+
<AppLocalizationProvider
37+
baseDir="./locales"
38+
userLocales={navigator.languages}
39+
>
40+
<AppErrorDialog errorType="invalid-session" />
41+
</AppLocalizationProvider>
3442
));

packages/fxa-react/components/AppErrorDialog/index.test.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,15 @@ describe('AppErrorDialog', () => {
1414

1515
expect(queryByTestId('error-loading-app')).toBeInTheDocument();
1616
});
17+
18+
it('can trigger another signin attempt in invalid-session case', async () => {
19+
const { queryByText } = renderWithLocalizationProvider(
20+
<AppErrorDialog errorType="invalid-session" />
21+
);
22+
23+
expect(queryByText('Invalid Session')).toBeInTheDocument();
24+
expect(
25+
queryByText('Please sign out and sign in again.')
26+
).toBeInTheDocument();
27+
});
1728
});

packages/fxa-react/components/AppErrorDialog/index.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
import React from 'react';
66
import { Localized } from '@fluent/react';
77

8-
export type ErrorType = 'general' | 'query-parameter-violation';
8+
export type ErrorType =
9+
| 'general'
10+
| 'query-parameter-violation'
11+
| 'invalid-session';
912

1013
const AppErrorDialog = ({ errorType }: { errorType?: ErrorType }) => {
1114
if (errorType == null) {
@@ -43,6 +46,24 @@ const AppErrorDialog = ({ errorType }: { errorType?: ErrorType }) => {
4346
</p>
4447
</Localized>
4548
)}
49+
50+
{errorType === 'invalid-session' && (
51+
<>
52+
<Localized id="app-invalid-session-err-heading">
53+
<h2
54+
className="text-grey-900 font-header text-lg font-bold mb-3"
55+
data-testid="error-invalid-session"
56+
>
57+
Invalid Session
58+
</h2>
59+
</Localized>
60+
<Localized id="app-invalid-session-err-message">
61+
<p className="text-grey-400">
62+
Please sign out and sign in again.
63+
</p>
64+
</Localized>
65+
</>
66+
)}
4667
</div>
4768
</div>
4869
);

packages/fxa-settings/src/components/ErrorBoundaries/index.stories.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44

55
import React from 'react';
66
import { AppError } from '.';
7-
import {
8-
9-
UrlQueryData,
10-
} from '../../lib/model-data';
7+
import { UrlQueryData } from '../../lib/model-data';
118
import { withLocalization } from 'fxa-react/lib/storybooks';
129

1310
import { Meta } from '@storybook/react';
@@ -43,3 +40,12 @@ export const QueryParamValidationError = () => {
4340
// AppError should display a list of the validation errors
4441
return <AppError error={validationError} />;
4542
};
43+
44+
export const InvalidSessionError = () => {
45+
const error = {
46+
name: '',
47+
message: 'Unconfirmed Session',
48+
errno: 138,
49+
};
50+
return <AppError error={error} />;
51+
};

packages/fxa-settings/src/components/ErrorBoundaries/index.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import React, { ReactNode } from 'react';
66
import { ModelValidationErrors } from '../../lib/model-data';
77
import * as Sentry from '@sentry/browser';
88
import AppErrorDialog from 'fxa-react/components/AppErrorDialog';
9+
import { AuthUiErrors, isAuthUiError } from '../../lib/auth-errors/auth-errors';
910

1011
/**
1112
* Handles errors that might occur in fxa-settings
@@ -47,6 +48,16 @@ export class AppErrorBoundary extends React.Component<{ children: ReactNode }> {
4748
}
4849

4950
export const AppError = ({ error }: { error?: Error }) => {
51+
// Special handling for invalid session states
52+
if (
53+
isAuthUiError(error) &&
54+
(error.errno === AuthUiErrors.INVALID_TOKEN.errno ||
55+
error.errno === AuthUiErrors.UNVERIFIED_SESSION.errno)
56+
) {
57+
// TODO: Add functionality so that is easy for a user to sign back in.
58+
return <AppErrorDialog errorType="invalid-session" />;
59+
}
60+
5061
// Special handling for validation errors
5162
if (error instanceof ModelValidationErrors) {
5263
return <AppErrorDialog errorType="query-parameter-violation" />;

packages/fxa-settings/src/lib/auth-errors/auth-errors.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ const ERRORS = {
5656
},
5757
INVALID_TOKEN: {
5858
errno: 110,
59-
message: 'Invalid token',
59+
message: 'Invalid session. Please sign out and sign in again.',
60+
version: 2,
6061
},
6162
INVALID_TIMESTAMP: {
6263
errno: 111,
@@ -139,8 +140,8 @@ const ERRORS = {
139140
},
140141
UNVERIFIED_SESSION: {
141142
errno: 138,
142-
message: 'Unconfirmed session',
143-
version: 2,
143+
message: 'Unconfirmed session. Please sign out and sign in again.',
144+
version: 3,
144145
},
145146
EMAIL_PRIMARY_EXISTS: {
146147
errno: 139,
@@ -690,3 +691,14 @@ export const AuthUiErrorNos: {
690691
errnos.push(x.errno);
691692
}
692693
})();
694+
695+
/**
696+
* TypeGuard for AuthUiErrors
697+
*/
698+
export function isAuthUiError(error: any): error is AuthUiError {
699+
return (
700+
typeof error === 'object' &&
701+
typeof error?.errno === 'number' &&
702+
typeof error?.message === 'string'
703+
);
704+
}

packages/fxa-settings/src/lib/auth-errors/en.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ auth-error-102 = Unknown account
44
auth-error-103 = Incorrect password
55
auth-error-105-2 = Invalid confirmation code
66
auth-error-110 = Invalid token
7+
auth-error-110-2 = Invalid session. Please sign out and sign in again.
78
# Error shown to users when they have attempted a request (e.g., requesting a password reset) too many times
89
# and their requests have been throttled, but the specific amount of time before they can retry is unknown.
910
auth-error-114-generic = You’ve tried too many times. Please try again later.
@@ -16,6 +17,7 @@ auth-error-114 = You’ve tried too many times. Please try again { $retryAfter }
1617
auth-error-125 = The request was blocked for security reasons
1718
auth-error-129-2 = You entered an invalid phone number. Please check it and try again.
1819
auth-error-138-2 = Unconfirmed session
20+
auth-error-138-3 = Unconfirmed Session. Please sign out and sign in again.
1921
auth-error-139 = Secondary email must be different than your account email
2022
auth-error-155 = TOTP token not found
2123
# Error shown when the user submits an invalid backup authentication code

0 commit comments

Comments
 (0)