@oneblink/apps-react 11.0.0-beta.1 → 11.0.0-beta.2

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.
Files changed (35) hide show
  1. package/dist/apps/auth-service.d.ts +3 -3
  2. package/dist/apps/auth-service.js +2 -2
  3. package/dist/apps/auth-service.js.map +1 -1
  4. package/dist/apps/index.d.ts +10 -0
  5. package/dist/apps/index.js +10 -0
  6. package/dist/apps/index.js.map +1 -1
  7. package/dist/apps/mfa-service.d.ts +4 -0
  8. package/dist/apps/mfa-service.js +3 -0
  9. package/dist/apps/mfa-service.js.map +1 -0
  10. package/dist/apps/services/cognito.d.ts +3 -3
  11. package/dist/apps/services/cognito.js +3 -3
  12. package/dist/apps/services/cognito.js.map +1 -1
  13. package/dist/components/mfa/MfaAuthenticatorAppDialog.js +2 -2
  14. package/dist/components/mfa/MfaAuthenticatorAppDialog.js.map +1 -1
  15. package/dist/components/mfa/MfaMethodRow.d.ts +2 -1
  16. package/dist/components/mfa/MfaMethodRow.js +3 -3
  17. package/dist/components/mfa/MfaMethodRow.js.map +1 -1
  18. package/dist/components/mfa/MultiFactorAuthentication.d.ts +11 -10
  19. package/dist/components/mfa/MultiFactorAuthentication.js +20 -14
  20. package/dist/components/mfa/MultiFactorAuthentication.js.map +1 -1
  21. package/dist/hooks/useLogin.d.ts +2 -2
  22. package/dist/hooks/useLogin.js.map +1 -1
  23. package/dist/hooks/useMfa.d.ts +66 -29
  24. package/dist/hooks/useMfa.js +85 -43
  25. package/dist/hooks/useMfa.js.map +1 -1
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.js +1 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/utils/joinArray.d.ts +1 -0
  30. package/dist/utils/joinArray.js +7 -0
  31. package/dist/utils/joinArray.js.map +1 -0
  32. package/dist/utils/mfa-requirement.d.ts +12 -0
  33. package/dist/utils/mfa-requirement.js +96 -0
  34. package/dist/utils/mfa-requirement.js.map +1 -0
  35. package/package.json +1 -1
@@ -10,7 +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
- function MfaMethodList() {
13
+ import { formatMfaMethodNotAcceptedMessage } from '../../utils/mfa-requirement';
14
+ function MfaMethodList({ mfaRequirement }) {
14
15
  const { mfaSettings, loadingError, isLoading, isSettingUpMfa, settingUpMfaMethod, isSettingPreferredMfaMethod, beginMfaSetup, beginDisablingMfaMethod, setPreferredMfaMethod, beginRemovingPhoneNumber, } = useMfa();
15
16
  const phoneDetail = useMemo(() => {
16
17
  if (!mfaSettings.sms.phoneNumber) {
@@ -21,15 +22,21 @@ function MfaMethodList() {
21
22
  }
22
23
  return `Phone number: ${mfaSettings.sms.phoneNumber}`;
23
24
  }, [mfaSettings]);
25
+ const authenticatorMfaRequirementMessage = useMemo(() => {
26
+ return formatMfaMethodNotAcceptedMessage('authenticatorApp', mfaRequirement);
27
+ }, [mfaRequirement]);
28
+ const smsMfaRequirementMessage = useMemo(() => {
29
+ return formatMfaMethodNotAcceptedMessage('sms', mfaRequirement);
30
+ }, [mfaRequirement]);
24
31
  if (isLoading) {
25
32
  return (_jsx(Typography, { variant: "body2", color: "text.secondary", children: "Loading MFA methods..." }));
26
33
  }
27
34
  if (loadingError) {
28
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." }));
29
36
  }
30
- 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.", 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, 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, 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 })] }));
31
38
  }
32
- function MfaSetup({ ssoSetupUrl }) {
39
+ function MfaSetup({ ssoSetupUrl, mfaRequirement }) {
33
40
  const { isExternalIdentityProviderUser } = useMfa();
34
41
  if (ssoSetupUrl) {
35
42
  return (_jsx(Button, { variant: "outlined", size: "small", component: "a", href: ssoSetupUrl, target: "_blank", rel: "noopener noreferrer", "data-cypress": "configure-mfa-button", children: "Configure MFA" }));
@@ -37,7 +44,7 @@ function MfaSetup({ ssoSetupUrl }) {
37
44
  if (isExternalIdentityProviderUser) {
38
45
  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" }) }) }));
39
46
  }
40
- return (_jsxs(_Fragment, { children: [_jsx(MfaMethodList, {}), _jsx(MfaDisableDialog, {}), _jsx(MfaRemovePhoneNumberDialog, {}), _jsx(MfaPhoneNumberDialog, {}), _jsx(MfaAuthenticatorAppDialog, {}), _jsx(MfaErrorSnackbar, {}), _jsx(MfaSuccessSnackbar, {})] }));
47
+ return (_jsxs(_Fragment, { children: [_jsx(MfaMethodList, { mfaRequirement: mfaRequirement }), _jsx(MfaDisableDialog, {}), _jsx(MfaRemovePhoneNumberDialog, {}), _jsx(MfaPhoneNumberDialog, {}), _jsx(MfaAuthenticatorAppDialog, {}), _jsx(MfaErrorSnackbar, {}), _jsx(MfaSuccessSnackbar, {})] }));
41
48
  }
42
49
  /**
43
50
  * React Component that provides a mechanism for app users to configure Multi
@@ -54,28 +61,27 @@ function MfaSetup({ ssoSetupUrl }) {
54
61
  * } from '@oneblink/apps-react'
55
62
  *
56
63
  * function Component() {
57
- * return <MultiFactorAuthentication />
64
+ * return <MultiFactorAuthentication mfaRequirement={undefined} />
58
65
  * }
59
66
  *
60
- * function App() {
67
+ * function AppWithMfaRequirement({ mfaRequirement }) {
61
68
  * return (
62
69
  * <MfaProvider>
63
- * <Component />
70
+ * <MultiFactorAuthentication mfaRequirement={mfaRequirement} />
64
71
  * </MfaProvider>
65
72
  * )
66
73
  * }
67
- *
68
- * const root = document.getElementById('root')
69
- * if (root) {
70
- * ReactDOM.render(<App />, root)
71
- * }
72
74
  * ```
73
75
  *
74
76
  * @param props
77
+ * @param props.mfaRequirement - The MFA methods allowed by your administrator
78
+ * for using this app. Pass `undefined` when the app has no MFA requirement.
79
+ * Users can still enable other methods, but will be warned when their
80
+ * configuration does not meet this requirement.
75
81
  * @returns
76
82
  * @group Components
77
83
  */
78
- export default function MultiFactorAuthentication({ ssoSetupUrl }) {
79
- 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 })] }) }) }) }) }) }));
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 })] }) }) }) }) }) }));
80
86
  }
81
87
  //# 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 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'\n\ntype Props = {\n ssoSetupUrl: string | undefined\n}\n\nfunction MfaMethodList() {\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 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={\n isSettingUpMfa && settingUpMfaMethod === 'authenticator'\n }\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 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 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 }: 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 <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 />\n * }\n *\n * function App() {\n * return (\n * <MfaProvider>\n * <Component />\n * </MfaProvider>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param props\n * @returns\n * @group Components\n */\nexport default function MultiFactorAuthentication({ ssoSetupUrl }: 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 ssoSetupUrl={ssoSetupUrl} />\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":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EACL,GAAG,EACH,MAAM,EACN,OAAO,EACP,IAAI,EACJ,KAAK,EACL,OAAO,EACP,UAAU,GACX,MAAM,eAAe,CAAA;AAEtB,OAAO,yBAAyB,MAAM,6BAA6B,CAAA;AACnE,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,OAAO,0BAA0B,MAAM,8BAA8B,CAAA;AACrE,OAAO,oBAAoB,MAAM,wBAAwB,CAAA;AACzD,OAAO,YAAY,MAAM,gBAAgB,CAAA;AACzC,OAAO,kBAAkB,MAAM,sBAAsB,CAAA;AACrD,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,iCAAiC,EAAE,MAAM,6BAA6B,CAAA;AAO/E,SAAS,aAAa,CAAC,EAAE,cAAc,EAAiC;IACtE,MAAM,EACJ,WAAW,EACX,YAAY,EACZ,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,2BAA2B,EAC3B,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,GACzB,GAAG,MAAM,EAAE,CAAA;IAEZ,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACjC,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;YAC3C,OAAO,iBAAiB,WAAW,CAAC,GAAG,CAAC,WAAW,iBAAiB,CAAA;QACtE,CAAC;QAED,OAAO,iBAAiB,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,CAAA;IACvD,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,MAAM,kCAAkC,GAAG,OAAO,CAAC,GAAG,EAAE;QACtD,OAAO,iCAAiC,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAA;IAC9E,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAA;IAEpB,MAAM,wBAAwB,GAAG,OAAO,CAAC,GAAG,EAAE;QAC5C,OAAO,iCAAiC,CAAC,KAAK,EAAE,cAAc,CAAC,CAAA;IACjE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAA;IAEpB,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CACL,KAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,KAAK,EAAC,gBAAgB,uCAErC,CACd,CAAA;IACH,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,CACL,KAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,KAAK,EAAC,OAAO,0HAG5B,CACd,CAAA;IACH,CAAC;IAED,OAAO,CACL,8BACE,KAAC,YAAY,IACX,SAAS,EAAE,WAAW,CAAC,aAAa,CAAC,OAAO,EAC5C,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,SAAS,EAChD,WAAW,EAAE,cAAc,IAAI,kBAAkB,KAAK,eAAe,EACrE,2BAA2B,EAAE,2BAA2B,EACxD,eAAe,EAAE,CAAC,CAAC,YAAY,IAAI,cAAc,EACjD,qBAAqB,EAAE,CAAC,CAAC,YAAY,EACrC,KAAK,EAAC,mBAAmB,EACzB,WAAW,EAAC,yGAAyG,EACrH,qBAAqB,EAAE,kCAAkC,EACzD,aAAa,EAAC,mBAAmB,EACjC,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,EAC7C,SAAS,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,eAAe,CAAC,EACzD,cAAc,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,eAAe,CAAC,GAC5D,EACF,KAAC,OAAO,IAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAI,EAC1B,KAAC,YAAY,IACX,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,OAAO,EAClC,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,EACtC,WAAW,EAAE,cAAc,IAAI,kBAAkB,KAAK,KAAK,EAC3D,2BAA2B,EAAE,2BAA2B,EACxD,eAAe,EAAE,CAAC,CAAC,YAAY,IAAI,cAAc,EACjD,qBAAqB,EAAE,CAAC,CAAC,YAAY,EACrC,KAAK,EAAC,KAAK,EACX,WAAW,EAAC,yEAAyE,EACrF,MAAM,EAAE,WAAW,EACnB,qBAAqB,EAAE,wBAAwB,EAC/C,aAAa,EAAC,SAAS,EACvB,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EACnC,SAAS,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAC/C,cAAc,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAClD,YAAY,EACV,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAC1D,KAAC,MAAM,IACL,IAAI,EAAC,OAAO,EACZ,OAAO,EAAC,UAAU,EAClB,QAAQ,EAAE,CAAC,CAAC,YAAY,EACxB,OAAO,EAAE,wBAAwB,kBACpB,6BAA6B,6BAGnC,CACV,CAAC,CAAC,CAAC,SAAS,GAEf,IACD,CACJ,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,EAAE,WAAW,EAAE,cAAc,EAAS;IACtD,MAAM,EAAE,8BAA8B,EAAE,GAAG,MAAM,EAAE,CAAA;IAEnD,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CACL,KAAC,MAAM,IACL,OAAO,EAAC,UAAU,EAClB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,GAAG,EACb,IAAI,EAAE,WAAW,EACjB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,kBACZ,sBAAsB,8BAG5B,CACV,CAAA;IACH,CAAC;IAED,IAAI,8BAA8B,EAAE,CAAC;QACnC,OAAO,CACL,KAAC,OAAO,IAAC,KAAK,EAAC,gDAAgD,YAC7D,yBACE,KAAC,MAAM,IACL,OAAO,EAAC,UAAU,EAClB,QAAQ,EAAE,8BAA8B,kBAC3B,sBAAsB,8BAG5B,GACJ,GACC,CACX,CAAA;IACH,CAAC;IAED,OAAO,CACL,8BACE,KAAC,aAAa,IAAC,cAAc,EAAE,cAAc,GAAI,EACjD,KAAC,gBAAgB,KAAG,EACpB,KAAC,0BAA0B,KAAG,EAC9B,KAAC,oBAAoB,KAAG,EACxB,KAAC,yBAAyB,KAAG,EAC7B,KAAC,gBAAgB,KAAG,EACpB,KAAC,kBAAkB,KAAG,IACrB,CACJ,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,EAChD,cAAc,EACd,WAAW,GACL;IACN,OAAO,CACL,KAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,YAC/B,KAAC,GAAG,IAAC,OAAO,EAAE,CAAC,YACb,KAAC,KAAK,cACJ,KAAC,GAAG,IAAC,OAAO,EAAE,CAAC,YACb,KAAC,IAAI,IAAC,SAAS,QAAC,OAAO,EAAE,CAAC,EAAE,UAAU,EAAC,QAAQ,YAC7C,MAAC,IAAI,IAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,aACxB,MAAC,UAAU,IAAC,OAAO,EAAC,IAAI,EAAC,UAAU,EAAC,OAAO,6CACb,KAAC,aAAa,KAAG,IAClC,EACb,KAAC,GAAG,IAAC,OAAO,EAAE,CAAC,YACb,KAAC,OAAO,KAAG,GACP,EACN,KAAC,UAAU,IAAC,OAAO,EAAC,OAAO,EAAC,SAAS,wSAMxB,EACb,KAAC,QAAQ,IACP,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,cAAc,GAC9B,IACG,GACF,GACH,GACA,GACJ,GACD,CACR,CAAA;AACH,CAAC","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,4 +1,4 @@
1
- import { authService } from '../apps';
1
+ import { mfaService } from '../apps';
2
2
  /**
3
3
  * This function is a react hook to help writing your own login screen.
4
4
  *
@@ -433,7 +433,7 @@ export interface UseLoginValue {
433
433
  isInvalid: boolean;
434
434
  };
435
435
  /** The MFA method the user must complete to finish signing in, if available. */
436
- mfaMethod: authService.MfaMethod | null;
436
+ mfaMethod: mfaService.MfaMethod | null;
437
437
  /** `true` while processing `submitMfaCode()`. */
438
438
  isSubmittingMfaCode: boolean;
439
439
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useLogin.js","sourceRoot":"","sources":["../../src/hooks/useLogin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { authService, Sentry } from '../apps'\n\nimport useIsMounted from './useIsMounted'\nimport useBooleanState from './useBooleanState'\n\n/**\n * This function is a react hook to help writing your own login screen.\n *\n * ## Example\n *\n * ```jsx\n * import * as React from 'react'\n * import { useHistory } from 'react-router-dom'\n * import { useLogin } from '@oneblink/apps-react'\n *\n * function App() {\n * const history = useHistory()\n *\n * const [username, setUsername] = React.useState('')\n * const [password, setPassword] = React.useState('')\n * const [newPasswordConfirmed, setNewPasswordConfirmed] = React.useState('')\n * const [newPassword, setNewPassword] = React.useState('')\n * const [code, setCode] = React.useState('')\n *\n * const onLogin = React.useCallback(() => {\n * history.push('/')\n * }, [history])\n *\n * const {\n * // Login\n * loginWithGoogle,\n * loginWithUsernamePassword,\n * isLoggingIn,\n * // Reset Temp Password\n * isPasswordTemporary,\n * isResettingTemporaryPassword,\n * resetTemporaryPassword,\n * // MFA Password\n * mfaMethod,\n * isSubmittingMfaCode,\n * submitMfaCode,\n * // Login Errors\n * loginError,\n * clearLoginError,\n * // Showing Forgot Password\n * isShowingForgotPassword,\n * showForgotPassword,\n * hideForgotPassword,\n * // Sending Forgot Password Code\n * isSendingForgotPasswordCode,\n * sendForgotPasswordCode,\n * // Resetting Forgotten Password\n * hasSentForgotPasswordCode,\n * isResettingForgottenPassword,\n * resetForgottenPassword,\n * // Forgot Password Errors\n * forgotPasswordError,\n * clearForgotPasswordError,\n * // Validation\n * usernameValidation,\n * passwordValidation,\n * codeValidation,\n * newPasswordValidation,\n * newPasswordConfirmedValidation,\n * } = useLogin({\n * username,\n * password,\n * newPassword,\n * newPasswordConfirmed,\n * code,\n * onLogin,\n * })\n *\n * if (hasSentForgotPasswordCode) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * resetForgottenPassword()\n * }}\n * >\n * <p>We have sent you a password reset code via email. Enter it below to reset your password.</p>\n *\n * <input\n * type=\"password\"\n * placeholder=\"Code\"\n * value={code}\n * onChange={(e) => setCode(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"New Password\"\n * value={newPassword}\n * onChange={(e) => setNewPassword(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"Confirm Password\"\n * value={newPassword}\n * onChange={(e) => setNewPasswordConfirmed(e.target.value)}\n * />\n *\n * <button\n * type=\"submit\"\n * disabled={isResettingForgottenPassword || codeValidation.isInvalid || newPasswordValidation.isInvalid || newPasswordConfirmedValidation.isInvalid}\n * >\n * Change Password\n * </button>\n *\n * <p>Password Requirements</p>\n * <p>Contains a lowercase letter: {validation.hasLowercaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains an upper case letter: {validation.hasUpperCaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains a number: {validation.hasNumber ? 'Yes' : 'No'}</p>\n * <p>Contains a special character: {validation.hasSpecialCharacter ? 'Yes' : 'No'}</p>\n * <p>Contains at least 8 characters: {validation.hasMinLength ? 'Yes' : 'No'}</p>\n *\n * {forgotPasswordError && (\n * <p>{forgotPasswordError.message}</p>\n * <button type=\"button\" onClick={clearForgotPasswordError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * if (isShowingForgotPassword) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * sendForgotPasswordCode()\n * }}\n * >\n * <p>Enter your email address and we will send you a code to reset your password.</p>\n *\n * <input\n * type=\"email\"\n * placeholder=\"Email Address\"\n * value={username}\n * onChange={(e) => setUsername(e.target.value)}\n * />\n *\n * <p>\n * <a onClick={hideForgotPassword}>Remembered your password?</a>\n * </p>\n *\n * <button\n * type=\"submit\"\n * disabled={isSendingForgotPasswordCode || usernameValidation.isInvalid}\n * >\n * Reset Password\n * </button>\n *\n * {forgotPasswordError && (\n * <p>{forgotPasswordError.message}</p>\n * <button type=\"button\" onClick={clearForgotPasswordError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * if (isPasswordTemporary) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * resetTemporaryPassword()\n * }}\n * >\n * <p>The password you entered was only temporary and must be reset for security purposes. Please enter your new password below to continue.</p>\n *\n * <input\n * type=\"password\"\n * placeholder=\"New Password\"\n * value={newPassword}\n * onChange={(e) => setNewPassword(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"Confirm Password\"\n * value={newPassword}\n * onChange={(e) => setNewPasswordConfirmed(e.target.value)}\n * />\n *\n * <button\n * type=\"submit\"\n * disabled={isResettingTemporaryPassword || newPasswordValidation.isInvalid || newPasswordConfirmedValidation.isInvalid}\n * >\n * Change Password &amp; Sign In\n * </button>\n *\n * <p>Password Requirements</p>\n * <p>Contains a lowercase letter: {validation.hasLowercaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains an upper case letter: {validation.hasUpperCaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains a number: {validation.hasNumber ? 'Yes' : 'No'}</p>\n * <p>Contains a special character: {validation.hasSpecialCharacter ? 'Yes' : 'No'}</p>\n * <p>Contains at least 8 characters: {validation.hasMinLength ? 'Yes' : 'No'}</p>\n *\n * {loginError && (\n * <p>{loginError.message}</p>\n * <button type=\"button\" onClick={clearLoginError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * if (mfaMethod) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * submitMfaCode()\n * }}\n * >\n * <p>\n * {mfaMethod === 'email'\n * ? 'Enter the verification code sent to your email address.'\n * : mfaMethod === 'sms'\n * ? 'Enter the verification code sent to your phone number.'\n * : mfaMethod === 'authenticator'\n * ? 'Enter the 6-digit code found in your authenticator app.'\n * : 'Enter your verification code.'}\n * </p>\n *\n * <input\n * type=\"password\"\n * placeholder=\"Code\"\n * value={code}\n * onChange={(e) => setCode(e.target.value)}\n * />\n *\n * <button\n * type=\"submit\"\n * disabled={isSubmittingMfaCode || codeValidation.isInvalid}\n * >\n * Sign In\n * </button>\n *\n * {loginError && (\n * <p>{loginError.message}</p>\n * <button type=\"button\" onClick={clearLoginError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * loginWithUsernamePassword()\n * }}\n * >\n * <p>Sign in with your email address and password.</p>\n * <input\n * type=\"email\"\n * placeholder=\"Email Address\"\n * value={username}\n * onChange={(e) => setUsername(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"New Password\"\n * value={newPassword}\n * onChange={(e) => setNewPassword(e.target.value)}\n * />\n *\n * <p>\n * <a onClick={showForgotPassword}>Forgot your password?</a>\n * </p>\n *\n * <button\n * type=\"submit\"\n * disabled={isLoggingIn || usernameValidation.isInvalid || passwordValidation.isInvalid}\n * >\n * {children}\n * </button>\n *\n * <p>or</p>\n *\n * <button\n * type=\"button\"\n * onClick={loginWithGoogle}\n * >\n * <img\n * alt=\"Google\"\n * src=\"google-sign-in.png\"\n * />\n * <span>Sign in with Google</span>\n * </button>\n *\n * {loginError && (\n * <p>{loginError.message}</p>\n * <button type=\"button\" onClick={clearLoginError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param options\n * @returns\n * @group Hooks\n */\nexport default function useLogin({\n username,\n password,\n newPassword,\n newPasswordConfirmed,\n code,\n formsAppId,\n}: {\n /** The email address entered by the user. */\n username: string\n /** The password entered by the user. */\n password: string\n /** The new password entered by the user if changing their password. */\n newPassword: string\n /**\n * The new password repeated by the user if changing their password to ensure\n * they do type it in wrong.\n */\n newPasswordConfirmed: string\n /**\n * The code sent to the user after requesting a password reset by starting the\n * \"forgot password\" process.\n */\n code: string\n /** The identifier for the current forms app */\n formsAppId?: number\n}): UseLoginValue {\n const isMounted = useIsMounted()\n\n // Validation\n const usernameValidation = React.useMemo(() => {\n return {\n isInvalid: !username.trim(),\n }\n }, [username])\n\n const passwordValidation = React.useMemo(() => {\n return {\n isInvalid: !password.trim(),\n }\n }, [password])\n\n const codeValidation = React.useMemo(() => {\n return {\n isInvalid: !code.trim(),\n }\n }, [code])\n\n const newPasswordValidation = React.useMemo(() => {\n const validation = {\n hasLowercaseLetter: /[a-z]+/.test(newPassword),\n hasUpperCaseLetter: /[A-Z]+/.test(newPassword),\n hasNumber: /\\d+/.test(newPassword),\n hasSpecialCharacter: /[\\^$*.[\\]{}()?|\\-\"!@#%&/,><':;|_~`]+/.test(\n newPassword,\n ),\n hasMinLength: newPassword.length >= 8,\n isInvalid: true,\n }\n validation.isInvalid =\n !validation.hasLowercaseLetter ||\n !validation.hasUpperCaseLetter ||\n !validation.hasNumber ||\n !validation.hasSpecialCharacter ||\n !validation.hasMinLength\n return validation\n }, [newPassword])\n\n const newPasswordConfirmedValidation = React.useMemo(() => {\n return {\n isInvalid: newPassword !== newPasswordConfirmed,\n }\n }, [newPassword, newPasswordConfirmed])\n\n // Login, Reset Password, MFA\n const [\n {\n isResettingTemporaryPassword,\n isLoggingIn,\n loginError,\n loginAttemptResponse,\n isSubmittingMfaCode,\n },\n setLoginState,\n ] = React.useState<{\n isResettingTemporaryPassword: boolean\n isLoggingIn: boolean\n loginError: null | Error\n loginAttemptResponse: authService.LoginAttemptResponse | undefined\n isSubmittingMfaCode: boolean\n }>({\n isResettingTemporaryPassword: false,\n isLoggingIn: false,\n loginError: null,\n loginAttemptResponse: undefined,\n isSubmittingMfaCode: false,\n })\n const clearLoginError = React.useCallback(\n () =>\n setLoginState((current) => ({\n ...current,\n loginError: null,\n })),\n [],\n )\n const loginWithUsernamePassword = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid email address'),\n }))\n return\n }\n if (passwordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: true,\n loginError: null,\n }))\n\n try {\n const newLoginAttemptResponse = await authService.loginUsernamePassword(\n username,\n password,\n )\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: false,\n loginAttemptResponse: newLoginAttemptResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n password,\n passwordValidation.isInvalid,\n username,\n usernameValidation.isInvalid,\n ])\n\n const resetTemporaryPassword = React.useCallback(async () => {\n const resetTemporaryPasswordCallback =\n loginAttemptResponse?.resetPasswordCallback\n if (!resetTemporaryPasswordCallback) {\n return\n }\n\n if (newPasswordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n if (newPasswordConfirmedValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isResettingPassword: true,\n loginError: null,\n }))\n\n try {\n const resetPasswordResponse =\n await resetTemporaryPasswordCallback(newPassword)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isResettingTemporaryPassword: false,\n loginAttemptResponse: resetPasswordResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isResettingPassword: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n loginAttemptResponse?.resetPasswordCallback,\n newPassword,\n newPasswordConfirmedValidation.isInvalid,\n newPasswordValidation.isInvalid,\n ])\n\n const submitMfaCode = React.useCallback(async () => {\n const mfaCodeCallback = loginAttemptResponse?.mfa?.codeCallback\n if (!mfaCodeCallback) {\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isSubmittingMfaCode: true,\n loginError: null,\n }))\n\n try {\n const mfaResponse = await mfaCodeCallback(code)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isSubmittingMfaCode: false,\n loginAttemptResponse: mfaResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isSubmittingMfaCode: false,\n loginError: error as Error,\n }))\n }\n }\n }, [code, isMounted, loginAttemptResponse?.mfa?.codeCallback])\n\n // Forgot Password\n const [isShowingForgotPassword, showForgotPassword, hideForgotPassword] =\n useBooleanState(false)\n const [\n {\n resetForgottenPasswordCallback,\n isSendingForgotPasswordCode,\n isResettingForgottenPassword,\n forgotPasswordError,\n },\n setForgotPasswordState,\n ] = React.useState<{\n isSendingForgotPasswordCode: boolean\n forgotPasswordError: null | Error\n resetForgottenPasswordCallback:\n | null\n | ((code: string, newPassword: string) => void)\n isResettingForgottenPassword: boolean\n }>({\n isSendingForgotPasswordCode: false,\n forgotPasswordError: null,\n resetForgottenPasswordCallback: null,\n isResettingForgottenPassword: false,\n })\n const clearForgotPasswordError = React.useCallback(\n () =>\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: null,\n })),\n [],\n )\n const sendForgotPasswordCode = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid email address'),\n }))\n return\n }\n\n setForgotPasswordState({\n isSendingForgotPasswordCode: true,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n\n try {\n const newResetForgottenPasswordCallback =\n await authService.forgotPassword(username, formsAppId)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: newResetForgottenPasswordCallback,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: error as Error,\n isResettingForgottenPassword: false,\n })\n }\n }\n }, [isMounted, username, usernameValidation.isInvalid, formsAppId])\n\n const resetForgottenPassword = React.useCallback(async () => {\n if (!resetForgottenPasswordCallback) {\n return\n }\n\n if (codeValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error(\n 'Please enter the code that was sent to your email address',\n ),\n }))\n }\n if (newPasswordValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid password'),\n }))\n return\n }\n if (newPasswordConfirmedValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: true,\n forgotPasswordError: null,\n }))\n\n try {\n await resetForgottenPasswordCallback(code, newPassword)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n hideForgotPassword()\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: false,\n forgotPasswordError: error as Error,\n }))\n }\n }\n }, [\n resetForgottenPasswordCallback,\n codeValidation.isInvalid,\n newPasswordValidation.isInvalid,\n newPasswordConfirmedValidation.isInvalid,\n code,\n newPassword,\n isMounted,\n hideForgotPassword,\n ])\n\n const loginWithGoogle = React.useCallback(() => {\n authService.loginHostedUI('Google')\n }, [])\n\n return {\n // Login\n /** Open redirect user to the Google sign in */\n loginWithGoogle,\n loginWithUsernamePassword,\n isLoggingIn,\n loginError,\n clearLoginError,\n // Reset Temp Password\n isPasswordTemporary: !!loginAttemptResponse?.resetPasswordCallback,\n isResettingTemporaryPassword,\n resetTemporaryPassword,\n // MFA Code\n mfaMethod: loginAttemptResponse?.mfa?.method || null,\n isSubmittingMfaCode,\n submitMfaCode,\n // Showing Forgot Password\n isShowingForgotPassword,\n showForgotPassword,\n hideForgotPassword,\n forgotPasswordError,\n clearForgotPasswordError,\n // Sending Forgot Password Code\n isSendingForgotPasswordCode,\n sendForgotPasswordCode,\n // Resetting Forgotten Password\n hasSentForgotPasswordCode: !!resetForgottenPasswordCallback,\n isResettingForgottenPassword,\n resetForgottenPassword,\n // Validation\n usernameValidation,\n passwordValidation,\n codeValidation,\n newPasswordValidation,\n newPasswordConfirmedValidation,\n }\n}\n\nexport interface UseLoginValue {\n /** Open redirect user to the Google sign-in page. */\n loginWithGoogle: () => void\n /**\n * Attempt to use the `username` and `password` arguments to create a session.\n * Will call `onLogin()` if successful, otherwise will set `loginError`.\n */\n loginWithUsernamePassword: () => void\n /** `true` while processing `loginWithUsernamePassword()`. */\n isLoggingIn: boolean\n /**\n * `true` if the user logged in using a temporary password. Prompt the user\n * for a new password and call `resetTemporaryPassword()`.\n */\n isPasswordTemporary: boolean\n /**\n * Attempt to use `newPassword` and `newPasswordConfirmed` arguments to reset\n * the user's password and create a session. Will call `onLogin()` if\n * successful, otherwise will set `loginError`.\n */\n resetTemporaryPassword: () => void\n /**\n * Set if an error occurs while processing `loginWithUsernamePassword()` or\n * `resetTemporaryPassword()`.\n */\n loginError: Error | null\n /** Set `loginError` back to `null`. */\n clearLoginError: () => void\n /** `true` while processing `resetTemporaryPassword()`. */\n isResettingTemporaryPassword: boolean\n /** `true` when showing the forgot password flow. */\n isShowingForgotPassword: boolean\n /** Set `isShowingForgotPassword` to `true`. */\n showForgotPassword: () => void\n /** Set `isShowingForgotPassword` to `false`. */\n hideForgotPassword: () => void\n /**\n * Attempt to use the `username` argument to start the forgot password\n * process. This will send the user an email with a code to enter. A failed\n * request will set `forgotPasswordError`.\n */\n sendForgotPasswordCode: () => void\n /** `true` while processing `sendForgotPasswordCode()`. */\n isSendingForgotPasswordCode: boolean\n /** `true` if the forgot password code has been successfully sent to the user. */\n hasSentForgotPasswordCode: boolean\n /**\n * Attempt to use the `code`, `newPassword`, and `newPasswordConfirmed`\n * arguments to reset the user's password. A failed request will set\n * `forgotPasswordError`.\n */\n resetForgottenPassword: () => void\n /** `true` while processing `resetForgottenPassword()`. */\n isResettingForgottenPassword: boolean\n /**\n * Set if an error occurs while processing `sendForgotPasswordCode()` or\n * `resetForgottenPassword()`.\n */\n forgotPasswordError: Error | null\n /** Set `forgotPasswordError` back to `null`. */\n clearForgotPasswordError: () => void\n usernameValidation: {\n /** `true` if the `username` argument is invalid. */\n isInvalid: boolean\n }\n passwordValidation: {\n /** `true` if the `password` argument is invalid. */\n isInvalid: boolean\n }\n codeValidation: {\n /** `true` if the `code` argument is invalid. */\n isInvalid: boolean\n }\n newPasswordValidation: {\n /** `true` if the `newPassword` argument is invalid. */\n isInvalid: boolean\n /**\n * `true` if the `newPassword` argument has a lowercase letter (required to\n * be valid).\n */\n hasLowercaseLetter: boolean\n /**\n * `true` if the `newPassword` argument has an uppercase letter (required to\n * be valid).\n */\n hasUpperCaseLetter: boolean\n /** `true` if the `newPassword` argument has a number (required to be valid). */\n hasNumber: boolean\n /**\n * `true` if the `newPassword` argument has a special character (required to\n * be valid).\n */\n hasSpecialCharacter: boolean\n /**\n * `true` if the `newPassword` argument has at least the minimum number of\n * characters (required to be valid).\n */\n hasMinLength: boolean\n }\n newPasswordConfirmedValidation: {\n /**\n * `true` if the `newPasswordConfirmed` argument is invalid (must match the\n * `newPassword` argument).\n */\n isInvalid: boolean\n }\n /** The MFA method the user must complete to finish signing in, if available. */\n mfaMethod: authService.MfaMethod | null\n /** `true` while processing `submitMfaCode()`. */\n isSubmittingMfaCode: boolean\n /**\n * Attempt to use `code` argument to submit the MFA code and create a session.\n * Will call `onLogin()` if successful, otherwise will set `loginError`.\n */\n submitMfaCode: () => void\n}\n"]}
1
+ {"version":3,"file":"useLogin.js","sourceRoot":"","sources":["../../src/hooks/useLogin.ts"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { authService, mfaService, Sentry } from '../apps'\n\nimport useIsMounted from './useIsMounted'\nimport useBooleanState from './useBooleanState'\n\n/**\n * This function is a react hook to help writing your own login screen.\n *\n * ## Example\n *\n * ```jsx\n * import * as React from 'react'\n * import { useHistory } from 'react-router-dom'\n * import { useLogin } from '@oneblink/apps-react'\n *\n * function App() {\n * const history = useHistory()\n *\n * const [username, setUsername] = React.useState('')\n * const [password, setPassword] = React.useState('')\n * const [newPasswordConfirmed, setNewPasswordConfirmed] = React.useState('')\n * const [newPassword, setNewPassword] = React.useState('')\n * const [code, setCode] = React.useState('')\n *\n * const onLogin = React.useCallback(() => {\n * history.push('/')\n * }, [history])\n *\n * const {\n * // Login\n * loginWithGoogle,\n * loginWithUsernamePassword,\n * isLoggingIn,\n * // Reset Temp Password\n * isPasswordTemporary,\n * isResettingTemporaryPassword,\n * resetTemporaryPassword,\n * // MFA Password\n * mfaMethod,\n * isSubmittingMfaCode,\n * submitMfaCode,\n * // Login Errors\n * loginError,\n * clearLoginError,\n * // Showing Forgot Password\n * isShowingForgotPassword,\n * showForgotPassword,\n * hideForgotPassword,\n * // Sending Forgot Password Code\n * isSendingForgotPasswordCode,\n * sendForgotPasswordCode,\n * // Resetting Forgotten Password\n * hasSentForgotPasswordCode,\n * isResettingForgottenPassword,\n * resetForgottenPassword,\n * // Forgot Password Errors\n * forgotPasswordError,\n * clearForgotPasswordError,\n * // Validation\n * usernameValidation,\n * passwordValidation,\n * codeValidation,\n * newPasswordValidation,\n * newPasswordConfirmedValidation,\n * } = useLogin({\n * username,\n * password,\n * newPassword,\n * newPasswordConfirmed,\n * code,\n * onLogin,\n * })\n *\n * if (hasSentForgotPasswordCode) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * resetForgottenPassword()\n * }}\n * >\n * <p>We have sent you a password reset code via email. Enter it below to reset your password.</p>\n *\n * <input\n * type=\"password\"\n * placeholder=\"Code\"\n * value={code}\n * onChange={(e) => setCode(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"New Password\"\n * value={newPassword}\n * onChange={(e) => setNewPassword(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"Confirm Password\"\n * value={newPassword}\n * onChange={(e) => setNewPasswordConfirmed(e.target.value)}\n * />\n *\n * <button\n * type=\"submit\"\n * disabled={isResettingForgottenPassword || codeValidation.isInvalid || newPasswordValidation.isInvalid || newPasswordConfirmedValidation.isInvalid}\n * >\n * Change Password\n * </button>\n *\n * <p>Password Requirements</p>\n * <p>Contains a lowercase letter: {validation.hasLowercaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains an upper case letter: {validation.hasUpperCaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains a number: {validation.hasNumber ? 'Yes' : 'No'}</p>\n * <p>Contains a special character: {validation.hasSpecialCharacter ? 'Yes' : 'No'}</p>\n * <p>Contains at least 8 characters: {validation.hasMinLength ? 'Yes' : 'No'}</p>\n *\n * {forgotPasswordError && (\n * <p>{forgotPasswordError.message}</p>\n * <button type=\"button\" onClick={clearForgotPasswordError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * if (isShowingForgotPassword) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * sendForgotPasswordCode()\n * }}\n * >\n * <p>Enter your email address and we will send you a code to reset your password.</p>\n *\n * <input\n * type=\"email\"\n * placeholder=\"Email Address\"\n * value={username}\n * onChange={(e) => setUsername(e.target.value)}\n * />\n *\n * <p>\n * <a onClick={hideForgotPassword}>Remembered your password?</a>\n * </p>\n *\n * <button\n * type=\"submit\"\n * disabled={isSendingForgotPasswordCode || usernameValidation.isInvalid}\n * >\n * Reset Password\n * </button>\n *\n * {forgotPasswordError && (\n * <p>{forgotPasswordError.message}</p>\n * <button type=\"button\" onClick={clearForgotPasswordError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * if (isPasswordTemporary) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * resetTemporaryPassword()\n * }}\n * >\n * <p>The password you entered was only temporary and must be reset for security purposes. Please enter your new password below to continue.</p>\n *\n * <input\n * type=\"password\"\n * placeholder=\"New Password\"\n * value={newPassword}\n * onChange={(e) => setNewPassword(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"Confirm Password\"\n * value={newPassword}\n * onChange={(e) => setNewPasswordConfirmed(e.target.value)}\n * />\n *\n * <button\n * type=\"submit\"\n * disabled={isResettingTemporaryPassword || newPasswordValidation.isInvalid || newPasswordConfirmedValidation.isInvalid}\n * >\n * Change Password &amp; Sign In\n * </button>\n *\n * <p>Password Requirements</p>\n * <p>Contains a lowercase letter: {validation.hasLowercaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains an upper case letter: {validation.hasUpperCaseLetter ? 'Yes' : 'No'}</p>\n * <p>Contains a number: {validation.hasNumber ? 'Yes' : 'No'}</p>\n * <p>Contains a special character: {validation.hasSpecialCharacter ? 'Yes' : 'No'}</p>\n * <p>Contains at least 8 characters: {validation.hasMinLength ? 'Yes' : 'No'}</p>\n *\n * {loginError && (\n * <p>{loginError.message}</p>\n * <button type=\"button\" onClick={clearLoginError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * if (mfaMethod) {\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * submitMfaCode()\n * }}\n * >\n * <p>\n * {mfaMethod === 'email'\n * ? 'Enter the verification code sent to your email address.'\n * : mfaMethod === 'sms'\n * ? 'Enter the verification code sent to your phone number.'\n * : mfaMethod === 'authenticator'\n * ? 'Enter the 6-digit code found in your authenticator app.'\n * : 'Enter your verification code.'}\n * </p>\n *\n * <input\n * type=\"password\"\n * placeholder=\"Code\"\n * value={code}\n * onChange={(e) => setCode(e.target.value)}\n * />\n *\n * <button\n * type=\"submit\"\n * disabled={isSubmittingMfaCode || codeValidation.isInvalid}\n * >\n * Sign In\n * </button>\n *\n * {loginError && (\n * <p>{loginError.message}</p>\n * <button type=\"button\" onClick={clearLoginError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * return (\n * <form\n * onSubmit={(e) => {\n * e.preventDefault()\n * loginWithUsernamePassword()\n * }}\n * >\n * <p>Sign in with your email address and password.</p>\n * <input\n * type=\"email\"\n * placeholder=\"Email Address\"\n * value={username}\n * onChange={(e) => setUsername(e.target.value)}\n * />\n *\n * <input\n * type=\"password\"\n * placeholder=\"New Password\"\n * value={newPassword}\n * onChange={(e) => setNewPassword(e.target.value)}\n * />\n *\n * <p>\n * <a onClick={showForgotPassword}>Forgot your password?</a>\n * </p>\n *\n * <button\n * type=\"submit\"\n * disabled={isLoggingIn || usernameValidation.isInvalid || passwordValidation.isInvalid}\n * >\n * {children}\n * </button>\n *\n * <p>or</p>\n *\n * <button\n * type=\"button\"\n * onClick={loginWithGoogle}\n * >\n * <img\n * alt=\"Google\"\n * src=\"google-sign-in.png\"\n * />\n * <span>Sign in with Google</span>\n * </button>\n *\n * {loginError && (\n * <p>{loginError.message}</p>\n * <button type=\"button\" onClick={clearLoginError}>Clear Error</button>\n * )}\n * </form>\n * )\n * }\n *\n * const root = document.getElementById('root')\n * if (root) {\n * ReactDOM.render(<App />, root)\n * }\n * ```\n *\n * @param options\n * @returns\n * @group Hooks\n */\nexport default function useLogin({\n username,\n password,\n newPassword,\n newPasswordConfirmed,\n code,\n formsAppId,\n}: {\n /** The email address entered by the user. */\n username: string\n /** The password entered by the user. */\n password: string\n /** The new password entered by the user if changing their password. */\n newPassword: string\n /**\n * The new password repeated by the user if changing their password to ensure\n * they do type it in wrong.\n */\n newPasswordConfirmed: string\n /**\n * The code sent to the user after requesting a password reset by starting the\n * \"forgot password\" process.\n */\n code: string\n /** The identifier for the current forms app */\n formsAppId?: number\n}): UseLoginValue {\n const isMounted = useIsMounted()\n\n // Validation\n const usernameValidation = React.useMemo(() => {\n return {\n isInvalid: !username.trim(),\n }\n }, [username])\n\n const passwordValidation = React.useMemo(() => {\n return {\n isInvalid: !password.trim(),\n }\n }, [password])\n\n const codeValidation = React.useMemo(() => {\n return {\n isInvalid: !code.trim(),\n }\n }, [code])\n\n const newPasswordValidation = React.useMemo(() => {\n const validation = {\n hasLowercaseLetter: /[a-z]+/.test(newPassword),\n hasUpperCaseLetter: /[A-Z]+/.test(newPassword),\n hasNumber: /\\d+/.test(newPassword),\n hasSpecialCharacter: /[\\^$*.[\\]{}()?|\\-\"!@#%&/,><':;|_~`]+/.test(\n newPassword,\n ),\n hasMinLength: newPassword.length >= 8,\n isInvalid: true,\n }\n validation.isInvalid =\n !validation.hasLowercaseLetter ||\n !validation.hasUpperCaseLetter ||\n !validation.hasNumber ||\n !validation.hasSpecialCharacter ||\n !validation.hasMinLength\n return validation\n }, [newPassword])\n\n const newPasswordConfirmedValidation = React.useMemo(() => {\n return {\n isInvalid: newPassword !== newPasswordConfirmed,\n }\n }, [newPassword, newPasswordConfirmed])\n\n // Login, Reset Password, MFA\n const [\n {\n isResettingTemporaryPassword,\n isLoggingIn,\n loginError,\n loginAttemptResponse,\n isSubmittingMfaCode,\n },\n setLoginState,\n ] = React.useState<{\n isResettingTemporaryPassword: boolean\n isLoggingIn: boolean\n loginError: null | Error\n loginAttemptResponse: authService.LoginAttemptResponse | undefined\n isSubmittingMfaCode: boolean\n }>({\n isResettingTemporaryPassword: false,\n isLoggingIn: false,\n loginError: null,\n loginAttemptResponse: undefined,\n isSubmittingMfaCode: false,\n })\n const clearLoginError = React.useCallback(\n () =>\n setLoginState((current) => ({\n ...current,\n loginError: null,\n })),\n [],\n )\n const loginWithUsernamePassword = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid email address'),\n }))\n return\n }\n if (passwordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: true,\n loginError: null,\n }))\n\n try {\n const newLoginAttemptResponse = await authService.loginUsernamePassword(\n username,\n password,\n )\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: false,\n loginAttemptResponse: newLoginAttemptResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isLoggingIn: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n password,\n passwordValidation.isInvalid,\n username,\n usernameValidation.isInvalid,\n ])\n\n const resetTemporaryPassword = React.useCallback(async () => {\n const resetTemporaryPasswordCallback =\n loginAttemptResponse?.resetPasswordCallback\n if (!resetTemporaryPasswordCallback) {\n return\n }\n\n if (newPasswordValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please enter a valid password'),\n }))\n return\n }\n\n if (newPasswordConfirmedValidation.isInvalid) {\n setLoginState((current) => ({\n ...current,\n loginError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isResettingPassword: true,\n loginError: null,\n }))\n\n try {\n const resetPasswordResponse =\n await resetTemporaryPasswordCallback(newPassword)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isResettingTemporaryPassword: false,\n loginAttemptResponse: resetPasswordResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isResettingPassword: false,\n loginError: error as Error,\n }))\n }\n }\n }, [\n isMounted,\n loginAttemptResponse?.resetPasswordCallback,\n newPassword,\n newPasswordConfirmedValidation.isInvalid,\n newPasswordValidation.isInvalid,\n ])\n\n const submitMfaCode = React.useCallback(async () => {\n const mfaCodeCallback = loginAttemptResponse?.mfa?.codeCallback\n if (!mfaCodeCallback) {\n return\n }\n\n setLoginState((current) => ({\n ...current,\n isSubmittingMfaCode: true,\n loginError: null,\n }))\n\n try {\n const mfaResponse = await mfaCodeCallback(code)\n if (isMounted.current) {\n setLoginState((currentState) => ({\n ...currentState,\n isSubmittingMfaCode: false,\n loginAttemptResponse: mfaResponse,\n }))\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setLoginState((current) => ({\n ...current,\n isSubmittingMfaCode: false,\n loginError: error as Error,\n }))\n }\n }\n }, [code, isMounted, loginAttemptResponse?.mfa?.codeCallback])\n\n // Forgot Password\n const [isShowingForgotPassword, showForgotPassword, hideForgotPassword] =\n useBooleanState(false)\n const [\n {\n resetForgottenPasswordCallback,\n isSendingForgotPasswordCode,\n isResettingForgottenPassword,\n forgotPasswordError,\n },\n setForgotPasswordState,\n ] = React.useState<{\n isSendingForgotPasswordCode: boolean\n forgotPasswordError: null | Error\n resetForgottenPasswordCallback:\n | null\n | ((code: string, newPassword: string) => void)\n isResettingForgottenPassword: boolean\n }>({\n isSendingForgotPasswordCode: false,\n forgotPasswordError: null,\n resetForgottenPasswordCallback: null,\n isResettingForgottenPassword: false,\n })\n const clearForgotPasswordError = React.useCallback(\n () =>\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: null,\n })),\n [],\n )\n const sendForgotPasswordCode = React.useCallback(async () => {\n if (usernameValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid email address'),\n }))\n return\n }\n\n setForgotPasswordState({\n isSendingForgotPasswordCode: true,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n\n try {\n const newResetForgottenPasswordCallback =\n await authService.forgotPassword(username, formsAppId)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: newResetForgottenPasswordCallback,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: error as Error,\n isResettingForgottenPassword: false,\n })\n }\n }\n }, [isMounted, username, usernameValidation.isInvalid, formsAppId])\n\n const resetForgottenPassword = React.useCallback(async () => {\n if (!resetForgottenPasswordCallback) {\n return\n }\n\n if (codeValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error(\n 'Please enter the code that was sent to your email address',\n ),\n }))\n }\n if (newPasswordValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please enter a valid password'),\n }))\n return\n }\n if (newPasswordConfirmedValidation.isInvalid) {\n setForgotPasswordState((current) => ({\n ...current,\n forgotPasswordError: new Error('Please confirm your new password'),\n }))\n return\n }\n\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: true,\n forgotPasswordError: null,\n }))\n\n try {\n await resetForgottenPasswordCallback(code, newPassword)\n if (isMounted.current) {\n setForgotPasswordState({\n isSendingForgotPasswordCode: false,\n resetForgottenPasswordCallback: null,\n forgotPasswordError: null,\n isResettingForgottenPassword: false,\n })\n hideForgotPassword()\n }\n } catch (error) {\n Sentry.captureException(error)\n if (isMounted.current) {\n setForgotPasswordState((current) => ({\n ...current,\n isChangingPassword: false,\n forgotPasswordError: error as Error,\n }))\n }\n }\n }, [\n resetForgottenPasswordCallback,\n codeValidation.isInvalid,\n newPasswordValidation.isInvalid,\n newPasswordConfirmedValidation.isInvalid,\n code,\n newPassword,\n isMounted,\n hideForgotPassword,\n ])\n\n const loginWithGoogle = React.useCallback(() => {\n authService.loginHostedUI('Google')\n }, [])\n\n return {\n // Login\n /** Open redirect user to the Google sign in */\n loginWithGoogle,\n loginWithUsernamePassword,\n isLoggingIn,\n loginError,\n clearLoginError,\n // Reset Temp Password\n isPasswordTemporary: !!loginAttemptResponse?.resetPasswordCallback,\n isResettingTemporaryPassword,\n resetTemporaryPassword,\n // MFA Code\n mfaMethod: loginAttemptResponse?.mfa?.method || null,\n isSubmittingMfaCode,\n submitMfaCode,\n // Showing Forgot Password\n isShowingForgotPassword,\n showForgotPassword,\n hideForgotPassword,\n forgotPasswordError,\n clearForgotPasswordError,\n // Sending Forgot Password Code\n isSendingForgotPasswordCode,\n sendForgotPasswordCode,\n // Resetting Forgotten Password\n hasSentForgotPasswordCode: !!resetForgottenPasswordCallback,\n isResettingForgottenPassword,\n resetForgottenPassword,\n // Validation\n usernameValidation,\n passwordValidation,\n codeValidation,\n newPasswordValidation,\n newPasswordConfirmedValidation,\n }\n}\n\nexport interface UseLoginValue {\n /** Open redirect user to the Google sign-in page. */\n loginWithGoogle: () => void\n /**\n * Attempt to use the `username` and `password` arguments to create a session.\n * Will call `onLogin()` if successful, otherwise will set `loginError`.\n */\n loginWithUsernamePassword: () => void\n /** `true` while processing `loginWithUsernamePassword()`. */\n isLoggingIn: boolean\n /**\n * `true` if the user logged in using a temporary password. Prompt the user\n * for a new password and call `resetTemporaryPassword()`.\n */\n isPasswordTemporary: boolean\n /**\n * Attempt to use `newPassword` and `newPasswordConfirmed` arguments to reset\n * the user's password and create a session. Will call `onLogin()` if\n * successful, otherwise will set `loginError`.\n */\n resetTemporaryPassword: () => void\n /**\n * Set if an error occurs while processing `loginWithUsernamePassword()` or\n * `resetTemporaryPassword()`.\n */\n loginError: Error | null\n /** Set `loginError` back to `null`. */\n clearLoginError: () => void\n /** `true` while processing `resetTemporaryPassword()`. */\n isResettingTemporaryPassword: boolean\n /** `true` when showing the forgot password flow. */\n isShowingForgotPassword: boolean\n /** Set `isShowingForgotPassword` to `true`. */\n showForgotPassword: () => void\n /** Set `isShowingForgotPassword` to `false`. */\n hideForgotPassword: () => void\n /**\n * Attempt to use the `username` argument to start the forgot password\n * process. This will send the user an email with a code to enter. A failed\n * request will set `forgotPasswordError`.\n */\n sendForgotPasswordCode: () => void\n /** `true` while processing `sendForgotPasswordCode()`. */\n isSendingForgotPasswordCode: boolean\n /** `true` if the forgot password code has been successfully sent to the user. */\n hasSentForgotPasswordCode: boolean\n /**\n * Attempt to use the `code`, `newPassword`, and `newPasswordConfirmed`\n * arguments to reset the user's password. A failed request will set\n * `forgotPasswordError`.\n */\n resetForgottenPassword: () => void\n /** `true` while processing `resetForgottenPassword()`. */\n isResettingForgottenPassword: boolean\n /**\n * Set if an error occurs while processing `sendForgotPasswordCode()` or\n * `resetForgottenPassword()`.\n */\n forgotPasswordError: Error | null\n /** Set `forgotPasswordError` back to `null`. */\n clearForgotPasswordError: () => void\n usernameValidation: {\n /** `true` if the `username` argument is invalid. */\n isInvalid: boolean\n }\n passwordValidation: {\n /** `true` if the `password` argument is invalid. */\n isInvalid: boolean\n }\n codeValidation: {\n /** `true` if the `code` argument is invalid. */\n isInvalid: boolean\n }\n newPasswordValidation: {\n /** `true` if the `newPassword` argument is invalid. */\n isInvalid: boolean\n /**\n * `true` if the `newPassword` argument has a lowercase letter (required to\n * be valid).\n */\n hasLowercaseLetter: boolean\n /**\n * `true` if the `newPassword` argument has an uppercase letter (required to\n * be valid).\n */\n hasUpperCaseLetter: boolean\n /** `true` if the `newPassword` argument has a number (required to be valid). */\n hasNumber: boolean\n /**\n * `true` if the `newPassword` argument has a special character (required to\n * be valid).\n */\n hasSpecialCharacter: boolean\n /**\n * `true` if the `newPassword` argument has at least the minimum number of\n * characters (required to be valid).\n */\n hasMinLength: boolean\n }\n newPasswordConfirmedValidation: {\n /**\n * `true` if the `newPasswordConfirmed` argument is invalid (must match the\n * `newPassword` argument).\n */\n isInvalid: boolean\n }\n /** The MFA method the user must complete to finish signing in, if available. */\n mfaMethod: mfaService.MfaMethod | null\n /** `true` while processing `submitMfaCode()`. */\n isSubmittingMfaCode: boolean\n /**\n * Attempt to use `code` argument to submit the MFA code and create a session.\n * Will call `onLogin()` if successful, otherwise will set `loginError`.\n */\n submitMfaCode: () => void\n}\n"]}
@@ -1,29 +1,30 @@
1
1
  import * as React from 'react';
2
- import { authService } from '../apps';
2
+ import { mfaService } from '../apps';
3
+ import { MiscTypes } from '@oneblink/types';
3
4
  type MfaState = {
4
5
  isExternalIdentityProviderUser: boolean;
5
6
  isLoading: boolean;
6
7
  isMfaEnabled: boolean;
7
- mfaSettings: authService.MfaSettings;
8
+ mfaSettings: mfaService.MfaSettings;
8
9
  isSetupSuccessOpen: boolean;
9
10
  loadingError?: Error;
10
11
  isSettingUpMfa: boolean;
11
- settingUpMfaMethod?: authService.MfaMethod;
12
+ settingUpMfaMethod?: mfaService.MfaMethod;
12
13
  isSetupMethodDialogOpen: boolean;
13
- disablingMfaMethod?: authService.MfaMethod;
14
+ disablingMfaMethod?: mfaService.MfaMethod;
14
15
  isSettingPreferredMfaMethod: boolean;
15
16
  setupError?: Error;
16
- mfaAuthenticatorAppSetup?: Awaited<ReturnType<typeof authService.setupMfaAuthenticatorApp>>;
17
+ mfaAuthenticatorAppSetup?: Awaited<ReturnType<typeof mfaService.setupMfaAuthenticatorApp>>;
17
18
  isPhoneNumberDialogOpen: boolean;
18
19
  phoneVerificationCodeSentAt?: number;
19
20
  isRemovePhoneNumberDialogOpen: boolean;
20
21
  };
21
22
  export declare const MfaContext: React.Context<MfaState & {
22
- beginMfaSetup: (mfaMethod: authService.MfaMethod) => Promise<void>;
23
+ beginMfaSetup: (mfaMethod: mfaService.MfaMethod) => Promise<void>;
23
24
  openMfaSetupMethodDialog: () => void;
24
25
  closeMfaSetupMethodDialog: () => void;
25
- beginDisablingMfaMethod: (mfaMethod: authService.MfaMethod) => void;
26
- setPreferredMfaMethod: (mfaMethod: authService.MfaMethod) => Promise<void>;
26
+ beginDisablingMfaMethod: (mfaMethod: mfaService.MfaMethod) => void;
27
+ setPreferredMfaMethod: (mfaMethod: mfaService.MfaMethod) => Promise<void>;
27
28
  openPhoneNumberDialog: () => void;
28
29
  closePhoneNumberDialog: () => void;
29
30
  savePhoneNumber: (phoneNumber: string) => Promise<void>;
@@ -56,23 +57,36 @@ export declare const MfaContext: React.Context<MfaState & {
56
57
  * useUserMeetsMfaRequirement,
57
58
  * } from '@oneblink/apps-react'
58
59
  *
59
- * function Component() {
60
- * const { isLoading, userMeetsMfaRequirement } =
61
- * useUserMeetsMfaRequirement(true)
62
- * // use MFA Requirement details here
60
+ * function Component({ teamMemberMfaRequirement }) {
61
+ * const { mfaSetupRequired, isLoading, loadingError, refreshMfa } =
62
+ * useUserMeetsMfaRequirement(teamMemberMfaRequirement)
63
+ *
64
+ * if (isLoading) {
65
+ * return <Loading />
66
+ * }
67
+ *
68
+ * if (loadingError) {
69
+ * return <Error onRetry={refreshMfa} />
70
+ * }
71
+ *
72
+ * if (mfaSetupRequired) {
73
+ * return <ConfigureMfa />
74
+ * }
75
+ *
76
+ * return <Application />
63
77
  * }
64
78
  *
65
- * function App() {
79
+ * function App({ teamMemberMfaRequirement }) {
66
80
  * return (
67
81
  * <MfaProvider isExternalIdentityProviderUser={false}>
68
- * <Component />
82
+ * <Component teamMemberMfaRequirement={teamMemberMfaRequirement} />
69
83
  * </MfaProvider>
70
84
  * )
71
85
  * }
72
86
  *
73
87
  * const root = document.getElementById('root')
74
88
  * if (root) {
75
- * ReactDOM.render(<App />, root)
89
+ * ReactDOM.render(<App teamMemberMfaRequirement={mfaRequirement} />, root)
76
90
  * }
77
91
  * ```
78
92
  *
@@ -85,11 +99,11 @@ export declare function MfaProvider({ children, isExternalIdentityProviderUser,
85
99
  isExternalIdentityProviderUser: boolean;
86
100
  }): import("react/jsx-runtime").JSX.Element;
87
101
  export default function useMfa(): MfaState & {
88
- beginMfaSetup: (mfaMethod: authService.MfaMethod) => Promise<void>;
102
+ beginMfaSetup: (mfaMethod: mfaService.MfaMethod) => Promise<void>;
89
103
  openMfaSetupMethodDialog: () => void;
90
104
  closeMfaSetupMethodDialog: () => void;
91
- beginDisablingMfaMethod: (mfaMethod: authService.MfaMethod) => void;
92
- setPreferredMfaMethod: (mfaMethod: authService.MfaMethod) => Promise<void>;
105
+ beginDisablingMfaMethod: (mfaMethod: mfaService.MfaMethod) => void;
106
+ setPreferredMfaMethod: (mfaMethod: mfaService.MfaMethod) => Promise<void>;
93
107
  openPhoneNumberDialog: () => void;
94
108
  closePhoneNumberDialog: () => void;
95
109
  savePhoneNumber: (phoneNumber: string) => Promise<void>;
@@ -107,25 +121,48 @@ export default function useMfa(): MfaState & {
107
121
  loadMfa: () => void;
108
122
  };
109
123
  /**
110
- * React hook to check if the logged in user meets the MFA requirement of your
111
- * application. Will throw an Error if used outside of the
112
- * `<MfaProvider />` component.
124
+ * React hook to determine whether the logged in user must set up MFA before
125
+ * accessing your application. Reads MFA settings from the `<MfaProvider />`
126
+ * context. Will throw an Error if used outside of `<MfaProvider />`.
127
+ *
128
+ * Users signed in via an external identity provider are not required to set up
129
+ * MFA.
113
130
  *
114
- * Example
131
+ * #### Example
115
132
  *
116
133
  * ```js
117
- * import { useUserMeetsMfaRequirement } from '@oneblink/apps-react'
134
+ * import { MfaProvider, useUserMeetsMfaRequirement } from '@oneblink/apps-react'
118
135
  *
119
- * const isMfaRequired = true
136
+ * function Component({ teamMemberMfaRequirement }) {
137
+ * const { mfaSetupRequired, isLoading, loadingError, refreshMfa } =
138
+ * useUserMeetsMfaRequirement(teamMemberMfaRequirement)
120
139
  *
121
- * function Component() {
122
- * const userMeetsMfaRequirement =
123
- * useUserMeetsMfaRequirement(isMfaRequired)
140
+ * if (isLoading) {
141
+ * return <Loading />
142
+ * }
143
+ *
144
+ * if (loadingError) {
145
+ * return <Error onRetry={refreshMfa} />
146
+ * }
147
+ *
148
+ * if (mfaSetupRequired) {
149
+ * return <ConfigureMfa />
150
+ * }
151
+ *
152
+ * return <Application />
124
153
  * }
125
154
  * ```
126
155
  *
127
- * @returns
156
+ * @param mfaRequirement - The MFA requirement to enforce, e.g. from your
157
+ * organisation or app settings.
158
+ * @returns Whether MFA setup is required, along with loading state from the MFA
159
+ * provider.
128
160
  * @group Hooks
129
161
  */
130
- export declare function useUserMeetsMfaRequirement(isMfaRequired: boolean): boolean;
162
+ export declare function useUserMeetsMfaRequirement(mfaRequirement: MiscTypes.MfaRequirement | undefined): {
163
+ mfaSetupRequired: boolean;
164
+ isLoading: boolean;
165
+ loadingError: Error | undefined;
166
+ refreshMfa: () => void;
167
+ };
131
168
  export {};