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

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 (49) hide show
  1. package/dist/apps/auth-service.d.ts +15 -8
  2. package/dist/apps/auth-service.js +18 -8
  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 +29 -0
  8. package/dist/apps/mfa-service.js +30 -0
  9. package/dist/apps/mfa-service.js.map +1 -0
  10. package/dist/apps/services/AWSCognitoClient.d.ts +17 -11
  11. package/dist/apps/services/AWSCognitoClient.js +67 -38
  12. package/dist/apps/services/AWSCognitoClient.js.map +1 -1
  13. package/dist/apps/services/cognito.d.ts +5 -24
  14. package/dist/apps/services/cognito.js +3 -32
  15. package/dist/apps/services/cognito.js.map +1 -1
  16. package/dist/components/mfa/MfaAuthenticatorAppDialog.js +2 -2
  17. package/dist/components/mfa/MfaAuthenticatorAppDialog.js.map +1 -1
  18. package/dist/components/mfa/MfaMethodRow.d.ts +4 -1
  19. package/dist/components/mfa/MfaMethodRow.js +5 -5
  20. package/dist/components/mfa/MfaMethodRow.js.map +1 -1
  21. package/dist/components/mfa/MfaPhoneNumberDialog.js +10 -35
  22. package/dist/components/mfa/MfaPhoneNumberDialog.js.map +1 -1
  23. package/dist/components/mfa/MultiFactorAuthentication.d.ts +12 -10
  24. package/dist/components/mfa/MultiFactorAuthentication.js +21 -14
  25. package/dist/components/mfa/MultiFactorAuthentication.js.map +1 -1
  26. package/dist/form-elements/FormElementBarcodeScanner.js +66 -18
  27. package/dist/form-elements/FormElementBarcodeScanner.js.map +1 -1
  28. package/dist/hooks/useLogin.d.ts +16 -2
  29. package/dist/hooks/useLogin.js +53 -3
  30. package/dist/hooks/useLogin.js.map +1 -1
  31. package/dist/hooks/useMfa.d.ts +66 -31
  32. package/dist/hooks/useMfa.js +84 -61
  33. package/dist/hooks/useMfa.js.map +1 -1
  34. package/dist/hooks/useResendCoolDown.d.ts +5 -0
  35. package/dist/hooks/useResendCoolDown.js +27 -0
  36. package/dist/hooks/useResendCoolDown.js.map +1 -0
  37. package/dist/index.d.ts +2 -0
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/styles/barcode-scanner.scss +4 -0
  41. package/dist/styles.css +5 -0
  42. package/dist/styles.scss +1 -0
  43. package/dist/utils/joinArray.d.ts +1 -0
  44. package/dist/utils/joinArray.js +7 -0
  45. package/dist/utils/joinArray.js.map +1 -0
  46. package/dist/utils/mfa-requirement.d.ts +12 -0
  47. package/dist/utils/mfa-requirement.js +149 -0
  48. package/dist/utils/mfa-requirement.js.map +1 -0
  49. package/package.json +3 -3
@@ -1,9 +1,9 @@
1
1
  import { MiscTypes } from '@oneblink/types';
2
2
  import { getIdToken, getFormsKeyId, setFormsKeyToken } from './services/forms-key';
3
- import { registerAuthListener, isLoggedIn, loginHostedUI, loginUsernamePassword, changePassword, forgotPassword, handleAuthentication, logoutHostedUI, getUserProfile, getUserFriendlyName, LoginAttemptResponse, MfaMethod, MfaRequirementCheckResult, MfaSettings, checkIsMfaEnabled, getMfaSettings, updateUserPhoneNumber, removeUserPhoneNumber, sendPhoneNumberVerificationCode, verifyUserPhoneNumber, disableMfaMethod, setPreferredMfaMethod, setupMfaAuthenticatorApp, setupSmsMfa, generateMfaAuthenticatorAppQrCodeUrl, DEFAULT_MFA_SETTINGS } from './services/cognito';
3
+ import { registerAuthListener, isLoggedIn, loginHostedUI, loginUsernamePassword, changePassword, forgotPassword, handleAuthentication, logoutHostedUI, getUserProfile, getUserFriendlyName } from './services/cognito';
4
4
  import { getUserToken, setUserToken } from './services/user-token';
5
- export { registerAuthListener, loginHostedUI, loginUsernamePassword, handleAuthentication, logoutHostedUI, changePassword, forgotPassword, isLoggedIn, getIdToken, getUserProfile, getFormsKeyId, setFormsKeyToken, getUserToken, setUserToken, getUserFriendlyName, checkIsMfaEnabled, getMfaSettings, updateUserPhoneNumber, removeUserPhoneNumber, sendPhoneNumberVerificationCode, verifyUserPhoneNumber, disableMfaMethod, setPreferredMfaMethod, setupMfaAuthenticatorApp, setupSmsMfa, generateMfaAuthenticatorAppQrCodeUrl, DEFAULT_MFA_SETTINGS, };
6
- export type { LoginAttemptResponse, MfaMethod, MfaRequirementCheckResult, MfaSettings, };
5
+ export { registerAuthListener, loginHostedUI, loginUsernamePassword, handleAuthentication, logoutHostedUI, changePassword, forgotPassword, isLoggedIn, getIdToken, getUserProfile, getFormsKeyId, setFormsKeyToken, getUserToken, setUserToken, getUserFriendlyName, };
6
+ export type { LoginAttemptResponse } from './services/cognito';
7
7
  /**
8
8
  * Log the current user out and remove an data stored locally by the user e.g.
9
9
  * drafts.
@@ -34,23 +34,30 @@ export declare function init({ oAuthClientId }: {
34
34
  }): void;
35
35
  /**
36
36
  * Determine if the current user is a OneBlink App User for a OneBlink Forms
37
- * App. Returns `false` if the current user is not logged in.
37
+ * App. Returns `false` if the current user is not logged in or not authorised
38
+ * for the given SAML groups.
38
39
  *
39
40
  * #### Example
40
41
  *
41
42
  * ```js
42
- * const formsAppId = 1
43
- * const isAuthorised = await authService.isAuthorised(formsAppId)
43
+ * const isAuthorised = await authService.isAuthorised({
44
+ * formsAppId: 1,
45
+ * samlGroups: ['group1', 'group2'],
46
+ * })
44
47
  * if (!isAuthorised) {
45
48
  * // handle unauthorised user
46
49
  * }
47
50
  * ```
48
51
  *
49
- * @param formsAppId
52
+ * @param options.formsAppId
53
+ * @param options.samlGroups
50
54
  * @param abortSignal
51
55
  * @returns
52
56
  */
53
- export declare function isAuthorised(formsAppId: number, abortSignal?: AbortSignal): Promise<boolean>;
57
+ export declare function isAuthorised({ formsAppId, samlGroups }: {
58
+ formsAppId: number;
59
+ samlGroups?: string[];
60
+ }, abortSignal?: AbortSignal): Promise<boolean>;
54
61
  /**
55
62
  * Get the current user's App User details for a OneBlink Forms App. Returns
56
63
  * `undefined` if the current user is not logged in.
@@ -1,11 +1,11 @@
1
1
  import OneBlinkAppsError from './services/errors/oneBlinkAppsError';
2
2
  import { getIdToken, getFormsKeyId, setFormsKeyToken, } from './services/forms-key';
3
- import { init as initCognito, registerAuthListener, isLoggedIn, loginHostedUI, loginUsernamePassword, changePassword, forgotPassword, handleAuthentication, logoutHostedUI, logout as logoutCognito, getUserProfile, getUsername, getUserFriendlyName, checkIsMfaEnabled, getMfaSettings, updateUserPhoneNumber, removeUserPhoneNumber, sendPhoneNumberVerificationCode, verifyUserPhoneNumber, disableMfaMethod, setPreferredMfaMethod, setupMfaAuthenticatorApp, setupSmsMfa, generateMfaAuthenticatorAppQrCodeUrl, DEFAULT_MFA_SETTINGS, } from './services/cognito';
3
+ import { init as initCognito, registerAuthListener, isLoggedIn, loginHostedUI, loginUsernamePassword, changePassword, forgotPassword, handleAuthentication, logoutHostedUI, logout as logoutCognito, getUserProfile, getUsername, getUserFriendlyName, } from './services/cognito';
4
4
  import { getRequest, postRequest } from './services/fetch';
5
5
  import tenants from './tenants';
6
6
  import { getUserToken, setUserToken } from './services/user-token';
7
7
  import utilsService from './services/utils';
8
- export { registerAuthListener, loginHostedUI, loginUsernamePassword, handleAuthentication, logoutHostedUI, changePassword, forgotPassword, isLoggedIn, getIdToken, getUserProfile, getFormsKeyId, setFormsKeyToken, getUserToken, setUserToken, getUserFriendlyName, checkIsMfaEnabled, getMfaSettings, updateUserPhoneNumber, removeUserPhoneNumber, sendPhoneNumberVerificationCode, verifyUserPhoneNumber, disableMfaMethod, setPreferredMfaMethod, setupMfaAuthenticatorApp, setupSmsMfa, generateMfaAuthenticatorAppQrCodeUrl, DEFAULT_MFA_SETTINGS, };
8
+ export { registerAuthListener, loginHostedUI, loginUsernamePassword, handleAuthentication, logoutHostedUI, changePassword, forgotPassword, isLoggedIn, getIdToken, getUserProfile, getFormsKeyId, setFormsKeyToken, getUserToken, setUserToken, getUserFriendlyName, };
9
9
  import Sentry from './Sentry';
10
10
  /**
11
11
  * Log the current user out and remove an data stored locally by the user e.g.
@@ -58,25 +58,35 @@ export function init({ oAuthClientId }) {
58
58
  }
59
59
  /**
60
60
  * Determine if the current user is a OneBlink App User for a OneBlink Forms
61
- * App. Returns `false` if the current user is not logged in.
61
+ * App. Returns `false` if the current user is not logged in or not authorised
62
+ * for the given SAML groups.
62
63
  *
63
64
  * #### Example
64
65
  *
65
66
  * ```js
66
- * const formsAppId = 1
67
- * const isAuthorised = await authService.isAuthorised(formsAppId)
67
+ * const isAuthorised = await authService.isAuthorised({
68
+ * formsAppId: 1,
69
+ * samlGroups: ['group1', 'group2'],
70
+ * })
68
71
  * if (!isAuthorised) {
69
72
  * // handle unauthorised user
70
73
  * }
71
74
  * ```
72
75
  *
73
- * @param formsAppId
76
+ * @param options.formsAppId
77
+ * @param options.samlGroups
74
78
  * @param abortSignal
75
79
  * @returns
76
80
  */
77
- export async function isAuthorised(formsAppId, abortSignal) {
81
+ export async function isAuthorised({ formsAppId, samlGroups }, abortSignal) {
78
82
  return getCurrentFormsAppUser(formsAppId, abortSignal)
79
- .then(() => true)
83
+ .then((userProfile) => {
84
+ // if no SAML groups are provided, then provided the user is authenticated then they're authorised
85
+ if (!samlGroups) {
86
+ return true;
87
+ }
88
+ return samlGroups.some((group) => userProfile === null || userProfile === void 0 ? void 0 : userProfile.groups.includes(group));
89
+ })
80
90
  .catch((error) => {
81
91
  if (error.status >= 400 && error.status < 500) {
82
92
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-service.js","sourceRoot":"","sources":["../../src/apps/auth-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { MiscTypes } from '@oneblink/types'\nimport OneBlinkAppsError from './services/errors/oneBlinkAppsError'\nimport {\n getIdToken,\n getFormsKeyId,\n setFormsKeyToken,\n} from './services/forms-key'\nimport {\n init as initCognito,\n registerAuthListener,\n isLoggedIn,\n loginHostedUI,\n loginUsernamePassword,\n changePassword,\n forgotPassword,\n handleAuthentication,\n logoutHostedUI,\n logout as logoutCognito,\n getUserProfile,\n getUsername,\n getUserFriendlyName,\n LoginAttemptResponse,\n MfaMethod,\n MfaRequirementCheckResult,\n MfaSettings,\n checkIsMfaEnabled,\n getMfaSettings,\n updateUserPhoneNumber,\n removeUserPhoneNumber,\n sendPhoneNumberVerificationCode,\n verifyUserPhoneNumber,\n disableMfaMethod,\n setPreferredMfaMethod,\n setupMfaAuthenticatorApp,\n setupSmsMfa,\n generateMfaAuthenticatorAppQrCodeUrl,\n DEFAULT_MFA_SETTINGS,\n} from './services/cognito'\nimport { getRequest, postRequest, HTTPError } from './services/fetch'\nimport tenants from './tenants'\nimport { getUserToken, setUserToken } from './services/user-token'\nimport utilsService from './services/utils'\n\nexport {\n registerAuthListener,\n loginHostedUI,\n loginUsernamePassword,\n handleAuthentication,\n logoutHostedUI,\n changePassword,\n forgotPassword,\n isLoggedIn,\n getIdToken,\n getUserProfile,\n getFormsKeyId,\n setFormsKeyToken,\n getUserToken,\n setUserToken,\n getUserFriendlyName,\n checkIsMfaEnabled,\n getMfaSettings,\n updateUserPhoneNumber,\n removeUserPhoneNumber,\n sendPhoneNumberVerificationCode,\n verifyUserPhoneNumber,\n disableMfaMethod,\n setPreferredMfaMethod,\n setupMfaAuthenticatorApp,\n setupSmsMfa,\n generateMfaAuthenticatorAppQrCodeUrl,\n DEFAULT_MFA_SETTINGS,\n}\nexport type {\n LoginAttemptResponse,\n MfaMethod,\n MfaRequirementCheckResult,\n MfaSettings,\n}\nimport Sentry from './Sentry'\n\n/**\n * Log the current user out and remove an data stored locally by the user e.g.\n * drafts.\n *\n * #### Example\n *\n * ```js\n * await authService.logout()\n * ```\n */\nexport async function logout() {\n console.log('Logging out...')\n\n try {\n await utilsService.localForage.clear()\n } catch (error) {\n Sentry.captureException(error)\n console.warn('Could not clear localForage before logging out', error)\n }\n\n await logoutCognito()\n}\n\n/**\n * Initialize the service with required configuration. **This must be done\n * before using before some of the function in this service.**\n *\n * #### Example\n *\n * ```js\n * authService.init({\n * oAuthClientId: 'YOUR_OAUTH_CLIENT_ID',\n * })\n * ```\n *\n * @param options\n */\nexport function init({ oAuthClientId }: { oAuthClientId: string }) {\n initCognito({\n region: tenants.current.awsRegion,\n loginDomain: tenants.current.loginDomain,\n oAuthClientId,\n redirectUri: window.location.origin + '/callback',\n logoutUri: window.location.origin + '/logout',\n })\n\n const listener = () => {\n Sentry.setTag('username', getUsername() || undefined)\n }\n listener()\n registerAuthListener(listener)\n}\n\n/**\n * Determine if the current user is a OneBlink App User for a OneBlink Forms\n * App. Returns `false` if the current user is not logged in.\n *\n * #### Example\n *\n * ```js\n * const formsAppId = 1\n * const isAuthorised = await authService.isAuthorised(formsAppId)\n * if (!isAuthorised) {\n * // handle unauthorised user\n * }\n * ```\n *\n * @param formsAppId\n * @param abortSignal\n * @returns\n */\nexport async function isAuthorised(\n formsAppId: number,\n abortSignal?: AbortSignal,\n): Promise<boolean> {\n return getCurrentFormsAppUser(formsAppId, abortSignal)\n .then(() => true)\n .catch((error) => {\n if (error.status >= 400 && error.status < 500) {\n return false\n } else {\n Sentry.captureException(error)\n console.log(\n 'Could not determine if the current user has access to this forms app',\n error,\n )\n return false\n }\n })\n}\n\n/**\n * Get the current user's App User details for a OneBlink Forms App. Returns\n * `undefined` if the current user is not logged in.\n *\n * #### Example\n *\n * ```js\n * const formsAppId = 1\n * const formsAppUserDetails =\n * await authService.getCurrentFormsAppUser(formsAppId)\n * if (!formsAppUserDetails) {\n * // handle unauthorised user\n * }\n * ```\n *\n * @param formsAppId\n * @returns\n */\nexport async function getCurrentFormsAppUser(\n formsAppId: number,\n abortSignal?: AbortSignal,\n): Promise<\n | {\n userProfile?: MiscTypes.UserProfile\n formsAppId: number\n groups: string[]\n }\n | undefined\n> {\n if (getFormsKeyId()) {\n return {\n formsAppId,\n groups: [],\n }\n }\n\n const userProfile = getUserProfile()\n\n if (!userProfile) {\n return undefined\n }\n\n const url = `${tenants.current.apiOrigin}/forms-apps/${formsAppId}/my-forms-app-user`\n return await getRequest<{\n userProfile?: MiscTypes.UserProfile\n formsAppId: number\n groups: string[]\n }>(url, abortSignal)\n}\n\n/**\n * If the current user is not a Forms App User, this function will send a\n * request on behalf of the current user to the OneBlink Forms App\n * administrators to request access.\n *\n * #### Example\n *\n * ```js\n * const formsAppId = 1\n * await authService.requestAccess(formsAppId)\n * // Display a message to user indicating a request has been sent to the application administrators\n * ```\n *\n * @param formsAppId\n */\nexport async function requestAccess(formsAppId: number): Promise<void> {\n if (!isLoggedIn()) {\n throw new OneBlinkAppsError(\n 'You must login before requesting access to this application',\n {\n requiresLogin: true,\n },\n )\n }\n\n try {\n const url = `${tenants.current.apiOrigin}/forms-apps/${formsAppId}/request-access`\n await postRequest(url)\n } catch (error) {\n Sentry.captureException(error)\n console.warn('Error while requesting access to forms app', error)\n\n throw new OneBlinkAppsError(\n 'Sorry, we could not request access automatically right now, please try again. If the problem persists, please contact your administrator yourself.',\n {\n originalError: error as Error,\n title: 'Error Requesting Access',\n httpStatusCode: (error as HTTPError).status,\n },\n )\n }\n}\n\n/**\n * Allow a user to sign up to a forms app.\n *\n * #### Example\n *\n * ```js\n * await authService.signUp({\n * formsAppId: 1,\n * email: 'test@oneblink.io',\n * firstName: 'first',\n * lastName: 'last',\n * })\n * ```\n *\n * @param {formsAppId, email, generatePassword, firstName, lastName}\n * @returns\n */\n\nexport async function signUp({\n formsAppId,\n email,\n firstName,\n lastName,\n}: {\n formsAppId: number\n email: string\n firstName?: string\n lastName?: string\n}): Promise<void> {\n try {\n const url = `${tenants.current.apiOrigin}/forms-apps/${formsAppId}/sign-up`\n return await postRequest(url, {\n email,\n firstName,\n lastName,\n })\n } catch (error) {\n Sentry.captureException(error)\n console.warn('Error while calling sign-up to forms app', error)\n\n throw new OneBlinkAppsError(\n 'Sorry, we could not create you a account right now, please try again. If the problem persists, please contact your administrator yourself.',\n {\n originalError: error as Error,\n title: 'Error Signing up',\n httpStatusCode: (error as HTTPError).status,\n },\n )\n }\n}\n"]}
1
+ {"version":3,"file":"auth-service.js","sourceRoot":"","sources":["../../src/apps/auth-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { MiscTypes } from '@oneblink/types'\nimport OneBlinkAppsError from './services/errors/oneBlinkAppsError'\nimport {\n getIdToken,\n getFormsKeyId,\n setFormsKeyToken,\n} from './services/forms-key'\nimport {\n init as initCognito,\n registerAuthListener,\n isLoggedIn,\n loginHostedUI,\n loginUsernamePassword,\n changePassword,\n forgotPassword,\n handleAuthentication,\n logoutHostedUI,\n logout as logoutCognito,\n getUserProfile,\n getUsername,\n getUserFriendlyName,\n} from './services/cognito'\nimport { getRequest, postRequest, HTTPError } from './services/fetch'\nimport tenants from './tenants'\nimport { getUserToken, setUserToken } from './services/user-token'\nimport utilsService from './services/utils'\n\nexport {\n registerAuthListener,\n loginHostedUI,\n loginUsernamePassword,\n handleAuthentication,\n logoutHostedUI,\n changePassword,\n forgotPassword,\n isLoggedIn,\n getIdToken,\n getUserProfile,\n getFormsKeyId,\n setFormsKeyToken,\n getUserToken,\n setUserToken,\n getUserFriendlyName,\n}\nexport type { LoginAttemptResponse } from './services/cognito'\nimport Sentry from './Sentry'\n\n/**\n * Log the current user out and remove an data stored locally by the user e.g.\n * drafts.\n *\n * #### Example\n *\n * ```js\n * await authService.logout()\n * ```\n */\nexport async function logout() {\n console.log('Logging out...')\n\n try {\n await utilsService.localForage.clear()\n } catch (error) {\n Sentry.captureException(error)\n console.warn('Could not clear localForage before logging out', error)\n }\n\n await logoutCognito()\n}\n\n/**\n * Initialize the service with required configuration. **This must be done\n * before using before some of the function in this service.**\n *\n * #### Example\n *\n * ```js\n * authService.init({\n * oAuthClientId: 'YOUR_OAUTH_CLIENT_ID',\n * })\n * ```\n *\n * @param options\n */\nexport function init({ oAuthClientId }: { oAuthClientId: string }) {\n initCognito({\n region: tenants.current.awsRegion,\n loginDomain: tenants.current.loginDomain,\n oAuthClientId,\n redirectUri: window.location.origin + '/callback',\n logoutUri: window.location.origin + '/logout',\n })\n\n const listener = () => {\n Sentry.setTag('username', getUsername() || undefined)\n }\n listener()\n registerAuthListener(listener)\n}\n\n/**\n * Determine if the current user is a OneBlink App User for a OneBlink Forms\n * App. Returns `false` if the current user is not logged in or not authorised\n * for the given SAML groups.\n *\n * #### Example\n *\n * ```js\n * const isAuthorised = await authService.isAuthorised({\n * formsAppId: 1,\n * samlGroups: ['group1', 'group2'],\n * })\n * if (!isAuthorised) {\n * // handle unauthorised user\n * }\n * ```\n *\n * @param options.formsAppId\n * @param options.samlGroups\n * @param abortSignal\n * @returns\n */\nexport async function isAuthorised(\n { formsAppId, samlGroups }: { formsAppId: number; samlGroups?: string[] },\n abortSignal?: AbortSignal,\n): Promise<boolean> {\n return getCurrentFormsAppUser(formsAppId, abortSignal)\n .then((userProfile) => {\n // if no SAML groups are provided, then provided the user is authenticated then they're authorised\n if (!samlGroups) {\n return true\n }\n return samlGroups.some((group) => userProfile?.groups.includes(group))\n })\n .catch((error) => {\n if (error.status >= 400 && error.status < 500) {\n return false\n } else {\n Sentry.captureException(error)\n console.log(\n 'Could not determine if the current user has access to this forms app',\n error,\n )\n return false\n }\n })\n}\n\n/**\n * Get the current user's App User details for a OneBlink Forms App. Returns\n * `undefined` if the current user is not logged in.\n *\n * #### Example\n *\n * ```js\n * const formsAppId = 1\n * const formsAppUserDetails =\n * await authService.getCurrentFormsAppUser(formsAppId)\n * if (!formsAppUserDetails) {\n * // handle unauthorised user\n * }\n * ```\n *\n * @param formsAppId\n * @returns\n */\nexport async function getCurrentFormsAppUser(\n formsAppId: number,\n abortSignal?: AbortSignal,\n): Promise<\n | {\n userProfile?: MiscTypes.UserProfile\n formsAppId: number\n groups: string[]\n }\n | undefined\n> {\n if (getFormsKeyId()) {\n return {\n formsAppId,\n groups: [],\n }\n }\n\n const userProfile = getUserProfile()\n\n if (!userProfile) {\n return undefined\n }\n\n const url = `${tenants.current.apiOrigin}/forms-apps/${formsAppId}/my-forms-app-user`\n return await getRequest<{\n userProfile?: MiscTypes.UserProfile\n formsAppId: number\n groups: string[]\n }>(url, abortSignal)\n}\n\n/**\n * If the current user is not a Forms App User, this function will send a\n * request on behalf of the current user to the OneBlink Forms App\n * administrators to request access.\n *\n * #### Example\n *\n * ```js\n * const formsAppId = 1\n * await authService.requestAccess(formsAppId)\n * // Display a message to user indicating a request has been sent to the application administrators\n * ```\n *\n * @param formsAppId\n */\nexport async function requestAccess(formsAppId: number): Promise<void> {\n if (!isLoggedIn()) {\n throw new OneBlinkAppsError(\n 'You must login before requesting access to this application',\n {\n requiresLogin: true,\n },\n )\n }\n\n try {\n const url = `${tenants.current.apiOrigin}/forms-apps/${formsAppId}/request-access`\n await postRequest(url)\n } catch (error) {\n Sentry.captureException(error)\n console.warn('Error while requesting access to forms app', error)\n\n throw new OneBlinkAppsError(\n 'Sorry, we could not request access automatically right now, please try again. If the problem persists, please contact your administrator yourself.',\n {\n originalError: error as Error,\n title: 'Error Requesting Access',\n httpStatusCode: (error as HTTPError).status,\n },\n )\n }\n}\n\n/**\n * Allow a user to sign up to a forms app.\n *\n * #### Example\n *\n * ```js\n * await authService.signUp({\n * formsAppId: 1,\n * email: 'test@oneblink.io',\n * firstName: 'first',\n * lastName: 'last',\n * })\n * ```\n *\n * @param {formsAppId, email, generatePassword, firstName, lastName}\n * @returns\n */\n\nexport async function signUp({\n formsAppId,\n email,\n firstName,\n lastName,\n}: {\n formsAppId: number\n email: string\n firstName?: string\n lastName?: string\n}): Promise<void> {\n try {\n const url = `${tenants.current.apiOrigin}/forms-apps/${formsAppId}/sign-up`\n return await postRequest(url, {\n email,\n firstName,\n lastName,\n })\n } catch (error) {\n Sentry.captureException(error)\n console.warn('Error while calling sign-up to forms app', error)\n\n throw new OneBlinkAppsError(\n 'Sorry, we could not create you a account right now, please try again. If the problem persists, please contact your administrator yourself.',\n {\n originalError: error as Error,\n title: 'Error Signing up',\n httpStatusCode: (error as HTTPError).status,\n },\n )\n }\n}\n"]}
@@ -21,6 +21,16 @@ export * as offlineService from './offline-service';
21
21
  * ```
22
22
  */
23
23
  export * as authService from './auth-service';
24
+ /**
25
+ * ## MFA Service
26
+ *
27
+ * Helper functions for multi factor authentication and MFA requirements.
28
+ *
29
+ * ```js
30
+ * import { mfaService } from '@oneblink/apps-react'
31
+ * ```
32
+ */
33
+ export * as mfaService from './mfa-service';
24
34
  /**
25
35
  * ## Draft Service
26
36
  *
@@ -21,6 +21,16 @@ export * as offlineService from './offline-service';
21
21
  * ```
22
22
  */
23
23
  export * as authService from './auth-service';
24
+ /**
25
+ * ## MFA Service
26
+ *
27
+ * Helper functions for multi factor authentication and MFA requirements.
28
+ *
29
+ * ```js
30
+ * import { mfaService } from '@oneblink/apps-react'
31
+ * ```
32
+ */
33
+ export * as mfaService from './mfa-service';
24
34
  /**
25
35
  * ## Draft Service
26
36
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apps/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAA;AACnD;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAA;AAC7C;;;;;;;;GAQG;AACH,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAA;AAC/C;;;;;;;;GAQG;AACH,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAA;AACnD;;;;;;;;GAQG;AACH,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAA;AACnD;;;;;;;;GAQG;AACH,OAAO,KAAK,iBAAiB,MAAM,sBAAsB,CAAA;AACzD;;;;;;;;GAQG;AACH,OAAO,KAAK,UAAU,MAAM,eAAe,CAAA;AAC3C;;;;;;;;GAQG;AACH,OAAO,KAAK,iBAAiB,MAAM,sBAAsB,CAAA;AACzD;;;;;;;;GAQG;AACH,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAA;AACtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,OAAO,KAAK,mBAAmB,MAAM,wBAAwB,CAAA;AAC7D;;;;;;;;GAQG;AACH,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAA;AAC7C;;;;;;;;GAQG;AACH,OAAO,KAAK,gBAAgB,MAAM,qBAAqB,CAAA;AACvD;;;;;;;;GAQG;AACH,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAA;AACtD;;;;;;;;GAQG;AACH,OAAO,KAAK,gBAAgB,MAAM,sBAAsB,CAAA;AACxD;;;;;;;;GAQG;AACH,OAAO,KAAK,mBAAmB,MAAM,wBAAwB,CAAA;AAC7D;;;;;;;;GAQG;AACH,OAAO,KAAK,kBAAkB,MAAM,uBAAuB,CAAA;AAC3D;;;;;;;;GAQG;AACH,OAAO,KAAK,qBAAqB,MAAM,2BAA2B,CAAA;AAClE;;;;;;;;GAQG;AACH,OAAO,KAAK,0BAA0B,MAAM,iCAAiC,CAAA;AAE7E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAA;AAE5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,CAAA;AAC9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;AAC5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,CAAA","sourcesContent":["/**\n * ## Offline Service\n *\n * Helper functions for offline handling\n *\n * ```js\n * import { offlineService } from '@oneblink/apps-react'\n * ```\n */\nexport * as offlineService from './offline-service'\n/**\n * ## Authentication/Authorisation Service\n *\n * Helper functions for handling user authentication and authorisation.\n *\n * **NOTE: `init()` must be called before using some of the functions in this\n * service.**\n *\n * ```js\n * import { authService } from '@oneblink/apps-react'\n * ```\n */\nexport * as authService from './auth-service'\n/**\n * ## Draft Service\n *\n * Helper functions for handling drafts.\n *\n * ```js\n * import { draftService } from '@oneblink/apps-react'\n * ```\n */\nexport * as draftService from './draft-service'\n/**\n * ## Prefill Service\n *\n * Helper functions for offline handling\n *\n * ```js\n * import { prefillService } from '@oneblink/apps-react'\n * ```\n */\nexport * as prefillService from './prefill-service'\n/**\n * ## Payment Service\n *\n * Helper functions for payment handling\n *\n * ```js\n * import { paymentService } from '@oneblink/apps-react'\n * ```\n */\nexport * as paymentService from './payment-service'\n/**\n * ## Scheduling Service\n *\n * Helper functions for scheduling booking handling\n *\n * ```js\n * import { schedulingService } from '@oneblink/apps-react'\n * ```\n */\nexport * as schedulingService from './scheduling-service'\n/**\n * ## Job Service\n *\n * Helper functions for job handling\n *\n * ```js\n * import { jobService } from '@oneblink/apps-react'\n * ```\n */\nexport * as jobService from './job-service'\n/**\n * ## Submission Service\n *\n * Helper functions for handling form submissions\n *\n * ```js\n * import { submissionService } from '@oneblink/apps-react'\n * ```\n */\nexport * as submissionService from './submission-service'\n/**\n * ## Auto Save Service\n *\n * Helper functions for handling data while user is completing form.\n *\n * ```js\n * import { autoSaveService } from '@oneblink/apps-react'\n * ```\n */\nexport * as autoSaveService from './auto-save-service'\n/**\n * ## Notification Service\n *\n * Helper functions for notification handling\n *\n * ```js\n * import { notificationService } from '@oneblink/apps-react'\n * ```\n *\n * ### Service Worker\n *\n * To display push notifications and allow them to be clicked to open the\n * application, add the following JavaScript to your service worker (we\n * recommend using\n * [offline-plugin](https://www.npmjs.com/package/offline-plugin)):\n *\n * #### Example\n *\n * ```js\n * self.addEventListener('push', (event) => {\n * console.log('push event', event)\n *\n * if (!event.data) {\n * console.log('Received push event without any data', event)\n * return\n * }\n * const notification = event.data.json()\n *\n * event.waitUntil(\n * clients.matchAll().then((c) => {\n * if (c.length === 0 || c.every((client) => !client.focused)) {\n * // Show notification\n * return self.registration.showNotification(\n * notification.title,\n * notification.options,\n * )\n * } else {\n * console.log('Application is already open!')\n * }\n * }),\n * )\n * })\n *\n * self.addEventListener('notificationclick', (event) => {\n * console.log('notification click event', event)\n *\n * const pathname =\n * event.notification.data && event.notification.data.pathname\n * ? event.notification.data.pathname\n * : '/'\n *\n * event.waitUntil(\n * clients.matchAll().then((clis) => {\n * const client = clis[0]\n * if (client === undefined) {\n * // there are no visible windows. Open one.\n * clients.openWindow(pathname)\n * } else {\n * client.navigate(pathname)\n * client.focus()\n * }\n *\n * return self.registration\n * .getNotifications()\n * .then((notifications) => {\n * notifications.forEach((notification) => {\n * notification.close()\n * })\n * })\n * }),\n * )\n * })\n * ```\n */\nexport * as notificationService from './notification-service'\n/**\n * ## Form Service\n *\n * Helper functions for form handling\n *\n * ```js\n * import { formService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formService from './form-service'\n/**\n * ## Approvals Service\n *\n * Helper functions for handling approvals\n *\n * ```js\n * import { approvalsService } from '@oneblink/apps-react'\n * ```\n */\nexport * as approvalsService from './approvals-service'\n/**\n * ## Forms App Service\n *\n * Helper functions for forms apps\n *\n * ```js\n * import { formsAppService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formsAppService from './forms-app-service'\n/**\n * ## Form Store Service\n *\n * Helper functions for handling Form Store Records\n *\n * ```js\n * import { formStoreService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formStoreService from './form-store-service'\n/**\n * ## Localisation Service\n *\n * Helper functions for handling all things locale.\n *\n * ```js\n * import { localisationService } from '@oneblink/apps-react'\n * ```\n */\nexport * as localisationService from './localisation-service'\n/**\n * ## Attachments Service\n *\n * Helper functions for attachment handling\n *\n * ```js\n * import { attachmentsService } from '@oneblink/apps-react'\n * ```\n */\nexport * as attachmentsService from './attachments-service'\n/**\n * ## Scheduled Tasks Service\n *\n * Helper functions for scheduled tasks\n *\n * ```js\n * import { scheduledTasksService } from '@oneblink/apps-react'\n * ```\n */\nexport * as scheduledTasksService from './scheduled-tasks-service'\n/**\n * ## Forms App Environment Service\n *\n * Helper functions for forms app environments\n *\n * ```js\n * import { formsAppEnvironmentService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formsAppEnvironmentService from './forms-app-environment-service'\n\nexport { default as OneBlinkAppsError } from './services/errors/oneBlinkAppsError'\nimport tenants from './tenants'\nexport { default as Sentry } from './Sentry'\n\nexport const useTenantCivicPlus = () => tenants.useCivicPlus()\nexport const useTenantOneBlink = () => tenants.useOneBlink()\nexport const useTenantOneBlinkUS = () => tenants.useOneBlinkUS()\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/apps/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAA;AACnD;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAA;AAC7C;;;;;;;;GAQG;AACH,OAAO,KAAK,UAAU,MAAM,eAAe,CAAA;AAC3C;;;;;;;;GAQG;AACH,OAAO,KAAK,YAAY,MAAM,iBAAiB,CAAA;AAC/C;;;;;;;;GAQG;AACH,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAA;AACnD;;;;;;;;GAQG;AACH,OAAO,KAAK,cAAc,MAAM,mBAAmB,CAAA;AACnD;;;;;;;;GAQG;AACH,OAAO,KAAK,iBAAiB,MAAM,sBAAsB,CAAA;AACzD;;;;;;;;GAQG;AACH,OAAO,KAAK,UAAU,MAAM,eAAe,CAAA;AAC3C;;;;;;;;GAQG;AACH,OAAO,KAAK,iBAAiB,MAAM,sBAAsB,CAAA;AACzD;;;;;;;;GAQG;AACH,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAA;AACtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AACH,OAAO,KAAK,mBAAmB,MAAM,wBAAwB,CAAA;AAC7D;;;;;;;;GAQG;AACH,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAA;AAC7C;;;;;;;;GAQG;AACH,OAAO,KAAK,gBAAgB,MAAM,qBAAqB,CAAA;AACvD;;;;;;;;GAQG;AACH,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAA;AACtD;;;;;;;;GAQG;AACH,OAAO,KAAK,gBAAgB,MAAM,sBAAsB,CAAA;AACxD;;;;;;;;GAQG;AACH,OAAO,KAAK,mBAAmB,MAAM,wBAAwB,CAAA;AAC7D;;;;;;;;GAQG;AACH,OAAO,KAAK,kBAAkB,MAAM,uBAAuB,CAAA;AAC3D;;;;;;;;GAQG;AACH,OAAO,KAAK,qBAAqB,MAAM,2BAA2B,CAAA;AAClE;;;;;;;;GAQG;AACH,OAAO,KAAK,0BAA0B,MAAM,iCAAiC,CAAA;AAE7E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAClF,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAA;AAE5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,CAAA;AAC9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;AAC5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,CAAA","sourcesContent":["/**\n * ## Offline Service\n *\n * Helper functions for offline handling\n *\n * ```js\n * import { offlineService } from '@oneblink/apps-react'\n * ```\n */\nexport * as offlineService from './offline-service'\n/**\n * ## Authentication/Authorisation Service\n *\n * Helper functions for handling user authentication and authorisation.\n *\n * **NOTE: `init()` must be called before using some of the functions in this\n * service.**\n *\n * ```js\n * import { authService } from '@oneblink/apps-react'\n * ```\n */\nexport * as authService from './auth-service'\n/**\n * ## MFA Service\n *\n * Helper functions for multi factor authentication and MFA requirements.\n *\n * ```js\n * import { mfaService } from '@oneblink/apps-react'\n * ```\n */\nexport * as mfaService from './mfa-service'\n/**\n * ## Draft Service\n *\n * Helper functions for handling drafts.\n *\n * ```js\n * import { draftService } from '@oneblink/apps-react'\n * ```\n */\nexport * as draftService from './draft-service'\n/**\n * ## Prefill Service\n *\n * Helper functions for offline handling\n *\n * ```js\n * import { prefillService } from '@oneblink/apps-react'\n * ```\n */\nexport * as prefillService from './prefill-service'\n/**\n * ## Payment Service\n *\n * Helper functions for payment handling\n *\n * ```js\n * import { paymentService } from '@oneblink/apps-react'\n * ```\n */\nexport * as paymentService from './payment-service'\n/**\n * ## Scheduling Service\n *\n * Helper functions for scheduling booking handling\n *\n * ```js\n * import { schedulingService } from '@oneblink/apps-react'\n * ```\n */\nexport * as schedulingService from './scheduling-service'\n/**\n * ## Job Service\n *\n * Helper functions for job handling\n *\n * ```js\n * import { jobService } from '@oneblink/apps-react'\n * ```\n */\nexport * as jobService from './job-service'\n/**\n * ## Submission Service\n *\n * Helper functions for handling form submissions\n *\n * ```js\n * import { submissionService } from '@oneblink/apps-react'\n * ```\n */\nexport * as submissionService from './submission-service'\n/**\n * ## Auto Save Service\n *\n * Helper functions for handling data while user is completing form.\n *\n * ```js\n * import { autoSaveService } from '@oneblink/apps-react'\n * ```\n */\nexport * as autoSaveService from './auto-save-service'\n/**\n * ## Notification Service\n *\n * Helper functions for notification handling\n *\n * ```js\n * import { notificationService } from '@oneblink/apps-react'\n * ```\n *\n * ### Service Worker\n *\n * To display push notifications and allow them to be clicked to open the\n * application, add the following JavaScript to your service worker (we\n * recommend using\n * [offline-plugin](https://www.npmjs.com/package/offline-plugin)):\n *\n * #### Example\n *\n * ```js\n * self.addEventListener('push', (event) => {\n * console.log('push event', event)\n *\n * if (!event.data) {\n * console.log('Received push event without any data', event)\n * return\n * }\n * const notification = event.data.json()\n *\n * event.waitUntil(\n * clients.matchAll().then((c) => {\n * if (c.length === 0 || c.every((client) => !client.focused)) {\n * // Show notification\n * return self.registration.showNotification(\n * notification.title,\n * notification.options,\n * )\n * } else {\n * console.log('Application is already open!')\n * }\n * }),\n * )\n * })\n *\n * self.addEventListener('notificationclick', (event) => {\n * console.log('notification click event', event)\n *\n * const pathname =\n * event.notification.data && event.notification.data.pathname\n * ? event.notification.data.pathname\n * : '/'\n *\n * event.waitUntil(\n * clients.matchAll().then((clis) => {\n * const client = clis[0]\n * if (client === undefined) {\n * // there are no visible windows. Open one.\n * clients.openWindow(pathname)\n * } else {\n * client.navigate(pathname)\n * client.focus()\n * }\n *\n * return self.registration\n * .getNotifications()\n * .then((notifications) => {\n * notifications.forEach((notification) => {\n * notification.close()\n * })\n * })\n * }),\n * )\n * })\n * ```\n */\nexport * as notificationService from './notification-service'\n/**\n * ## Form Service\n *\n * Helper functions for form handling\n *\n * ```js\n * import { formService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formService from './form-service'\n/**\n * ## Approvals Service\n *\n * Helper functions for handling approvals\n *\n * ```js\n * import { approvalsService } from '@oneblink/apps-react'\n * ```\n */\nexport * as approvalsService from './approvals-service'\n/**\n * ## Forms App Service\n *\n * Helper functions for forms apps\n *\n * ```js\n * import { formsAppService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formsAppService from './forms-app-service'\n/**\n * ## Form Store Service\n *\n * Helper functions for handling Form Store Records\n *\n * ```js\n * import { formStoreService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formStoreService from './form-store-service'\n/**\n * ## Localisation Service\n *\n * Helper functions for handling all things locale.\n *\n * ```js\n * import { localisationService } from '@oneblink/apps-react'\n * ```\n */\nexport * as localisationService from './localisation-service'\n/**\n * ## Attachments Service\n *\n * Helper functions for attachment handling\n *\n * ```js\n * import { attachmentsService } from '@oneblink/apps-react'\n * ```\n */\nexport * as attachmentsService from './attachments-service'\n/**\n * ## Scheduled Tasks Service\n *\n * Helper functions for scheduled tasks\n *\n * ```js\n * import { scheduledTasksService } from '@oneblink/apps-react'\n * ```\n */\nexport * as scheduledTasksService from './scheduled-tasks-service'\n/**\n * ## Forms App Environment Service\n *\n * Helper functions for forms app environments\n *\n * ```js\n * import { formsAppEnvironmentService } from '@oneblink/apps-react'\n * ```\n */\nexport * as formsAppEnvironmentService from './forms-app-environment-service'\n\nexport { default as OneBlinkAppsError } from './services/errors/oneBlinkAppsError'\nimport tenants from './tenants'\nexport { default as Sentry } from './Sentry'\n\nexport const useTenantCivicPlus = () => tenants.useCivicPlus()\nexport const useTenantOneBlink = () => tenants.useOneBlink()\nexport const useTenantOneBlinkUS = () => tenants.useOneBlinkUS()\n"]}
@@ -0,0 +1,29 @@
1
+ import { MiscTypes } from '@oneblink/types';
2
+ import { getMfaSettings } from './services/cognito';
3
+ export { getMfaSettings };
4
+ export { updateUserPhoneNumber, removeUserPhoneNumber, verifyUserPhoneNumber, disableMfaMethod, setPreferredMfaMethod, setupMfaAuthenticatorApp, setupSmsMfa, generateMfaAuthenticatorAppQrCodeUrl, DEFAULT_MFA_SETTINGS, } from './services/cognito';
5
+ export type { MfaMethod, MfaSettings, LoggedInMfaMethod } from './services/cognito';
6
+ export { isMfaRequired, mfaRequirementToSelectedMethods, mfaSelectedMethodsToMfaRequirement, formatMfaRequirementLabel, userMeetsMfaRequirement, formatMfaSetupRequiredMessage, formatMfaMethodRequirementMessage, isMfaMethodUsedForLogin, } from '../utils/mfa-requirement';
7
+ export type { MfaRequirementMethod } from '../utils/mfa-requirement';
8
+ export type MfaRequirementCheckResult = {
9
+ mfaSettings: Awaited<ReturnType<typeof getMfaSettings>>;
10
+ userMeetsMfaRequirement: boolean;
11
+ };
12
+ /**
13
+ * Check if the current user meets an MFA requirement.
14
+ *
15
+ * #### Example
16
+ *
17
+ * ```js
18
+ * const { mfaSettings, userMeetsMfaRequirement } =
19
+ * await mfaService.checkIsMfaEnabled('any')
20
+ * if (userMeetsMfaRequirement) {
21
+ * // User has met the MFA requirement
22
+ * } else {
23
+ * // Prompt user to set up MFA
24
+ * }
25
+ * ```
26
+ *
27
+ * @returns
28
+ */
29
+ export declare function checkIsMfaEnabled(mfaRequirement: MiscTypes.MfaRequirement | undefined): Promise<MfaRequirementCheckResult>;
@@ -0,0 +1,30 @@
1
+ import { getMfaSettings } from './services/cognito';
2
+ import { userMeetsMfaRequirement } from '../utils/mfa-requirement';
3
+ export { getMfaSettings };
4
+ export { updateUserPhoneNumber, removeUserPhoneNumber, verifyUserPhoneNumber, disableMfaMethod, setPreferredMfaMethod, setupMfaAuthenticatorApp, setupSmsMfa, generateMfaAuthenticatorAppQrCodeUrl, DEFAULT_MFA_SETTINGS, } from './services/cognito';
5
+ export { isMfaRequired, mfaRequirementToSelectedMethods, mfaSelectedMethodsToMfaRequirement, formatMfaRequirementLabel, userMeetsMfaRequirement, formatMfaSetupRequiredMessage, formatMfaMethodRequirementMessage, isMfaMethodUsedForLogin, } from '../utils/mfa-requirement';
6
+ /**
7
+ * Check if the current user meets an MFA requirement.
8
+ *
9
+ * #### Example
10
+ *
11
+ * ```js
12
+ * const { mfaSettings, userMeetsMfaRequirement } =
13
+ * await mfaService.checkIsMfaEnabled('any')
14
+ * if (userMeetsMfaRequirement) {
15
+ * // User has met the MFA requirement
16
+ * } else {
17
+ * // Prompt user to set up MFA
18
+ * }
19
+ * ```
20
+ *
21
+ * @returns
22
+ */
23
+ export async function checkIsMfaEnabled(mfaRequirement) {
24
+ const mfaSettings = await getMfaSettings();
25
+ return {
26
+ mfaSettings,
27
+ userMeetsMfaRequirement: userMeetsMfaRequirement(mfaRequirement, mfaSettings),
28
+ };
29
+ }
30
+ //# sourceMappingURL=mfa-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mfa-service.js","sourceRoot":"","sources":["../../src/apps/mfa-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAElE,OAAO,EAAE,cAAc,EAAE,CAAA;AACzB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,oCAAoC,EACpC,oBAAoB,GACrB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EACL,aAAa,EACb,+BAA+B,EAC/B,kCAAkC,EAClC,yBAAyB,EACzB,uBAAuB,EACvB,6BAA6B,EAC7B,iCAAiC,EACjC,uBAAuB,GACxB,MAAM,0BAA0B,CAAA;AAQjC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,cAAoD;IAEpD,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAA;IAE1C,OAAO;QACL,WAAW;QACX,uBAAuB,EAAE,uBAAuB,CAC9C,cAAc,EACd,WAAW,CACZ;KACF,CAAA;AACH,CAAC","sourcesContent":["import { MiscTypes } from '@oneblink/types'\r\nimport { getMfaSettings } from './services/cognito'\r\nimport { userMeetsMfaRequirement } from '../utils/mfa-requirement'\r\n\r\nexport { getMfaSettings }\r\nexport {\r\n updateUserPhoneNumber,\r\n removeUserPhoneNumber,\r\n verifyUserPhoneNumber,\r\n disableMfaMethod,\r\n setPreferredMfaMethod,\r\n setupMfaAuthenticatorApp,\r\n setupSmsMfa,\r\n generateMfaAuthenticatorAppQrCodeUrl,\r\n DEFAULT_MFA_SETTINGS,\r\n} from './services/cognito'\r\nexport type { MfaMethod, MfaSettings, LoggedInMfaMethod } from './services/cognito'\r\nexport {\r\n isMfaRequired,\r\n mfaRequirementToSelectedMethods,\r\n mfaSelectedMethodsToMfaRequirement,\r\n formatMfaRequirementLabel,\r\n userMeetsMfaRequirement,\r\n formatMfaSetupRequiredMessage,\r\n formatMfaMethodRequirementMessage,\r\n isMfaMethodUsedForLogin,\r\n} from '../utils/mfa-requirement'\r\nexport type { MfaRequirementMethod } from '../utils/mfa-requirement'\r\n\r\nexport type MfaRequirementCheckResult = {\r\n mfaSettings: Awaited<ReturnType<typeof getMfaSettings>>\r\n userMeetsMfaRequirement: boolean\r\n}\r\n\r\n/**\r\n * Check if the current user meets an MFA requirement.\r\n *\r\n * #### Example\r\n *\r\n * ```js\r\n * const { mfaSettings, userMeetsMfaRequirement } =\r\n * await mfaService.checkIsMfaEnabled('any')\r\n * if (userMeetsMfaRequirement) {\r\n * // User has met the MFA requirement\r\n * } else {\r\n * // Prompt user to set up MFA\r\n * }\r\n * ```\r\n *\r\n * @returns\r\n */\r\nexport async function checkIsMfaEnabled(\r\n mfaRequirement: MiscTypes.MfaRequirement | undefined,\r\n): Promise<MfaRequirementCheckResult> {\r\n const mfaSettings = await getMfaSettings()\r\n\r\n return {\r\n mfaSettings,\r\n userMeetsMfaRequirement: userMeetsMfaRequirement(\r\n mfaRequirement,\r\n mfaSettings,\r\n ),\r\n }\r\n}\r\n"]}
@@ -1,7 +1,8 @@
1
1
  import { AuthenticationResultType, CognitoIdentityProviderClient, InitiateAuthResponse } from '@aws-sdk/client-cognito-identity-provider';
2
- import { MiscTypes } from '@oneblink/types';
3
2
  export type MfaMethod = 'authenticator' | 'sms';
3
+ export type LoggedInMfaMethod = 'SOFTWARE_TOKEN_MFA' | 'SMS_MFA' | 'NO_MFA_ENABLED';
4
4
  export type MfaSettings = {
5
+ loggedInWithMfaMethod: LoggedInMfaMethod;
5
6
  authenticator: {
6
7
  enabled: boolean;
7
8
  preferred: boolean;
@@ -14,16 +15,23 @@ export type MfaSettings = {
14
15
  };
15
16
  };
16
17
  export declare const DEFAULT_MFA_SETTINGS: MfaSettings;
17
- export type MfaRequirementCheckResult = {
18
- mfaSettings: MfaSettings;
19
- userMeetsMfaRequirement: boolean;
18
+ export declare function resolveLoggedInMfaMethod(idToken: string | undefined): LoggedInMfaMethod;
19
+ export declare function resolveMfaPreferredFlags({ authenticatorEnabled, smsEnabled, preferredMfaSetting, }: {
20
+ authenticatorEnabled: boolean;
21
+ smsEnabled: boolean;
22
+ preferredMfaSetting: string | undefined;
23
+ }): {
24
+ authenticatorPreferred: boolean;
25
+ smsPreferred: boolean;
26
+ };
27
+ export type LoginAttemptMfa = {
28
+ method: MfaMethod;
29
+ codeCallback: (code: string) => Promise<LoginAttemptResponse>;
30
+ resendCodeCallback?: () => Promise<LoginAttemptResponse>;
20
31
  };
21
32
  export type LoginAttemptResponse = {
22
33
  resetPasswordCallback?: (newPassword: string) => Promise<LoginAttemptResponse>;
23
- mfa?: {
24
- codeCallback: (code: string) => Promise<LoginAttemptResponse>;
25
- method: MfaMethod;
26
- };
34
+ mfa?: LoginAttemptMfa;
27
35
  };
28
36
  export default class AWSCognitoClient {
29
37
  clientId: string;
@@ -54,7 +62,7 @@ export default class AWSCognitoClient {
54
62
  _isSessionValid(): boolean;
55
63
  _refreshSession(): Promise<void>;
56
64
  registerListener(listener: () => unknown): () => void;
57
- responseToAuthChallenge(username: string, initiateAuthResponse: InitiateAuthResponse): Promise<LoginAttemptResponse>;
65
+ responseToAuthChallenge(username: string, initiateAuthResponse: InitiateAuthResponse, password?: string): Promise<LoginAttemptResponse>;
58
66
  loginUsernamePassword(username: string, password: string): Promise<LoginAttemptResponse>;
59
67
  loginHostedUI(identityProviderName?: string): Promise<void>;
60
68
  handleAuthentication(): Promise<void>;
@@ -69,12 +77,10 @@ export default class AWSCognitoClient {
69
77
  getIdToken(): Promise<string | undefined>;
70
78
  getAccessToken(): Promise<string | undefined>;
71
79
  getMfaSettings(abortSignal?: AbortSignal): Promise<MfaSettings>;
72
- checkIsMfaEnabled(mfaRequirement: MiscTypes.MfaRequirement | undefined): Promise<MfaRequirementCheckResult>;
73
80
  updateUserPhoneNumber(phoneNumber: string): Promise<{
74
81
  isPhoneNumberVerified: boolean;
75
82
  }>;
76
83
  removeUserPhoneNumber(): Promise<void>;
77
- sendPhoneNumberVerificationCode(): Promise<import("@aws-sdk/client-cognito-identity-provider").GetUserAttributeVerificationCodeCommandOutput | undefined>;
78
84
  verifyUserPhoneNumber(code: string): Promise<void>;
79
85
  setPreferredMfaMethod(method: MfaMethod): Promise<void>;
80
86
  disableMfaMethod(method: MfaMethod): Promise<void>;
@@ -1,7 +1,9 @@
1
- import { AssociateSoftwareTokenCommand, ChangePasswordCommand, CognitoIdentityProviderClient, ConfirmForgotPasswordCommand, DeleteUserAttributesCommand, GetUserAttributeVerificationCodeCommand, GetUserCommand, GlobalSignOutCommand, InitiateAuthCommand, RespondToAuthChallengeCommand, SetUserMFAPreferenceCommand, UpdateUserAttributesCommand, VerifySoftwareTokenCommand, VerifyUserAttributeCommand, } from '@aws-sdk/client-cognito-identity-provider';
1
+ import { AssociateSoftwareTokenCommand, ChangePasswordCommand, CognitoIdentityProviderClient, ConfirmForgotPasswordCommand, DeleteUserAttributesCommand, GetUserCommand, GlobalSignOutCommand, InitiateAuthCommand, RespondToAuthChallengeCommand, SetUserMFAPreferenceCommand, UpdateUserAttributesCommand, VerifySoftwareTokenCommand, VerifyUserAttributeCommand, } from '@aws-sdk/client-cognito-identity-provider';
2
+ import { jwtDecode } from 'jwt-decode';
2
3
  import Sentry from '../Sentry';
3
4
  import { OneBlinkAppsError } from '..';
4
5
  export const DEFAULT_MFA_SETTINGS = {
6
+ loggedInWithMfaMethod: 'NO_MFA_ENABLED',
5
7
  authenticator: { enabled: false, preferred: false },
6
8
  sms: {
7
9
  enabled: false,
@@ -10,19 +12,39 @@ export const DEFAULT_MFA_SETTINGS = {
10
12
  isPhoneNumberVerified: false,
11
13
  },
12
14
  };
13
- const MFA_REQUIREMENT_METHOD_CHECKS = {
14
- sms: (mfaSettings) => mfaSettings.sms.enabled,
15
- authenticatorApp: (mfaSettings) => mfaSettings.authenticator.enabled,
16
- };
17
- function checkUserMeetsMfaRequirement(mfaRequirement, mfaSettings) {
18
- if (!mfaRequirement) {
19
- return true;
15
+ export function resolveLoggedInMfaMethod(idToken) {
16
+ if (idToken) {
17
+ try {
18
+ const payload = jwtDecode(idToken);
19
+ switch (payload.mfa_method) {
20
+ case 'SOFTWARE_TOKEN_MFA':
21
+ case 'SMS_MFA':
22
+ return payload.mfa_method;
23
+ }
24
+ }
25
+ catch (error) {
26
+ console.warn('Error while decoding id token for logged in MFA method', error);
27
+ Sentry.captureException(error);
28
+ }
20
29
  }
21
- const requiredMethods = Object.keys(MFA_REQUIREMENT_METHOD_CHECKS).filter((method) => mfaRequirement[method]);
22
- if (requiredMethods.length === 0) {
23
- return true;
30
+ return 'NO_MFA_ENABLED';
31
+ }
32
+ export function resolveMfaPreferredFlags({ authenticatorEnabled, smsEnabled, preferredMfaSetting, }) {
33
+ const cognitoAuthenticatorPreferred = preferredMfaSetting === 'SOFTWARE_TOKEN_MFA';
34
+ const cognitoSmsPreferred = preferredMfaSetting === 'SMS_MFA';
35
+ if (cognitoAuthenticatorPreferred && authenticatorEnabled) {
36
+ return { authenticatorPreferred: true, smsPreferred: false };
24
37
  }
25
- return requiredMethods.some((method) => MFA_REQUIREMENT_METHOD_CHECKS[method](mfaSettings));
38
+ if (cognitoSmsPreferred && smsEnabled) {
39
+ return { authenticatorPreferred: false, smsPreferred: true };
40
+ }
41
+ if (authenticatorEnabled && smsEnabled) {
42
+ return { authenticatorPreferred: true, smsPreferred: false };
43
+ }
44
+ return {
45
+ authenticatorPreferred: authenticatorEnabled,
46
+ smsPreferred: smsEnabled,
47
+ };
26
48
  }
27
49
  export default class AWSCognitoClient {
28
50
  constructor({ clientId, region, loginDomain, redirectUri, logoutUri, }) {
@@ -144,7 +166,7 @@ export default class AWSCognitoClient {
144
166
  }
145
167
  };
146
168
  }
147
- async responseToAuthChallenge(username, initiateAuthResponse) {
169
+ async responseToAuthChallenge(username, initiateAuthResponse, password) {
148
170
  if (initiateAuthResponse.AuthenticationResult) {
149
171
  this._storeAuthenticationResult(initiateAuthResponse.AuthenticationResult);
150
172
  return {};
@@ -163,7 +185,7 @@ export default class AWSCognitoClient {
163
185
  NEW_PASSWORD: newPassword,
164
186
  },
165
187
  }));
166
- return await this.responseToAuthChallenge(username, resetPasswordResult);
188
+ return await this.responseToAuthChallenge(username, resetPasswordResult, newPassword);
167
189
  },
168
190
  };
169
191
  }
@@ -181,8 +203,9 @@ export default class AWSCognitoClient {
181
203
  SOFTWARE_TOKEN_MFA_CODE: code,
182
204
  },
183
205
  }));
184
- return await this.responseToAuthChallenge(username, resetPasswordResult);
206
+ return await this.responseToAuthChallenge(username, resetPasswordResult, password);
185
207
  },
208
+ resendCodeCallback: undefined,
186
209
  },
187
210
  };
188
211
  }
@@ -190,6 +213,9 @@ export default class AWSCognitoClient {
190
213
  throw new Error('Email OTP is not supported');
191
214
  }
192
215
  case 'SMS_MFA': {
216
+ if (!initiateAuthResponse.Session) {
217
+ throw new Error('An unexpected error occurred while attempting to process your login. Please try again or contact support if the problem persists.');
218
+ }
193
219
  return {
194
220
  mfa: {
195
221
  method: 'sms',
@@ -203,7 +229,18 @@ export default class AWSCognitoClient {
203
229
  SMS_MFA_CODE: code,
204
230
  },
205
231
  }));
206
- return await this.responseToAuthChallenge(username, smsChallengeResult);
232
+ return await this.responseToAuthChallenge(username, smsChallengeResult, password);
233
+ },
234
+ resendCodeCallback: async () => {
235
+ var _a;
236
+ if (!password) {
237
+ throw new Error('Unable to resend the SMS verification code. Please try signing in again.');
238
+ }
239
+ const loginAttemptResponse = await this.loginUsernamePassword(username, password);
240
+ if (((_a = loginAttemptResponse.mfa) === null || _a === void 0 ? void 0 : _a.method) !== 'sms') {
241
+ throw new Error('Unable to resend the SMS verification code. Please try signing in again.');
242
+ }
243
+ return loginAttemptResponse;
207
244
  },
208
245
  },
209
246
  };
@@ -221,7 +258,7 @@ export default class AWSCognitoClient {
221
258
  PASSWORD: password,
222
259
  },
223
260
  }));
224
- return await this.responseToAuthChallenge(username, loginResult);
261
+ return await this.responseToAuthChallenge(username, loginResult, password);
225
262
  }
226
263
  async loginHostedUI(identityProviderName) {
227
264
  const loginDomain = this.loginDomain;
@@ -376,26 +413,28 @@ export default class AWSCognitoClient {
376
413
  const preferredMfaSetting = user.PreferredMfaSetting;
377
414
  const phoneNumber = (_b = (_a = user.UserAttributes) === null || _a === void 0 ? void 0 : _a.find((attribute) => attribute.Name === 'phone_number')) === null || _b === void 0 ? void 0 : _b.Value;
378
415
  const isPhoneNumberVerified = ((_d = (_c = user.UserAttributes) === null || _c === void 0 ? void 0 : _c.find((attribute) => attribute.Name === 'phone_number_verified')) === null || _d === void 0 ? void 0 : _d.Value) === 'true';
416
+ const authenticatorEnabled = mfaList.includes('SOFTWARE_TOKEN_MFA');
417
+ const smsEnabled = mfaList.includes('SMS_MFA');
418
+ const { authenticatorPreferred, smsPreferred } = resolveMfaPreferredFlags({
419
+ authenticatorEnabled,
420
+ smsEnabled,
421
+ preferredMfaSetting,
422
+ });
423
+ const loggedInWithMfaMethod = resolveLoggedInMfaMethod(this._getIdToken());
379
424
  return {
425
+ loggedInWithMfaMethod,
380
426
  authenticator: {
381
- enabled: mfaList.includes('SOFTWARE_TOKEN_MFA'),
382
- preferred: preferredMfaSetting === 'SOFTWARE_TOKEN_MFA',
427
+ enabled: authenticatorEnabled,
428
+ preferred: authenticatorPreferred,
383
429
  },
384
430
  sms: {
385
- enabled: mfaList.includes('SMS_MFA'),
386
- preferred: preferredMfaSetting === 'SMS_MFA',
431
+ enabled: smsEnabled,
432
+ preferred: smsPreferred,
387
433
  phoneNumber,
388
434
  isPhoneNumberVerified,
389
435
  },
390
436
  };
391
437
  }
392
- async checkIsMfaEnabled(mfaRequirement) {
393
- const mfaSettings = await this.getMfaSettings();
394
- return {
395
- mfaSettings,
396
- userMeetsMfaRequirement: checkUserMeetsMfaRequirement(mfaRequirement, mfaSettings),
397
- };
398
- }
399
438
  async updateUserPhoneNumber(phoneNumber) {
400
439
  const accessToken = await this.getAccessToken();
401
440
  if (!accessToken) {
@@ -423,16 +462,6 @@ export default class AWSCognitoClient {
423
462
  UserAttributeNames: ['phone_number'],
424
463
  }));
425
464
  }
426
- async sendPhoneNumberVerificationCode() {
427
- const accessToken = await this.getAccessToken();
428
- if (!accessToken) {
429
- return;
430
- }
431
- return await this.cognitoIdentityProviderClient.send(new GetUserAttributeVerificationCodeCommand({
432
- AccessToken: accessToken,
433
- AttributeName: 'phone_number',
434
- }));
435
- }
436
465
  async verifyUserPhoneNumber(code) {
437
466
  const accessToken = await this.getAccessToken();
438
467
  if (!accessToken) {