@aws-amplify/auth 6.5.6-unstable.caf00e2.0 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/cjs/common/AuthErrorStrings.js +2 -2
  2. package/dist/cjs/common/AuthErrorStrings.js.map +1 -1
  3. package/dist/cjs/providers/cognito/apis/confirmSignIn.js +2 -2
  4. package/dist/cjs/providers/cognito/apis/confirmSignIn.js.map +1 -1
  5. package/dist/cjs/providers/cognito/apis/updateMFAPreference.js +2 -1
  6. package/dist/cjs/providers/cognito/apis/updateMFAPreference.js.map +1 -1
  7. package/dist/cjs/providers/cognito/utils/signInHelpers.js +189 -130
  8. package/dist/cjs/providers/cognito/utils/signInHelpers.js.map +1 -1
  9. package/dist/esm/common/AuthErrorStrings.mjs +2 -2
  10. package/dist/esm/common/AuthErrorStrings.mjs.map +1 -1
  11. package/dist/esm/foundation/factories/serviceClients/cognitoIdentityProvider/types/sdk.d.ts +24 -3
  12. package/dist/esm/providers/cognito/apis/confirmSignIn.mjs +2 -2
  13. package/dist/esm/providers/cognito/apis/confirmSignIn.mjs.map +1 -1
  14. package/dist/esm/providers/cognito/apis/updateMFAPreference.mjs +2 -1
  15. package/dist/esm/providers/cognito/apis/updateMFAPreference.mjs.map +1 -1
  16. package/dist/esm/providers/cognito/types/inputs.d.ts +1 -0
  17. package/dist/esm/providers/cognito/utils/signInHelpers.d.ts +4 -3
  18. package/dist/esm/providers/cognito/utils/signInHelpers.mjs +187 -127
  19. package/dist/esm/providers/cognito/utils/signInHelpers.mjs.map +1 -1
  20. package/dist/esm/types/models.d.ts +44 -2
  21. package/package.json +104 -104
  22. package/src/common/AuthErrorStrings.ts +4 -2
  23. package/src/foundation/factories/serviceClients/cognitoIdentityProvider/types/sdk.ts +23 -1
  24. package/src/providers/cognito/apis/confirmSignIn.ts +2 -2
  25. package/src/providers/cognito/apis/updateMFAPreference.ts +2 -1
  26. package/src/providers/cognito/types/inputs.ts +1 -0
  27. package/src/providers/cognito/utils/signInHelpers.ts +246 -166
  28. package/src/types/models.ts +48 -1
@@ -76,43 +76,96 @@ async function handleCustomChallenge({ challengeResponse, clientMetadata, sessio
76
76
  }
77
77
  async function handleMFASetupChallenge({ challengeResponse, username, clientMetadata, session, deviceName, config, }) {
78
78
  const { userPoolId, userPoolClientId, userPoolEndpoint } = config;
79
+ if (challengeResponse === 'EMAIL') {
80
+ return {
81
+ ChallengeName: 'MFA_SETUP',
82
+ Session: session,
83
+ ChallengeParameters: {
84
+ MFAS_CAN_SETUP: '["EMAIL_OTP"]',
85
+ },
86
+ $metadata: {},
87
+ };
88
+ }
89
+ if (challengeResponse === 'TOTP') {
90
+ return {
91
+ ChallengeName: 'MFA_SETUP',
92
+ Session: session,
93
+ ChallengeParameters: {
94
+ MFAS_CAN_SETUP: '["SOFTWARE_TOKEN_MFA"]',
95
+ },
96
+ $metadata: {},
97
+ };
98
+ }
79
99
  const challengeResponses = {
80
100
  USERNAME: username,
81
101
  };
82
- const verifySoftwareToken = createVerifySoftwareTokenClient({
83
- endpointResolver: createCognitoUserPoolEndpointResolver({
84
- endpointOverride: userPoolEndpoint,
85
- }),
86
- });
87
- const { Session } = await verifySoftwareToken({
88
- region: getRegionFromUserPoolId(userPoolId),
89
- userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
90
- }, {
91
- UserCode: challengeResponse,
92
- Session: session,
93
- FriendlyDeviceName: deviceName,
94
- });
95
- signInStore.dispatch({
96
- type: 'SET_SIGN_IN_SESSION',
97
- value: Session,
98
- });
99
- const jsonReq = {
100
- ChallengeName: 'MFA_SETUP',
101
- ChallengeResponses: challengeResponses,
102
- Session,
103
- ClientMetadata: clientMetadata,
104
- ClientId: userPoolClientId,
105
- };
106
- const respondToAuthChallenge = createRespondToAuthChallengeClient({
107
- endpointResolver: createCognitoUserPoolEndpointResolver({
108
- endpointOverride: userPoolEndpoint,
109
- }),
102
+ const isTOTPCode = /^\d+$/.test(challengeResponse);
103
+ if (isTOTPCode) {
104
+ const verifySoftwareToken = createVerifySoftwareTokenClient({
105
+ endpointResolver: createCognitoUserPoolEndpointResolver({
106
+ endpointOverride: userPoolEndpoint,
107
+ }),
108
+ });
109
+ const { Session } = await verifySoftwareToken({
110
+ region: getRegionFromUserPoolId(userPoolId),
111
+ userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
112
+ }, {
113
+ UserCode: challengeResponse,
114
+ Session: session,
115
+ FriendlyDeviceName: deviceName,
116
+ });
117
+ signInStore.dispatch({
118
+ type: 'SET_SIGN_IN_SESSION',
119
+ value: Session,
120
+ });
121
+ const jsonReq = {
122
+ ChallengeName: 'MFA_SETUP',
123
+ ChallengeResponses: challengeResponses,
124
+ Session,
125
+ ClientMetadata: clientMetadata,
126
+ ClientId: userPoolClientId,
127
+ };
128
+ const respondToAuthChallenge = createRespondToAuthChallengeClient({
129
+ endpointResolver: createCognitoUserPoolEndpointResolver({
130
+ endpointOverride: userPoolEndpoint,
131
+ }),
132
+ });
133
+ return respondToAuthChallenge({
134
+ region: getRegionFromUserPoolId(userPoolId),
135
+ userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
136
+ }, jsonReq);
137
+ }
138
+ const isEmail = challengeResponse.includes('@');
139
+ if (isEmail) {
140
+ challengeResponses.EMAIL = challengeResponse;
141
+ const jsonReq = {
142
+ ChallengeName: 'MFA_SETUP',
143
+ ChallengeResponses: challengeResponses,
144
+ Session: session,
145
+ ClientMetadata: clientMetadata,
146
+ ClientId: userPoolClientId,
147
+ };
148
+ const respondToAuthChallenge = createRespondToAuthChallengeClient({
149
+ endpointResolver: createCognitoUserPoolEndpointResolver({
150
+ endpointOverride: userPoolEndpoint,
151
+ }),
152
+ });
153
+ return respondToAuthChallenge({
154
+ region: getRegionFromUserPoolId(userPoolId),
155
+ userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
156
+ }, jsonReq);
157
+ }
158
+ throw new AuthError({
159
+ name: AuthErrorCodes.SignInException,
160
+ message: `Cannot proceed with MFA setup using challengeResponse: ${challengeResponse}`,
161
+ recoverySuggestion: 'Try passing "EMAIL", "TOTP", a valid email, or OTP code as the challengeResponse.',
110
162
  });
111
- return respondToAuthChallenge({ region: getRegionFromUserPoolId(userPoolId) }, jsonReq);
112
163
  }
113
164
  async function handleSelectMFATypeChallenge({ challengeResponse, username, clientMetadata, session, config, }) {
114
165
  const { userPoolId, userPoolClientId, userPoolEndpoint } = config;
115
- assertValidationError(challengeResponse === 'TOTP' || challengeResponse === 'SMS', AuthValidationErrorCode.IncorrectMFAMethod);
166
+ assertValidationError(challengeResponse === 'TOTP' ||
167
+ challengeResponse === 'SMS' ||
168
+ challengeResponse === 'EMAIL', AuthValidationErrorCode.IncorrectMFAMethod);
116
169
  const challengeResponses = {
117
170
  USERNAME: username,
118
171
  ANSWER: mapMfaType(challengeResponse),
@@ -140,64 +193,6 @@ async function handleSelectMFATypeChallenge({ challengeResponse, username, clien
140
193
  userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
141
194
  }, jsonReq);
142
195
  }
143
- async function handleSMSMFAChallenge({ challengeResponse, clientMetadata, session, username, config, }) {
144
- const { userPoolId, userPoolClientId, userPoolEndpoint } = config;
145
- const challengeResponses = {
146
- USERNAME: username,
147
- SMS_MFA_CODE: challengeResponse,
148
- };
149
- const UserContextData = getUserContextData({
150
- username,
151
- userPoolId,
152
- userPoolClientId,
153
- });
154
- const jsonReq = {
155
- ChallengeName: 'SMS_MFA',
156
- ChallengeResponses: challengeResponses,
157
- Session: session,
158
- ClientMetadata: clientMetadata,
159
- ClientId: userPoolClientId,
160
- UserContextData,
161
- };
162
- const respondToAuthChallenge = createRespondToAuthChallengeClient({
163
- endpointResolver: createCognitoUserPoolEndpointResolver({
164
- endpointOverride: userPoolEndpoint,
165
- }),
166
- });
167
- return respondToAuthChallenge({
168
- region: getRegionFromUserPoolId(userPoolId),
169
- userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
170
- }, jsonReq);
171
- }
172
- async function handleSoftwareTokenMFAChallenge({ challengeResponse, clientMetadata, session, username, config, }) {
173
- const { userPoolId, userPoolClientId, userPoolEndpoint } = config;
174
- const challengeResponses = {
175
- USERNAME: username,
176
- SOFTWARE_TOKEN_MFA_CODE: challengeResponse,
177
- };
178
- const UserContextData = getUserContextData({
179
- username,
180
- userPoolId,
181
- userPoolClientId,
182
- });
183
- const jsonReq = {
184
- ChallengeName: 'SOFTWARE_TOKEN_MFA',
185
- ChallengeResponses: challengeResponses,
186
- Session: session,
187
- ClientMetadata: clientMetadata,
188
- ClientId: userPoolClientId,
189
- UserContextData,
190
- };
191
- const respondToAuthChallenge = createRespondToAuthChallengeClient({
192
- endpointResolver: createCognitoUserPoolEndpointResolver({
193
- endpointOverride: userPoolEndpoint,
194
- }),
195
- });
196
- return respondToAuthChallenge({
197
- region: getRegionFromUserPoolId(userPoolId),
198
- userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
199
- }, jsonReq);
200
- }
201
196
  async function handleCompleteNewPasswordChallenge({ challengeResponse, clientMetadata, session, username, requiredAttributes, config, }) {
202
197
  const { userPoolId, userPoolClientId, userPoolEndpoint } = config;
203
198
  const challengeResponses = {
@@ -551,30 +546,52 @@ async function getSignInResult(params) {
551
546
  };
552
547
  case 'MFA_SETUP': {
553
548
  const { signInSession, username } = signInStore.getState();
554
- if (!isMFATypeEnabled(challengeParameters, 'TOTP'))
555
- throw new AuthError({
556
- name: AuthErrorCodes.SignInException,
557
- message: `Cannot initiate MFA setup from available types: ${getMFATypes(parseMFATypes(challengeParameters.MFAS_CAN_SETUP))}`,
549
+ const mfaSetupTypes = getMFATypes(parseMFATypes(challengeParameters.MFAS_CAN_SETUP)) || [];
550
+ const allowedMfaSetupTypes = getAllowedMfaSetupTypes(mfaSetupTypes);
551
+ const isTotpMfaSetupAvailable = allowedMfaSetupTypes.includes('TOTP');
552
+ const isEmailMfaSetupAvailable = allowedMfaSetupTypes.includes('EMAIL');
553
+ if (isTotpMfaSetupAvailable && isEmailMfaSetupAvailable) {
554
+ return {
555
+ isSignedIn: false,
556
+ nextStep: {
557
+ signInStep: 'CONTINUE_SIGN_IN_WITH_MFA_SETUP_SELECTION',
558
+ allowedMFATypes: allowedMfaSetupTypes,
559
+ },
560
+ };
561
+ }
562
+ if (isEmailMfaSetupAvailable) {
563
+ return {
564
+ isSignedIn: false,
565
+ nextStep: {
566
+ signInStep: 'CONTINUE_SIGN_IN_WITH_EMAIL_SETUP',
567
+ },
568
+ };
569
+ }
570
+ if (isTotpMfaSetupAvailable) {
571
+ const associateSoftwareToken = createAssociateSoftwareTokenClient({
572
+ endpointResolver: createCognitoUserPoolEndpointResolver({
573
+ endpointOverride: authConfig.userPoolEndpoint,
574
+ }),
558
575
  });
559
- const associateSoftwareToken = createAssociateSoftwareTokenClient({
560
- endpointResolver: createCognitoUserPoolEndpointResolver({
561
- endpointOverride: authConfig.userPoolEndpoint,
562
- }),
563
- });
564
- const { Session, SecretCode: secretCode } = await associateSoftwareToken({ region: getRegionFromUserPoolId(authConfig.userPoolId) }, {
565
- Session: signInSession,
566
- });
567
- signInStore.dispatch({
568
- type: 'SET_SIGN_IN_SESSION',
569
- value: Session,
576
+ const { Session, SecretCode: secretCode } = await associateSoftwareToken({ region: getRegionFromUserPoolId(authConfig.userPoolId) }, {
577
+ Session: signInSession,
578
+ });
579
+ signInStore.dispatch({
580
+ type: 'SET_SIGN_IN_SESSION',
581
+ value: Session,
582
+ });
583
+ return {
584
+ isSignedIn: false,
585
+ nextStep: {
586
+ signInStep: 'CONTINUE_SIGN_IN_WITH_TOTP_SETUP',
587
+ totpSetupDetails: getTOTPSetupDetails(secretCode, username),
588
+ },
589
+ };
590
+ }
591
+ throw new AuthError({
592
+ name: AuthErrorCodes.SignInException,
593
+ message: `Cannot initiate MFA setup from available types: ${mfaSetupTypes}`,
570
594
  });
571
- return {
572
- isSignedIn: false,
573
- nextStep: {
574
- signInStep: 'CONTINUE_SIGN_IN_WITH_TOTP_SETUP',
575
- totpSetupDetails: getTOTPSetupDetails(secretCode, username),
576
- },
577
- };
578
595
  }
579
596
  case 'NEW_PASSWORD_REQUIRED':
580
597
  return {
@@ -610,6 +627,17 @@ async function getSignInResult(params) {
610
627
  signInStep: 'CONFIRM_SIGN_IN_WITH_TOTP_CODE',
611
628
  },
612
629
  };
630
+ case 'EMAIL_OTP':
631
+ return {
632
+ isSignedIn: false,
633
+ nextStep: {
634
+ signInStep: 'CONFIRM_SIGN_IN_WITH_EMAIL_CODE',
635
+ codeDeliveryDetails: {
636
+ deliveryMedium: challengeParameters.CODE_DELIVERY_DELIVERY_MEDIUM,
637
+ destination: challengeParameters.CODE_DELIVERY_DESTINATION,
638
+ },
639
+ },
640
+ };
613
641
  }
614
642
  // TODO: remove this error message for production apps
615
643
  throw new AuthError({
@@ -661,14 +689,6 @@ async function handleChallengeName(username, challengeName, session, challengeRe
661
689
  const userAttributes = options?.userAttributes;
662
690
  const deviceName = options?.friendlyDeviceName;
663
691
  switch (challengeName) {
664
- case 'SMS_MFA':
665
- return handleSMSMFAChallenge({
666
- challengeResponse,
667
- clientMetadata,
668
- session,
669
- username,
670
- config,
671
- });
672
692
  case 'SELECT_MFA_TYPE':
673
693
  return handleSelectMFATypeChallenge({
674
694
  challengeResponse,
@@ -706,8 +726,11 @@ async function handleChallengeName(username, challengeName, session, challengeRe
706
726
  tokenOrchestrator,
707
727
  },
708
728
  ], username, tokenOrchestrator);
729
+ case 'SMS_MFA':
709
730
  case 'SOFTWARE_TOKEN_MFA':
710
- return handleSoftwareTokenMFAChallenge({
731
+ case 'EMAIL_OTP':
732
+ return handleMFAChallenge({
733
+ challengeName,
711
734
  challengeResponse,
712
735
  clientMetadata,
713
736
  session,
@@ -718,7 +741,7 @@ async function handleChallengeName(username, challengeName, session, challengeRe
718
741
  // TODO: remove this error message for production apps
719
742
  throw new AuthError({
720
743
  name: AuthErrorCodes.SignInException,
721
- message: `An error occurred during the sign in process.
744
+ message: `An error occurred during the sign in process.
722
745
  ${challengeName} challengeName returned by the underlying service was not addressed.`,
723
746
  });
724
747
  }
@@ -726,6 +749,8 @@ function mapMfaType(mfa) {
726
749
  let mfaType = 'SMS_MFA';
727
750
  if (mfa === 'TOTP')
728
751
  mfaType = 'SOFTWARE_TOKEN_MFA';
752
+ if (mfa === 'EMAIL')
753
+ mfaType = 'EMAIL_OTP';
729
754
  return mfaType;
730
755
  }
731
756
  function getMFAType(type) {
@@ -733,6 +758,8 @@ function getMFAType(type) {
733
758
  return 'SMS';
734
759
  if (type === 'SOFTWARE_TOKEN_MFA')
735
760
  return 'TOTP';
761
+ if (type === 'EMAIL_OTP')
762
+ return 'EMAIL';
736
763
  // TODO: log warning for unknown MFA type
737
764
  }
738
765
  function getMFATypes(types) {
@@ -745,12 +772,8 @@ function parseMFATypes(mfa) {
745
772
  return [];
746
773
  return JSON.parse(mfa);
747
774
  }
748
- function isMFATypeEnabled(challengeParams, mfaType) {
749
- const { MFAS_CAN_SETUP } = challengeParams;
750
- const mfaTypes = getMFATypes(parseMFATypes(MFAS_CAN_SETUP));
751
- if (!mfaTypes)
752
- return false;
753
- return mfaTypes.includes(mfaType);
775
+ function getAllowedMfaSetupTypes(availableMfaSetupTypes) {
776
+ return availableMfaSetupTypes.filter(authMfaType => authMfaType === 'EMAIL' || authMfaType === 'TOTP');
754
777
  }
755
778
  async function assertUserNotAuthenticated() {
756
779
  let authUser;
@@ -844,6 +867,43 @@ function getActiveSignInUsername(username) {
844
867
  const state = signInStore.getState();
845
868
  return state.username ?? username;
846
869
  }
870
+ async function handleMFAChallenge({ challengeName, challengeResponse, clientMetadata, session, username, config, }) {
871
+ const { userPoolId, userPoolClientId, userPoolEndpoint } = config;
872
+ const challengeResponses = {
873
+ USERNAME: username,
874
+ };
875
+ if (challengeName === 'EMAIL_OTP') {
876
+ challengeResponses.EMAIL_OTP_CODE = challengeResponse;
877
+ }
878
+ if (challengeName === 'SMS_MFA') {
879
+ challengeResponses.SMS_MFA_CODE = challengeResponse;
880
+ }
881
+ if (challengeName === 'SOFTWARE_TOKEN_MFA') {
882
+ challengeResponses.SOFTWARE_TOKEN_MFA_CODE = challengeResponse;
883
+ }
884
+ const userContextData = getUserContextData({
885
+ username,
886
+ userPoolId,
887
+ userPoolClientId,
888
+ });
889
+ const jsonReq = {
890
+ ChallengeName: challengeName,
891
+ ChallengeResponses: challengeResponses,
892
+ Session: session,
893
+ ClientMetadata: clientMetadata,
894
+ ClientId: userPoolClientId,
895
+ UserContextData: userContextData,
896
+ };
897
+ const respondToAuthChallenge = createRespondToAuthChallengeClient({
898
+ endpointResolver: createCognitoUserPoolEndpointResolver({
899
+ endpointOverride: userPoolEndpoint,
900
+ }),
901
+ });
902
+ return respondToAuthChallenge({
903
+ region: getRegionFromUserPoolId(userPoolId),
904
+ userAgentValue: getAuthUserAgentValue(AuthAction.ConfirmSignIn),
905
+ }, jsonReq);
906
+ }
847
907
 
848
- export { assertUserNotAuthenticated, createAttributes, getActiveSignInUsername, getMFAType, getMFATypes, getNewDeviceMetadata, getSignInResult, getSignInResultFromError, getTOTPSetupDetails, handleChallengeName, handleCompleteNewPasswordChallenge, handleCustomAuthFlowWithoutSRP, handleCustomChallenge, handleCustomSRPAuthFlow, handleMFASetupChallenge, handlePasswordVerifierChallenge, handleSMSMFAChallenge, handleSelectMFATypeChallenge, handleSoftwareTokenMFAChallenge, handleUserPasswordAuthFlow, handleUserSRPAuthFlow, isMFATypeEnabled, mapMfaType, parseAttributes, parseMFATypes, retryOnResourceNotFoundException, setActiveSignInUsername };
908
+ export { assertUserNotAuthenticated, createAttributes, getActiveSignInUsername, getAllowedMfaSetupTypes, getMFAType, getMFATypes, getNewDeviceMetadata, getSignInResult, getSignInResultFromError, getTOTPSetupDetails, handleChallengeName, handleCompleteNewPasswordChallenge, handleCustomAuthFlowWithoutSRP, handleCustomChallenge, handleCustomSRPAuthFlow, handleMFAChallenge, handleMFASetupChallenge, handlePasswordVerifierChallenge, handleSelectMFATypeChallenge, handleUserPasswordAuthFlow, handleUserSRPAuthFlow, mapMfaType, parseAttributes, parseMFATypes, retryOnResourceNotFoundException, setActiveSignInUsername };
849
909
  //# sourceMappingURL=signInHelpers.mjs.map