@oneblink/apps-react 11.0.0-beta.8 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,7 @@ import { MiscTypes } from '@oneblink/types';
2
2
  type Props = {
3
3
  mfaRequirement: MiscTypes.MfaRequirement | undefined;
4
4
  ssoSetupUrl?: string;
5
+ accessScopeLabel?: string;
5
6
  };
6
7
  /**
7
8
  * React Component that provides a mechanism for app users to configure Multi
@@ -38,5 +39,5 @@ type Props = {
38
39
  * @returns
39
40
  * @group Components
40
41
  */
41
- export default function MultiFactorAuthentication({ mfaRequirement, ssoSetupUrl, }: Props): import("react/jsx-runtime").JSX.Element;
42
+ export default function MultiFactorAuthentication({ mfaRequirement, ssoSetupUrl, accessScopeLabel, }: Props): import("react/jsx-runtime").JSX.Element;
42
43
  export {};
@@ -10,8 +10,8 @@ import MfaMethodRow from './MfaMethodRow';
10
10
  import MfaSuccessSnackbar from './MfaSuccessSnackbar';
11
11
  import MfaErrorSnackbar from './MfaErrorSnackbar';
12
12
  import MfaStatusChip from './MfaStatusChip';
13
- import { formatMfaMethodNotAcceptedMessage } from '../../utils/mfa-requirement';
14
- function MfaMethodList({ mfaRequirement }) {
13
+ import { formatMfaMethodRequirementMessage, isMfaMethodUsedForLogin, } from '../../utils/mfa-requirement';
14
+ function MfaMethodList({ mfaRequirement, accessScopeLabel = 'app', }) {
15
15
  const { mfaSettings, loadingError, isLoading, isSettingUpMfa, settingUpMfaMethod, isSettingPreferredMfaMethod, beginMfaSetup, beginDisablingMfaMethod, setPreferredMfaMethod, beginRemovingPhoneNumber, } = useMfa();
16
16
  const phoneDetail = useMemo(() => {
17
17
  if (!mfaSettings.sms.phoneNumber) {
@@ -23,20 +23,21 @@ function MfaMethodList({ mfaRequirement }) {
23
23
  return `Phone number: ${mfaSettings.sms.phoneNumber}`;
24
24
  }, [mfaSettings]);
25
25
  const authenticatorMfaRequirementMessage = useMemo(() => {
26
- return formatMfaMethodNotAcceptedMessage('authenticatorApp', mfaRequirement);
27
- }, [mfaRequirement]);
26
+ return formatMfaMethodRequirementMessage('authenticatorApp', mfaRequirement, mfaSettings, accessScopeLabel);
27
+ }, [accessScopeLabel, mfaRequirement, mfaSettings]);
28
28
  const smsMfaRequirementMessage = useMemo(() => {
29
- return formatMfaMethodNotAcceptedMessage('sms', mfaRequirement);
30
- }, [mfaRequirement]);
29
+ return formatMfaMethodRequirementMessage('sms', mfaRequirement, mfaSettings, accessScopeLabel);
30
+ }, [accessScopeLabel, mfaRequirement, mfaSettings]);
31
31
  if (isLoading) {
32
32
  return (_jsx(Typography, { variant: "body2", color: "text.secondary", children: "Loading MFA methods..." }));
33
33
  }
34
34
  if (loadingError) {
35
35
  return (_jsx(Typography, { variant: "body2", color: "error", children: "We are unable to load your MFA methods. Please try again by clicking the reload button on the chip above." }));
36
36
  }
37
- return (_jsxs(_Fragment, { children: [_jsx(MfaMethodRow, { isEnabled: mfaSettings.authenticator.enabled, isPreferred: mfaSettings.authenticator.preferred, isSettingUp: isSettingUpMfa && settingUpMfaMethod === 'authenticator', isSettingPreferredMfaMethod: isSettingPreferredMfaMethod, isSetupDisabled: !!loadingError || isSettingUpMfa, showSetupErrorTooltip: !!loadingError, title: "Authenticator App", description: "Use an app like Google Authenticator or Microsoft Authenticator to generate 6-digit verification codes.", mfaRequirementMessage: authenticatorMfaRequirementMessage, cypressPrefix: "mfa-authenticator", onSetup: () => beginMfaSetup('authenticator'), onDisable: () => beginDisablingMfaMethod('authenticator'), onSetPreferred: () => setPreferredMfaMethod('authenticator') }), _jsx(Divider, { sx: { my: 2 } }), _jsx(MfaMethodRow, { isEnabled: mfaSettings.sms.enabled, isPreferred: mfaSettings.sms.preferred, isSettingUp: isSettingUpMfa && settingUpMfaMethod === 'sms', isSettingPreferredMfaMethod: isSettingPreferredMfaMethod, isSetupDisabled: !!loadingError || isSettingUpMfa, showSetupErrorTooltip: !!loadingError, title: "SMS", description: "Receive a one-time verification code via SMS each time MFA is required.", detail: phoneDetail, mfaRequirementMessage: smsMfaRequirementMessage, cypressPrefix: "mfa-sms", onSetup: () => beginMfaSetup('sms'), onDisable: () => beginDisablingMfaMethod('sms'), onSetPreferred: () => setPreferredMfaMethod('sms'), extraButtons: !!mfaSettings.sms.phoneNumber && !mfaSettings.sms.enabled ? (_jsx(Button, { size: "small", variant: "outlined", disabled: !!loadingError, onClick: beginRemovingPhoneNumber, "data-cypress": "mfa-sms-remove-phone-button", children: "Remove Phone" })) : undefined })] }));
37
+ return (_jsxs(_Fragment, { children: [_jsx(MfaMethodRow, { isEnabled: mfaSettings.authenticator.enabled, isPreferred: mfaSettings.authenticator.preferred, isUsedForLogin: isMfaMethodUsedForLogin(mfaSettings, 'authenticatorApp'), isSettingUp: isSettingUpMfa && settingUpMfaMethod === 'authenticator', isSettingPreferredMfaMethod: isSettingPreferredMfaMethod, isSetupDisabled: !!loadingError || isSettingUpMfa, showSetupErrorTooltip: !!loadingError, title: "Authenticator App", description: "Use an app like Google Authenticator or Microsoft Authenticator to generate 6-digit verification codes.", mfaRequirementMessage: authenticatorMfaRequirementMessage, mfaRequirementMessageIsWarning: !!(mfaRequirement === null || mfaRequirement === void 0 ? void 0 : mfaRequirement.authenticatorApp) &&
38
+ !!authenticatorMfaRequirementMessage, cypressPrefix: "mfa-authenticator", onSetup: () => beginMfaSetup('authenticator'), onDisable: () => beginDisablingMfaMethod('authenticator'), onSetPreferred: () => setPreferredMfaMethod('authenticator') }), _jsx(Divider, { sx: { my: 2 } }), _jsx(MfaMethodRow, { isEnabled: mfaSettings.sms.enabled, isPreferred: mfaSettings.sms.preferred, isUsedForLogin: isMfaMethodUsedForLogin(mfaSettings, 'sms'), isSettingUp: isSettingUpMfa && settingUpMfaMethod === 'sms', isSettingPreferredMfaMethod: isSettingPreferredMfaMethod, isSetupDisabled: !!loadingError || isSettingUpMfa || !mfaSettings.sms.enabled, showSetupErrorTooltip: !!loadingError, title: "SMS", description: "Receive a one-time verification code via SMS each time MFA is required.", detail: phoneDetail, mfaRequirementMessage: smsMfaRequirementMessage, mfaRequirementMessageIsWarning: !!(mfaRequirement === null || mfaRequirement === void 0 ? void 0 : mfaRequirement.sms) && !!smsMfaRequirementMessage, cypressPrefix: "mfa-sms", onSetup: () => beginMfaSetup('sms'), onDisable: () => beginDisablingMfaMethod('sms'), onSetPreferred: () => setPreferredMfaMethod('sms'), extraButtons: !!mfaSettings.sms.phoneNumber && !mfaSettings.sms.enabled ? (_jsx(Button, { size: "small", variant: "outlined", disabled: !!loadingError, onClick: beginRemovingPhoneNumber, "data-cypress": "mfa-sms-remove-phone-button", children: "Remove Phone" })) : undefined })] }));
38
39
  }
39
- function MfaSetup({ ssoSetupUrl, mfaRequirement }) {
40
+ function MfaSetup({ ssoSetupUrl, mfaRequirement, accessScopeLabel }) {
40
41
  const { isExternalIdentityProviderUser } = useMfa();
41
42
  if (ssoSetupUrl) {
42
43
  return (_jsx(Button, { variant: "outlined", size: "small", component: "a", href: ssoSetupUrl, target: "_blank", rel: "noopener noreferrer", "data-cypress": "configure-mfa-button", children: "Configure MFA" }));
@@ -44,7 +45,7 @@ function MfaSetup({ ssoSetupUrl, mfaRequirement }) {
44
45
  if (isExternalIdentityProviderUser) {
45
46
  return (_jsx(Tooltip, { title: "MFA must be configured in your login provider.", children: _jsx("span", { children: _jsx(Button, { variant: "outlined", disabled: isExternalIdentityProviderUser, "data-cypress": "configure-mfa-button", children: "Configure MFA" }) }) }));
46
47
  }
47
- return (_jsxs(_Fragment, { children: [_jsx(MfaMethodList, { mfaRequirement: mfaRequirement }), _jsx(MfaDisableDialog, {}), _jsx(MfaRemovePhoneNumberDialog, {}), _jsx(MfaPhoneNumberDialog, {}), _jsx(MfaAuthenticatorAppDialog, {}), _jsx(MfaErrorSnackbar, {}), _jsx(MfaSuccessSnackbar, {})] }));
48
+ return (_jsxs(_Fragment, { children: [_jsx(MfaMethodList, { mfaRequirement: mfaRequirement, accessScopeLabel: accessScopeLabel }), _jsx(MfaDisableDialog, {}), _jsx(MfaRemovePhoneNumberDialog, {}), _jsx(MfaPhoneNumberDialog, {}), _jsx(MfaAuthenticatorAppDialog, {}), _jsx(MfaErrorSnackbar, {}), _jsx(MfaSuccessSnackbar, {})] }));
48
49
  }
49
50
  /**
50
51
  * React Component that provides a mechanism for app users to configure Multi
@@ -81,7 +82,7 @@ function MfaSetup({ ssoSetupUrl, mfaRequirement }) {
81
82
  * @returns
82
83
  * @group Components
83
84
  */
84
- export default function MultiFactorAuthentication({ mfaRequirement, ssoSetupUrl, }) {
85
- return (_jsx(Grid, { size: { xs: 'grow', lg: 8 }, children: _jsx(Box, { padding: 3, children: _jsx(Paper, { children: _jsx(Box, { padding: 3, children: _jsx(Grid, { container: true, spacing: 2, alignItems: "center", children: _jsxs(Grid, { size: { xs: 'grow' }, children: [_jsxs(Typography, { variant: "h4", fontWeight: "light", children: ["Multi Factor Authentication ", _jsx(MfaStatusChip, {})] }), _jsx(Box, { marginY: 1, children: _jsx(Divider, {}) }), _jsx(Typography, { variant: "body2", paragraph: true, children: "Multi factor authentication (MFA), also known as two factor authentication (2FA), is a best practice that requires a second authentication factor in addition to user name and password sign-in credentials. We strongly recommend enabling MFA to enhance your account security." }), _jsx(MfaSetup, { ssoSetupUrl: ssoSetupUrl, mfaRequirement: mfaRequirement })] }) }) }) }) }) }));
85
+ export default function MultiFactorAuthentication({ mfaRequirement, ssoSetupUrl, accessScopeLabel = 'App', }) {
86
+ return (_jsx(Grid, { size: { xs: 'grow', lg: 8 }, children: _jsx(Box, { padding: 3, children: _jsx(Paper, { children: _jsx(Box, { padding: 3, children: _jsx(Grid, { container: true, spacing: 2, alignItems: "center", children: _jsxs(Grid, { size: { xs: 'grow' }, children: [_jsxs(Typography, { variant: "h4", fontWeight: "light", children: ["Multi Factor Authentication", ' ', _jsx(MfaStatusChip, {})] }), _jsx(Box, { marginY: 1, children: _jsx(Divider, {}) }), _jsx(Typography, { variant: "body2", paragraph: true, children: "Multi factor authentication (MFA), also known as two factor authentication (2FA), is a best practice that requires a second authentication factor in addition to user name and password sign-in credentials. We strongly recommend enabling MFA to enhance your account security." }), _jsx(MfaSetup, { ssoSetupUrl: ssoSetupUrl, mfaRequirement: mfaRequirement, accessScopeLabel: accessScopeLabel })] }) }) }) }) }) }));
86
87
  }
87
88
  //# sourceMappingURL=MultiFactorAuthentication.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MultiFactorAuthentication.js","sourceRoot":"","sources":["../../../src/components/mfa/MultiFactorAuthentication.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react'\nimport {\n Box,\n Button,\n Divider,\n Grid,\n Paper,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { MiscTypes } from '@oneblink/types'\nimport MfaAuthenticatorAppDialog from './MfaAuthenticatorAppDialog'\nimport useMfa from '../../hooks/useMfa'\nimport MfaDisableDialog from './MfaDisableDialog'\nimport MfaRemovePhoneNumberDialog from './MfaRemovePhoneNumberDialog'\nimport MfaPhoneNumberDialog from './MfaPhoneNumberDialog'\nimport MfaMethodRow from './MfaMethodRow'\nimport MfaSuccessSnackbar from './MfaSuccessSnackbar'\nimport MfaErrorSnackbar from './MfaErrorSnackbar'\nimport MfaStatusChip from './MfaStatusChip'\nimport { formatMfaMethodNotAcceptedMessage } from '../../utils/mfa-requirement'\n\ntype Props = {\n mfaRequirement: MiscTypes.MfaRequirement | undefined\n ssoSetupUrl?: string\n}\n\nfunction MfaMethodList({ mfaRequirement }: Pick<Props, 'mfaRequirement'>) {\n const {\n mfaSettings,\n loadingError,\n isLoading,\n isSettingUpMfa,\n settingUpMfaMethod,\n isSettingPreferredMfaMethod,\n beginMfaSetup,\n beginDisablingMfaMethod,\n setPreferredMfaMethod,\n beginRemovingPhoneNumber,\n } = useMfa()\n\n const phoneDetail = useMemo(() => {\n if (!mfaSettings.sms.phoneNumber) {\n return undefined\n }\n\n if (!mfaSettings.sms.isPhoneNumberVerified) {\n return `Phone number: ${mfaSettings.sms.phoneNumber} (not verified)`\n }\n\n return `Phone number: ${mfaSettings.sms.phoneNumber}`\n }, [mfaSettings])\n\n const authenticatorMfaRequirementMessage = useMemo(() => {\n return formatMfaMethodNotAcceptedMessage('authenticatorApp', mfaRequirement)\n }, [mfaRequirement])\n\n const smsMfaRequirementMessage = useMemo(() => {\n return formatMfaMethodNotAcceptedMessage('sms', mfaRequirement)\n }, [mfaRequirement])\n\n if (isLoading) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\">\n Loading MFA methods...\n </Typography>\n )\n }\n\n if (loadingError) {\n return (\n <Typography variant=\"body2\" color=\"error\">\n We are unable to load your MFA methods. Please try again by clicking the\n reload button on the chip above.\n </Typography>\n )\n }\n\n return (\n <>\n <MfaMethodRow\n isEnabled={mfaSettings.authenticator.enabled}\n isPreferred={mfaSettings.authenticator.preferred}\n isSettingUp={isSettingUpMfa && settingUpMfaMethod === 'authenticator'}\n isSettingPreferredMfaMethod={isSettingPreferredMfaMethod}\n isSetupDisabled={!!loadingError || isSettingUpMfa}\n showSetupErrorTooltip={!!loadingError}\n title=\"Authenticator App\"\n description=\"Use an app like Google Authenticator or Microsoft Authenticator to generate 6-digit verification codes.\"\n mfaRequirementMessage={authenticatorMfaRequirementMessage}\n cypressPrefix=\"mfa-authenticator\"\n onSetup={() => beginMfaSetup('authenticator')}\n onDisable={() => beginDisablingMfaMethod('authenticator')}\n onSetPreferred={() => setPreferredMfaMethod('authenticator')}\n />\n <Divider sx={{ my: 2 }} />\n <MfaMethodRow\n isEnabled={mfaSettings.sms.enabled}\n isPreferred={mfaSettings.sms.preferred}\n isSettingUp={isSettingUpMfa && settingUpMfaMethod === 'sms'}\n isSettingPreferredMfaMethod={isSettingPreferredMfaMethod}\n isSetupDisabled={!!loadingError || isSettingUpMfa}\n showSetupErrorTooltip={!!loadingError}\n title=\"SMS\"\n description=\"Receive a one-time verification code via SMS each time MFA is required.\"\n detail={phoneDetail}\n mfaRequirementMessage={smsMfaRequirementMessage}\n cypressPrefix=\"mfa-sms\"\n onSetup={() => beginMfaSetup('sms')}\n onDisable={() => beginDisablingMfaMethod('sms')}\n onSetPreferred={() => setPreferredMfaMethod('sms')}\n extraButtons={\n !!mfaSettings.sms.phoneNumber && !mfaSettings.sms.enabled ? (\n <Button\n size=\"small\"\n variant=\"outlined\"\n disabled={!!loadingError}\n onClick={beginRemovingPhoneNumber}\n data-cypress=\"mfa-sms-remove-phone-button\"\n >\n Remove Phone\n </Button>\n ) : undefined\n }\n />\n </>\n )\n}\n\nfunction MfaSetup({ ssoSetupUrl, mfaRequirement }: Props) {\n const { isExternalIdentityProviderUser } = useMfa()\n\n if (ssoSetupUrl) {\n return (\n <Button\n variant=\"outlined\"\n size=\"small\"\n component=\"a\"\n href={ssoSetupUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n )\n }\n\n if (isExternalIdentityProviderUser) {\n return (\n <Tooltip title=\"MFA must be configured in your login provider.\">\n <span>\n <Button\n variant=\"outlined\"\n disabled={isExternalIdentityProviderUser}\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n </span>\n </Tooltip>\n )\n }\n\n return (\n <>\n <MfaMethodList mfaRequirement={mfaRequirement} />\n <MfaDisableDialog />\n <MfaRemovePhoneNumberDialog />\n <MfaPhoneNumberDialog />\n <MfaAuthenticatorAppDialog />\n <MfaErrorSnackbar />\n <MfaSuccessSnackbar />\n </>\n )\n}\n\n/**\n * React Component that provides a mechanism for app users to configure Multi\n * Factor Authentication. `<MfaProvider />` must be provided above this\n * component in the component tree.\n *\n * #### Example\n *\n * ```js\n * import * as React from 'react'\n * import {\n * MfaProvider,\n * MultiFactorAuthentication,\n * } from '@oneblink/apps-react'\n *\n * function Component() {\n * return <MultiFactorAuthentication mfaRequirement={undefined} />\n * }\n *\n * function AppWithMfaRequirement({ mfaRequirement }) {\n * return (\n * <MfaProvider>\n * <MultiFactorAuthentication mfaRequirement={mfaRequirement} />\n * </MfaProvider>\n * )\n * }\n * ```\n *\n * @param props\n * @param props.mfaRequirement - The MFA methods allowed by your administrator\n * for using this app. Pass `undefined` when the app has no MFA requirement.\n * Users can still enable other methods, but will be warned when their\n * configuration does not meet this requirement.\n * @returns\n * @group Components\n */\nexport default function MultiFactorAuthentication({\n mfaRequirement,\n ssoSetupUrl,\n}: Props) {\n return (\n <Grid size={{ xs: 'grow', lg: 8 }}>\n <Box padding={3}>\n <Paper>\n <Box padding={3}>\n <Grid container spacing={2} alignItems=\"center\">\n <Grid size={{ xs: 'grow' }}>\n <Typography variant=\"h4\" fontWeight=\"light\">\n Multi Factor Authentication <MfaStatusChip />\n </Typography>\n <Box marginY={1}>\n <Divider />\n </Box>\n <Typography variant=\"body2\" paragraph>\n Multi factor authentication (MFA), also known as two factor\n authentication (2FA), is a best practice that requires a\n second authentication factor in addition to user name and\n password sign-in credentials. We strongly recommend enabling\n MFA to enhance your account security.\n </Typography>\n <MfaSetup\n ssoSetupUrl={ssoSetupUrl}\n mfaRequirement={mfaRequirement}\n />\n </Grid>\n </Grid>\n </Box>\n </Paper>\n </Box>\n </Grid>\n )\n}\n"]}
1
+ {"version":3,"file":"MultiFactorAuthentication.js","sourceRoot":"","sources":["../../../src/components/mfa/MultiFactorAuthentication.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react'\nimport {\n Box,\n Button,\n Divider,\n Grid,\n Paper,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { MiscTypes } from '@oneblink/types'\nimport MfaAuthenticatorAppDialog from './MfaAuthenticatorAppDialog'\nimport useMfa from '../../hooks/useMfa'\nimport MfaDisableDialog from './MfaDisableDialog'\nimport MfaRemovePhoneNumberDialog from './MfaRemovePhoneNumberDialog'\nimport MfaPhoneNumberDialog from './MfaPhoneNumberDialog'\nimport MfaMethodRow from './MfaMethodRow'\nimport MfaSuccessSnackbar from './MfaSuccessSnackbar'\nimport MfaErrorSnackbar from './MfaErrorSnackbar'\nimport MfaStatusChip from './MfaStatusChip'\nimport {\n formatMfaMethodRequirementMessage,\n isMfaMethodUsedForLogin,\n} from '../../utils/mfa-requirement'\n\ntype Props = {\n mfaRequirement: MiscTypes.MfaRequirement | undefined\n ssoSetupUrl?: string\n accessScopeLabel?: string\n}\n\nfunction MfaMethodList({\n mfaRequirement,\n accessScopeLabel = 'app',\n}: Pick<Props, 'mfaRequirement' | 'accessScopeLabel'>) {\n const {\n mfaSettings,\n loadingError,\n isLoading,\n isSettingUpMfa,\n settingUpMfaMethod,\n isSettingPreferredMfaMethod,\n beginMfaSetup,\n beginDisablingMfaMethod,\n setPreferredMfaMethod,\n beginRemovingPhoneNumber,\n } = useMfa()\n\n const phoneDetail = useMemo(() => {\n if (!mfaSettings.sms.phoneNumber) {\n return undefined\n }\n\n if (!mfaSettings.sms.isPhoneNumberVerified) {\n return `Phone number: ${mfaSettings.sms.phoneNumber} (not verified)`\n }\n\n return `Phone number: ${mfaSettings.sms.phoneNumber}`\n }, [mfaSettings])\n\n const authenticatorMfaRequirementMessage = useMemo(() => {\n return formatMfaMethodRequirementMessage(\n 'authenticatorApp',\n mfaRequirement,\n mfaSettings,\n accessScopeLabel,\n )\n }, [accessScopeLabel, mfaRequirement, mfaSettings])\n\n const smsMfaRequirementMessage = useMemo(() => {\n return formatMfaMethodRequirementMessage(\n 'sms',\n mfaRequirement,\n mfaSettings,\n accessScopeLabel,\n )\n }, [accessScopeLabel, mfaRequirement, mfaSettings])\n\n if (isLoading) {\n return (\n <Typography variant=\"body2\" color=\"text.secondary\">\n Loading MFA methods...\n </Typography>\n )\n }\n\n if (loadingError) {\n return (\n <Typography variant=\"body2\" color=\"error\">\n We are unable to load your MFA methods. Please try again by clicking the\n reload button on the chip above.\n </Typography>\n )\n }\n\n return (\n <>\n <MfaMethodRow\n isEnabled={mfaSettings.authenticator.enabled}\n isPreferred={mfaSettings.authenticator.preferred}\n isUsedForLogin={isMfaMethodUsedForLogin(\n mfaSettings,\n 'authenticatorApp',\n )}\n isSettingUp={isSettingUpMfa && settingUpMfaMethod === 'authenticator'}\n isSettingPreferredMfaMethod={isSettingPreferredMfaMethod}\n isSetupDisabled={!!loadingError || isSettingUpMfa}\n showSetupErrorTooltip={!!loadingError}\n title=\"Authenticator App\"\n description=\"Use an app like Google Authenticator or Microsoft Authenticator to generate 6-digit verification codes.\"\n mfaRequirementMessage={authenticatorMfaRequirementMessage}\n mfaRequirementMessageIsWarning={\n !!mfaRequirement?.authenticatorApp &&\n !!authenticatorMfaRequirementMessage\n }\n cypressPrefix=\"mfa-authenticator\"\n onSetup={() => beginMfaSetup('authenticator')}\n onDisable={() => beginDisablingMfaMethod('authenticator')}\n onSetPreferred={() => setPreferredMfaMethod('authenticator')}\n />\n <Divider sx={{ my: 2 }} />\n <MfaMethodRow\n isEnabled={mfaSettings.sms.enabled}\n isPreferred={mfaSettings.sms.preferred}\n isUsedForLogin={isMfaMethodUsedForLogin(mfaSettings, 'sms')}\n isSettingUp={isSettingUpMfa && settingUpMfaMethod === 'sms'}\n isSettingPreferredMfaMethod={isSettingPreferredMfaMethod}\n isSetupDisabled={!!loadingError || isSettingUpMfa || !mfaSettings.sms.enabled}\n showSetupErrorTooltip={!!loadingError}\n title=\"SMS\"\n description=\"Receive a one-time verification code via SMS each time MFA is required.\"\n detail={phoneDetail}\n mfaRequirementMessage={smsMfaRequirementMessage}\n mfaRequirementMessageIsWarning={\n !!mfaRequirement?.sms && !!smsMfaRequirementMessage\n }\n cypressPrefix=\"mfa-sms\"\n onSetup={() => beginMfaSetup('sms')}\n onDisable={() => beginDisablingMfaMethod('sms')}\n onSetPreferred={() => setPreferredMfaMethod('sms')}\n extraButtons={\n !!mfaSettings.sms.phoneNumber && !mfaSettings.sms.enabled ? (\n <Button\n size=\"small\"\n variant=\"outlined\"\n disabled={!!loadingError}\n onClick={beginRemovingPhoneNumber}\n data-cypress=\"mfa-sms-remove-phone-button\"\n >\n Remove Phone\n </Button>\n ) : undefined\n }\n />\n </>\n )\n}\n\nfunction MfaSetup({ ssoSetupUrl, mfaRequirement, accessScopeLabel }: Props) {\n const { isExternalIdentityProviderUser } = useMfa()\n\n if (ssoSetupUrl) {\n return (\n <Button\n variant=\"outlined\"\n size=\"small\"\n component=\"a\"\n href={ssoSetupUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n )\n }\n\n if (isExternalIdentityProviderUser) {\n return (\n <Tooltip title=\"MFA must be configured in your login provider.\">\n <span>\n <Button\n variant=\"outlined\"\n disabled={isExternalIdentityProviderUser}\n data-cypress=\"configure-mfa-button\"\n >\n Configure MFA\n </Button>\n </span>\n </Tooltip>\n )\n }\n\n return (\n <>\n <MfaMethodList\n mfaRequirement={mfaRequirement}\n accessScopeLabel={accessScopeLabel}\n />\n <MfaDisableDialog />\n <MfaRemovePhoneNumberDialog />\n <MfaPhoneNumberDialog />\n <MfaAuthenticatorAppDialog />\n <MfaErrorSnackbar />\n <MfaSuccessSnackbar />\n </>\n )\n}\n\n/**\n * React Component that provides a mechanism for app users to configure Multi\n * Factor Authentication. `<MfaProvider />` must be provided above this\n * component in the component tree.\n *\n * #### Example\n *\n * ```js\n * import * as React from 'react'\n * import {\n * MfaProvider,\n * MultiFactorAuthentication,\n * } from '@oneblink/apps-react'\n *\n * function Component() {\n * return <MultiFactorAuthentication mfaRequirement={undefined} />\n * }\n *\n * function AppWithMfaRequirement({ mfaRequirement }) {\n * return (\n * <MfaProvider>\n * <MultiFactorAuthentication mfaRequirement={mfaRequirement} />\n * </MfaProvider>\n * )\n * }\n * ```\n *\n * @param props\n * @param props.mfaRequirement - The MFA methods allowed by your administrator\n * for using this app. Pass `undefined` when the app has no MFA requirement.\n * Users can still enable other methods, but will be warned when their\n * configuration does not meet this requirement.\n * @returns\n * @group Components\n */\nexport default function MultiFactorAuthentication({\n mfaRequirement,\n ssoSetupUrl,\n accessScopeLabel = 'App',\n}: Props) {\n return (\n <Grid size={{ xs: 'grow', lg: 8 }}>\n <Box padding={3}>\n <Paper>\n <Box padding={3}>\n <Grid container spacing={2} alignItems=\"center\">\n <Grid size={{ xs: 'grow' }}>\n <Typography variant=\"h4\" fontWeight=\"light\">\n Multi Factor Authentication{' '}\n <MfaStatusChip />\n </Typography>\n <Box marginY={1}>\n <Divider />\n </Box>\n <Typography variant=\"body2\" paragraph>\n Multi factor authentication (MFA), also known as two factor\n authentication (2FA), is a best practice that requires a\n second authentication factor in addition to user name and\n password sign-in credentials. We strongly recommend enabling\n MFA to enhance your account security.\n </Typography>\n <MfaSetup\n ssoSetupUrl={ssoSetupUrl}\n mfaRequirement={mfaRequirement}\n accessScopeLabel={accessScopeLabel}\n />\n </Grid>\n </Grid>\n </Box>\n </Paper>\n </Box>\n </Grid>\n )\n}\n"]}
@@ -0,0 +1,4 @@
1
+ .ob-figure__barcode-scanner {
2
+ width: 300px;
3
+ margin: auto;
4
+ }
package/dist/styles.css CHANGED
@@ -10360,3 +10360,8 @@ textarea:disabled {
10360
10360
  .ob-downloadable-files__error-pdf {
10361
10361
  padding-bottom: 1.5rem;
10362
10362
  }
10363
+
10364
+ .ob-figure__barcode-scanner {
10365
+ width: 300px;
10366
+ margin: auto;
10367
+ }
package/dist/styles.scss CHANGED
@@ -148,3 +148,4 @@ $section-padding-mobile: $section-padding-mobile-y $section-padding-mobile-x;
148
148
  @import './styles/nsw-point-address.scss';
149
149
  @import './styles/nsw-point-cadastral-parcel.scss';
150
150
  @import './styles/downloadable-files.scss';
151
+ @import './styles/barcode-scanner.scss';
@@ -1,12 +1,12 @@
1
1
  import { MiscTypes } from '@oneblink/types';
2
- import type { MfaSettings } from '../apps/services/AWSCognitoClient';
3
- export type { MfaSettings };
2
+ import type { LoggedInMfaMethod, MfaSettings } from '../apps/services/AWSCognitoClient';
3
+ export type { LoggedInMfaMethod, MfaSettings };
4
4
  export declare function isMfaRequired(mfaRequirement: MiscTypes.MfaRequirement | undefined): boolean;
5
5
  export type MfaRequirementMethod = keyof MiscTypes.MfaRequirement;
6
6
  export declare function mfaRequirementToSelectedMethods(mfaRequirement: MiscTypes.MfaRequirement | undefined): MfaRequirementMethod[];
7
7
  export declare function mfaSelectedMethodsToMfaRequirement(methods: MfaRequirementMethod[]): MiscTypes.MfaRequirement;
8
8
  export declare function formatMfaRequirementLabel(mfaRequirement: MiscTypes.MfaRequirement | undefined): string;
9
- export declare function formatMfaRequirementMethodLabel(method: MfaRequirementMethod): string;
9
+ export declare function isMfaMethodUsedForLogin(mfaSettings: MfaSettings, method: MfaRequirementMethod): boolean;
10
10
  export declare function userMeetsMfaRequirement(mfaRequirement: MiscTypes.MfaRequirement | undefined, mfaSettings: MfaSettings): boolean;
11
- export declare function formatMfaMethodNotAcceptedMessage(method: MfaRequirementMethod, mfaRequirement: MiscTypes.MfaRequirement | undefined, accessScopeLabel?: string): string | undefined;
12
11
  export declare function formatMfaSetupRequiredMessage(mfaRequirement: MiscTypes.MfaRequirement | undefined, mfaSettings: MfaSettings, accessScopeLabel?: string): string | undefined;
12
+ export declare function formatMfaMethodRequirementMessage(method: MfaRequirementMethod, mfaRequirement: MiscTypes.MfaRequirement | undefined, mfaSettings: MfaSettings, accessScopeLabel?: string): string | undefined;
@@ -38,7 +38,7 @@ export function formatMfaRequirementLabel(mfaRequirement) {
38
38
  const methodList = joinArray(selectedMethods.map(formatMfaRequirementMethodLabel), 'disjunction');
39
39
  return `MFA Required (${methodList} only)`;
40
40
  }
41
- export function formatMfaRequirementMethodLabel(method) {
41
+ function formatMfaRequirementMethodLabel(method) {
42
42
  switch (method) {
43
43
  case 'sms':
44
44
  return 'SMS';
@@ -50,23 +50,27 @@ export function formatMfaRequirementMethodLabel(method) {
50
50
  }
51
51
  }
52
52
  }
53
+ function mfaRequirementMethodToLoggedInMfaMethod(method) {
54
+ return method === 'sms' ? 'SMS_MFA' : 'SOFTWARE_TOKEN_MFA';
55
+ }
56
+ export function isMfaMethodUsedForLogin(mfaSettings, method) {
57
+ return (mfaSettings.loggedInWithMfaMethod ===
58
+ mfaRequirementMethodToLoggedInMfaMethod(method));
59
+ }
53
60
  export function userMeetsMfaRequirement(mfaRequirement, mfaSettings) {
54
61
  if (!isMfaRequired(mfaRequirement)) {
55
62
  return true;
56
63
  }
57
- if ((mfaRequirement === null || mfaRequirement === void 0 ? void 0 : mfaRequirement.sms) &&
58
- mfaSettings.sms.enabled &&
59
- mfaSettings.sms.preferred) {
64
+ if ((mfaRequirement === null || mfaRequirement === void 0 ? void 0 : mfaRequirement.sms) && mfaSettings.loggedInWithMfaMethod === 'SMS_MFA') {
60
65
  return true;
61
66
  }
62
67
  if ((mfaRequirement === null || mfaRequirement === void 0 ? void 0 : mfaRequirement.authenticatorApp) &&
63
- mfaSettings.authenticator.enabled &&
64
- mfaSettings.authenticator.preferred) {
68
+ mfaSettings.loggedInWithMfaMethod === 'SOFTWARE_TOKEN_MFA') {
65
69
  return true;
66
70
  }
67
71
  return false;
68
72
  }
69
- export function formatMfaMethodNotAcceptedMessage(method, mfaRequirement, accessScopeLabel = 'app') {
73
+ function formatMfaMethodNotAcceptedMessage(method, mfaRequirement, accessScopeLabel = 'app') {
70
74
  if (!mfaRequirement || !isMfaRequired(mfaRequirement)) {
71
75
  return undefined;
72
76
  }
@@ -77,24 +81,69 @@ export function formatMfaMethodNotAcceptedMessage(method, mfaRequirement, access
77
81
  const methodList = joinArray(requiredMethods.map(formatMfaRequirementMethodLabel), 'disjunction');
78
82
  return `This MFA method is not sufficient for using this ${accessScopeLabel.toLowerCase()}. Your administrator requires ${methodList} multi factor authentication.`;
79
83
  }
84
+ function isMfaMethodEnabled(mfaSettings, method) {
85
+ return method === 'sms'
86
+ ? mfaSettings.sms.enabled
87
+ : mfaSettings.authenticator.enabled;
88
+ }
89
+ function isMfaMethodPreferred(mfaSettings, method) {
90
+ return method === 'sms'
91
+ ? mfaSettings.sms.preferred
92
+ : mfaSettings.authenticator.preferred;
93
+ }
94
+ function hasPreferredEnabledRequiredMethod(mfaRequirement, mfaSettings) {
95
+ return mfaRequirementToSelectedMethods(mfaRequirement).some((method) => isMfaMethodEnabled(mfaSettings, method) &&
96
+ isMfaMethodPreferred(mfaSettings, method));
97
+ }
80
98
  export function formatMfaSetupRequiredMessage(mfaRequirement, mfaSettings, accessScopeLabel = 'Account') {
81
- if (!isMfaRequired(mfaRequirement) ||
99
+ if (!mfaRequirement ||
100
+ !isMfaRequired(mfaRequirement) ||
82
101
  userMeetsMfaRequirement(mfaRequirement, mfaSettings)) {
83
102
  return undefined;
84
103
  }
85
104
  const requiredMethods = mfaRequirementToSelectedMethods(mfaRequirement);
86
- const hasAnyMfaEnabled = mfaSettings.authenticator.enabled || mfaSettings.sms.enabled;
87
105
  if (requiredMethods.length === 1) {
88
- const methodLabel = formatMfaRequirementMethodLabel(requiredMethods[0]);
89
- if (hasAnyMfaEnabled) {
90
- return `requires ${methodLabel} multi factor authentication. You have a different MFA method configured, but that method is not accepted for this ${accessScopeLabel.toLowerCase()}.`;
106
+ const method = requiredMethods[0];
107
+ const methodLabel = formatMfaRequirementMethodLabel(method);
108
+ if (!isMfaMethodEnabled(mfaSettings, method)) {
109
+ return `requires ${methodLabel} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`;
110
+ }
111
+ if (!isMfaMethodPreferred(mfaSettings, method)) {
112
+ return `requires ${methodLabel} multi factor authentication. Please change your preferred MFA method to ${methodLabel} to access this ${accessScopeLabel}.`;
91
113
  }
92
- return `requires ${methodLabel} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`;
114
+ return `requires ${methodLabel} multi factor authentication. Now that ${methodLabel} is your preferred MFA method, you must log out and log back in to access this ${accessScopeLabel}.`;
93
115
  }
94
116
  const methodList = joinArray(requiredMethods.map(formatMfaRequirementMethodLabel), 'disjunction');
95
- if (hasAnyMfaEnabled) {
96
- return `requires ${methodList} multi factor authentication. Your current MFA method is not accepted for this ${accessScopeLabel.toLowerCase()}.`;
117
+ const hasAnyMfaEnabled = mfaSettings.authenticator.enabled || mfaSettings.sms.enabled;
118
+ if (!hasAnyMfaEnabled) {
119
+ return `requires ${methodList} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`;
120
+ }
121
+ if (!hasPreferredEnabledRequiredMethod(mfaRequirement, mfaSettings)) {
122
+ return `requires ${methodList} multi factor authentication. Please change your preferred MFA method to one of the accepted methods to access this ${accessScopeLabel}.`;
123
+ }
124
+ return `requires ${methodList} multi factor authentication. Now that your preferred MFA method meets this requirement, you must log out and log back in to access this ${accessScopeLabel}.`;
125
+ }
126
+ export function formatMfaMethodRequirementMessage(method, mfaRequirement, mfaSettings, accessScopeLabel = 'app') {
127
+ if (!mfaRequirement || !isMfaRequired(mfaRequirement)) {
128
+ return undefined;
129
+ }
130
+ const scope = accessScopeLabel.toLowerCase();
131
+ if (!mfaRequirement[method]) {
132
+ return formatMfaMethodNotAcceptedMessage(method, mfaRequirement, accessScopeLabel);
133
+ }
134
+ if (userMeetsMfaRequirement(mfaRequirement, mfaSettings)) {
135
+ return;
136
+ }
137
+ const methodLabel = formatMfaRequirementMethodLabel(method);
138
+ const isMethodEnabled = isMfaMethodEnabled(mfaSettings, method);
139
+ const isMethodPreferred = isMfaMethodPreferred(mfaSettings, method);
140
+ const firstSentence = `Your administrator requires ${methodLabel} multi factor authentication.`;
141
+ if (!isMethodEnabled) {
142
+ return `${firstSentence} Setup ${methodLabel} to access this ${scope}`;
143
+ }
144
+ if (!isMethodPreferred) {
145
+ return `${firstSentence} Set ${methodLabel} as your preferred MFA method to access this ${scope}.`;
97
146
  }
98
- return `requires ${methodList} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`;
147
+ return `${firstSentence} Now that ${methodLabel} is your preferred MFA method, you must log out and log back in to access this ${scope}.`;
99
148
  }
100
149
  //# sourceMappingURL=mfa-requirement.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mfa-requirement.js","sourceRoot":"","sources":["../../src/utils/mfa-requirement.ts"],"names":[],"mappings":"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","sourcesContent":["import { MiscTypes } from '@oneblink/types'\r\nimport type { MfaSettings } from '../apps/services/AWSCognitoClient'\r\nimport { joinArray } from './joinArray'\r\n\r\nexport type { MfaSettings }\r\n\r\nexport function isMfaRequired(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): boolean {\r\n return (\r\n !!mfaRequirement && (mfaRequirement.sms || mfaRequirement.authenticatorApp)\r\n )\r\n}\r\n\r\nexport type MfaRequirementMethod = keyof MiscTypes.MfaRequirement\r\n\r\nconst MFA_REQUIREMENT_METHOD_KEYS = Object.keys({\r\n sms: false,\r\n authenticatorApp: false,\r\n} satisfies MiscTypes.MfaRequirement) as MfaRequirementMethod[]\r\n\r\nexport function mfaRequirementToSelectedMethods(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): MfaRequirementMethod[] {\r\n const checkboxState = {\r\n sms: mfaRequirement?.sms ?? false,\r\n authenticatorApp: mfaRequirement?.authenticatorApp ?? false,\r\n }\r\n const methods: MfaRequirementMethod[] = []\r\n\r\n if (checkboxState.authenticatorApp) {\r\n methods.push('authenticatorApp')\r\n }\r\n\r\n if (checkboxState.sms) {\r\n methods.push('sms')\r\n }\r\n\r\n return methods\r\n}\r\n\r\nexport function mfaSelectedMethodsToMfaRequirement(\r\n methods: MfaRequirementMethod[],\r\n): MiscTypes.MfaRequirement {\r\n return {\r\n sms: methods.includes('sms'),\r\n authenticatorApp: methods.includes('authenticatorApp'),\r\n }\r\n}\r\n\r\nexport function formatMfaRequirementLabel(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): string {\r\n if (!isMfaRequired(mfaRequirement)) {\r\n return 'MFA Optional'\r\n }\r\n\r\n const selectedMethods = mfaRequirementToSelectedMethods(mfaRequirement)\r\n\r\n if (selectedMethods.length === MFA_REQUIREMENT_METHOD_KEYS.length) {\r\n return 'MFA Required'\r\n }\r\n\r\n const methodList = joinArray(\r\n selectedMethods.map(formatMfaRequirementMethodLabel),\r\n 'disjunction',\r\n )\r\n\r\n return `MFA Required (${methodList} only)`\r\n}\r\n\r\nexport function formatMfaRequirementMethodLabel(\r\n method: MfaRequirementMethod,\r\n): string {\r\n switch (method) {\r\n case 'sms':\r\n return 'SMS'\r\n case 'authenticatorApp':\r\n return 'Authenticator App'\r\n default: {\r\n const n: never = method\r\n return n\r\n }\r\n }\r\n}\r\n\r\nexport function userMeetsMfaRequirement(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n mfaSettings: MfaSettings,\r\n): boolean {\r\n if (!isMfaRequired(mfaRequirement)) {\r\n return true\r\n }\r\n\r\n if (\r\n mfaRequirement?.sms &&\r\n mfaSettings.sms.enabled &&\r\n mfaSettings.sms.preferred\r\n ) {\r\n return true\r\n }\r\n\r\n if (\r\n mfaRequirement?.authenticatorApp &&\r\n mfaSettings.authenticator.enabled &&\r\n mfaSettings.authenticator.preferred\r\n ) {\r\n return true\r\n }\r\n\r\n return false\r\n}\r\n\r\nexport function formatMfaMethodNotAcceptedMessage(\r\n method: MfaRequirementMethod,\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n accessScopeLabel = 'app',\r\n): string | undefined {\r\n if (!mfaRequirement || !isMfaRequired(mfaRequirement)) {\r\n return undefined\r\n }\r\n\r\n if (mfaRequirement[method]) {\r\n return undefined\r\n }\r\n\r\n const requiredMethods = mfaRequirementToSelectedMethods(mfaRequirement)\r\n\r\n const methodList = joinArray(\r\n requiredMethods.map(formatMfaRequirementMethodLabel),\r\n 'disjunction',\r\n )\r\n\r\n return `This MFA method is not sufficient for using this ${accessScopeLabel.toLowerCase()}. Your administrator requires ${methodList} multi factor authentication.`\r\n}\r\n\r\nexport function formatMfaSetupRequiredMessage(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n mfaSettings: MfaSettings,\r\n accessScopeLabel = 'Account',\r\n): string | undefined {\r\n if (\r\n !isMfaRequired(mfaRequirement) ||\r\n userMeetsMfaRequirement(mfaRequirement, mfaSettings)\r\n ) {\r\n return undefined\r\n }\r\n\r\n const requiredMethods = mfaRequirementToSelectedMethods(mfaRequirement)\r\n const hasAnyMfaEnabled =\r\n mfaSettings.authenticator.enabled || mfaSettings.sms.enabled\r\n\r\n if (requiredMethods.length === 1) {\r\n const methodLabel = formatMfaRequirementMethodLabel(requiredMethods[0])\r\n\r\n if (hasAnyMfaEnabled) {\r\n return `requires ${methodLabel} multi factor authentication. You have a different MFA method configured, but that method is not accepted for this ${accessScopeLabel.toLowerCase()}.`\r\n }\r\n\r\n return `requires ${methodLabel} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`\r\n }\r\n\r\n const methodList = joinArray(\r\n requiredMethods.map(formatMfaRequirementMethodLabel),\r\n 'disjunction',\r\n )\r\n\r\n if (hasAnyMfaEnabled) {\r\n return `requires ${methodList} multi factor authentication. Your current MFA method is not accepted for this ${accessScopeLabel.toLowerCase()}.`\r\n }\r\n\r\n return `requires ${methodList} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`\r\n}\r\n"]}
1
+ {"version":3,"file":"mfa-requirement.js","sourceRoot":"","sources":["../../src/utils/mfa-requirement.ts"],"names":[],"mappings":"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","sourcesContent":["import { MiscTypes } from '@oneblink/types'\r\nimport type {\r\n LoggedInMfaMethod,\r\n MfaSettings,\r\n} from '../apps/services/AWSCognitoClient'\r\nimport { joinArray } from './joinArray'\r\n\r\nexport type { LoggedInMfaMethod, MfaSettings }\r\n\r\nexport function isMfaRequired(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): boolean {\r\n return (\r\n !!mfaRequirement && (mfaRequirement.sms || mfaRequirement.authenticatorApp)\r\n )\r\n}\r\n\r\nexport type MfaRequirementMethod = keyof MiscTypes.MfaRequirement\r\n\r\nconst MFA_REQUIREMENT_METHOD_KEYS = Object.keys({\r\n sms: false,\r\n authenticatorApp: false,\r\n} satisfies MiscTypes.MfaRequirement) as MfaRequirementMethod[]\r\n\r\nexport function mfaRequirementToSelectedMethods(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): MfaRequirementMethod[] {\r\n const checkboxState = {\r\n sms: mfaRequirement?.sms ?? false,\r\n authenticatorApp: mfaRequirement?.authenticatorApp ?? false,\r\n }\r\n const methods: MfaRequirementMethod[] = []\r\n\r\n if (checkboxState.authenticatorApp) {\r\n methods.push('authenticatorApp')\r\n }\r\n\r\n if (checkboxState.sms) {\r\n methods.push('sms')\r\n }\r\n\r\n return methods\r\n}\r\n\r\nexport function mfaSelectedMethodsToMfaRequirement(\r\n methods: MfaRequirementMethod[],\r\n): MiscTypes.MfaRequirement {\r\n return {\r\n sms: methods.includes('sms'),\r\n authenticatorApp: methods.includes('authenticatorApp'),\r\n }\r\n}\r\n\r\nexport function formatMfaRequirementLabel(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): string {\r\n if (!isMfaRequired(mfaRequirement)) {\r\n return 'MFA Optional'\r\n }\r\n\r\n const selectedMethods = mfaRequirementToSelectedMethods(mfaRequirement)\r\n\r\n if (selectedMethods.length === MFA_REQUIREMENT_METHOD_KEYS.length) {\r\n return 'MFA Required'\r\n }\r\n\r\n const methodList = joinArray(\r\n selectedMethods.map(formatMfaRequirementMethodLabel),\r\n 'disjunction',\r\n )\r\n\r\n return `MFA Required (${methodList} only)`\r\n}\r\n\r\nfunction formatMfaRequirementMethodLabel(method: MfaRequirementMethod): string {\r\n switch (method) {\r\n case 'sms':\r\n return 'SMS'\r\n case 'authenticatorApp':\r\n return 'Authenticator App'\r\n default: {\r\n const n: never = method\r\n return n\r\n }\r\n }\r\n}\r\n\r\nfunction mfaRequirementMethodToLoggedInMfaMethod(\r\n method: MfaRequirementMethod,\r\n): Exclude<LoggedInMfaMethod, 'NO_MFA_ENABLED'> {\r\n return method === 'sms' ? 'SMS_MFA' : 'SOFTWARE_TOKEN_MFA'\r\n}\r\n\r\nexport function isMfaMethodUsedForLogin(\r\n mfaSettings: MfaSettings,\r\n method: MfaRequirementMethod,\r\n): boolean {\r\n return (\r\n mfaSettings.loggedInWithMfaMethod ===\r\n mfaRequirementMethodToLoggedInMfaMethod(method)\r\n )\r\n}\r\n\r\nexport function userMeetsMfaRequirement(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n mfaSettings: MfaSettings,\r\n): boolean {\r\n if (!isMfaRequired(mfaRequirement)) {\r\n return true\r\n }\r\n\r\n if (mfaRequirement?.sms && mfaSettings.loggedInWithMfaMethod === 'SMS_MFA') {\r\n return true\r\n }\r\n\r\n if (\r\n mfaRequirement?.authenticatorApp &&\r\n mfaSettings.loggedInWithMfaMethod === 'SOFTWARE_TOKEN_MFA'\r\n ) {\r\n return true\r\n }\r\n\r\n return false\r\n}\r\n\r\nfunction formatMfaMethodNotAcceptedMessage(\r\n method: MfaRequirementMethod,\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n accessScopeLabel = 'app',\r\n): string | undefined {\r\n if (!mfaRequirement || !isMfaRequired(mfaRequirement)) {\r\n return undefined\r\n }\r\n\r\n if (mfaRequirement[method]) {\r\n return undefined\r\n }\r\n\r\n const requiredMethods = mfaRequirementToSelectedMethods(mfaRequirement)\r\n\r\n const methodList = joinArray(\r\n requiredMethods.map(formatMfaRequirementMethodLabel),\r\n 'disjunction',\r\n )\r\n\r\n return `This MFA method is not sufficient for using this ${accessScopeLabel.toLowerCase()}. Your administrator requires ${methodList} multi factor authentication.`\r\n}\r\n\r\nfunction isMfaMethodEnabled(\r\n mfaSettings: MfaSettings,\r\n method: MfaRequirementMethod,\r\n): boolean {\r\n return method === 'sms'\r\n ? mfaSettings.sms.enabled\r\n : mfaSettings.authenticator.enabled\r\n}\r\n\r\nfunction isMfaMethodPreferred(\r\n mfaSettings: MfaSettings,\r\n method: MfaRequirementMethod,\r\n): boolean {\r\n return method === 'sms'\r\n ? mfaSettings.sms.preferred\r\n : mfaSettings.authenticator.preferred\r\n}\r\n\r\nfunction hasPreferredEnabledRequiredMethod(\r\n mfaRequirement: MiscTypes.MfaRequirement,\r\n mfaSettings: MfaSettings,\r\n): boolean {\r\n return mfaRequirementToSelectedMethods(mfaRequirement).some(\r\n (method) =>\r\n isMfaMethodEnabled(mfaSettings, method) &&\r\n isMfaMethodPreferred(mfaSettings, method),\r\n )\r\n}\r\n\r\nexport function formatMfaSetupRequiredMessage(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n mfaSettings: MfaSettings,\r\n accessScopeLabel = 'Account',\r\n): string | undefined {\r\n if (\r\n !mfaRequirement ||\r\n !isMfaRequired(mfaRequirement) ||\r\n userMeetsMfaRequirement(mfaRequirement, mfaSettings)\r\n ) {\r\n return undefined\r\n }\r\n\r\n const requiredMethods = mfaRequirementToSelectedMethods(mfaRequirement)\r\n\r\n if (requiredMethods.length === 1) {\r\n const method = requiredMethods[0]\r\n const methodLabel = formatMfaRequirementMethodLabel(method)\r\n\r\n if (!isMfaMethodEnabled(mfaSettings, method)) {\r\n return `requires ${methodLabel} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`\r\n }\r\n\r\n if (!isMfaMethodPreferred(mfaSettings, method)) {\r\n return `requires ${methodLabel} multi factor authentication. Please change your preferred MFA method to ${methodLabel} to access this ${accessScopeLabel}.`\r\n }\r\n\r\n return `requires ${methodLabel} multi factor authentication. Now that ${methodLabel} is your preferred MFA method, you must log out and log back in to access this ${accessScopeLabel}.`\r\n }\r\n\r\n const methodList = joinArray(\r\n requiredMethods.map(formatMfaRequirementMethodLabel),\r\n 'disjunction',\r\n )\r\n const hasAnyMfaEnabled =\r\n mfaSettings.authenticator.enabled || mfaSettings.sms.enabled\r\n\r\n if (!hasAnyMfaEnabled) {\r\n return `requires ${methodList} multi factor authentication to be configured before accessing this ${accessScopeLabel}.`\r\n }\r\n\r\n if (!hasPreferredEnabledRequiredMethod(mfaRequirement, mfaSettings)) {\r\n return `requires ${methodList} multi factor authentication. Please change your preferred MFA method to one of the accepted methods to access this ${accessScopeLabel}.`\r\n }\r\n\r\n return `requires ${methodList} multi factor authentication. Now that your preferred MFA method meets this requirement, you must log out and log back in to access this ${accessScopeLabel}.`\r\n}\r\n\r\nexport function formatMfaMethodRequirementMessage(\r\n method: MfaRequirementMethod,\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n mfaSettings: MfaSettings,\r\n accessScopeLabel = 'app',\r\n): string | undefined {\r\n if (!mfaRequirement || !isMfaRequired(mfaRequirement)) {\r\n return undefined\r\n }\r\n\r\n const scope = accessScopeLabel.toLowerCase()\r\n\r\n if (!mfaRequirement[method]) {\r\n return formatMfaMethodNotAcceptedMessage(\r\n method,\r\n mfaRequirement,\r\n accessScopeLabel,\r\n )\r\n }\r\n\r\n if (userMeetsMfaRequirement(mfaRequirement, mfaSettings)) {\r\n return\r\n }\r\n\r\n const methodLabel = formatMfaRequirementMethodLabel(method)\r\n const isMethodEnabled = isMfaMethodEnabled(mfaSettings, method)\r\n const isMethodPreferred = isMfaMethodPreferred(mfaSettings, method)\r\n\r\n const firstSentence = `Your administrator requires ${methodLabel} multi factor authentication.`\r\n\r\n if (!isMethodEnabled) {\r\n return `${firstSentence} Setup ${methodLabel} to access this ${scope}`\r\n }\r\n\r\n if (!isMethodPreferred) {\r\n return `${firstSentence} Set ${methodLabel} as your preferred MFA method to access this ${scope}.`\r\n }\r\n\r\n return `${firstSentence} Now that ${methodLabel} is your preferred MFA method, you must log out and log back in to access this ${scope}.`\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oneblink/apps-react",
3
3
  "description": "Helper functions for OneBlink apps in ReactJS.",
4
- "version": "11.0.0-beta.8",
4
+ "version": "11.0.0",
5
5
  "author": "OneBlink <developers@oneblink.io> (https://oneblink.io)",
6
6
  "bugs": {
7
7
  "url": "https://github.com/oneblink/apps-react/issues"