sendMFACode method

Future<CognitoUserSession?> sendMFACode(
  1. String confirmationCode, [
  2. String mfaType = 'SMS_MFA'
])

This is used by the user once he has an MFA code

Implementation

Future<CognitoUserSession?> sendMFACode(String confirmationCode,
    [String mfaType = 'SMS_MFA']) async {
  final challengeResponses = {
    'USERNAME': username,
    'SMS_MFA_CODE': confirmationCode,
  };
  if (mfaType == 'SOFTWARE_TOKEN_MFA') {
    challengeResponses['SOFTWARE_TOKEN_MFA_CODE'] = confirmationCode;
  }
  if (mfaType == 'EMAIL_OTP') {
    challengeResponses['EMAIL_OTP_CODE'] = confirmationCode;
  }
  if (_clientSecretHash != null) {
    challengeResponses['SECRET_HASH'] = _clientSecretHash;
  }

  await getCachedDeviceKeyAndPassword();
  if (_deviceKey != null) {
    challengeResponses['DEVICE_KEY'] = _deviceKey;
  }

  final paramsReq = {
    'ChallengeName': mfaType,
    'ChallengeResponses': challengeResponses,
    'ClientId': pool.getClientId(),
    'Session': _session,
  };
  if (getUserContextData() != null) {
    paramsReq['UserContextData'] = getUserContextData();
  }

  dynamic dataAuthenticate;
  try {
    dataAuthenticate = await client!.request('RespondToAuthChallenge',
        await _analyticsMetadataParamsDecorator.call(paramsReq));
  } on CognitoClientException catch (e) {
    // When trying to use MFA with a non verified phone_number this
    // missleading error will be received because Cognito expects in this case
    // the GUID style user name instead of the normal user name used in every
    // other request.
    if (e.code == "UserNotFoundException") {
      throw CognitoUserPhoneNumberVerificationNecessaryException();
    } else {
      rethrow;
    }
  }

  final String? challengeName = dataAuthenticate['ChallengeName'];

  if (challengeName == 'DEVICE_SRP_AUTH') {
    return getDeviceResponse();
  }

  _signInUserSession =
      getCognitoUserSession(dataAuthenticate['AuthenticationResult']);
  await cacheTokens();

  if (dataAuthenticate['AuthenticationResult']['NewDeviceMetadata'] == null) {
    return _signInUserSession;
  }

  final authenticationHelper =
      AuthenticationHelper(pool.getUserPoolId().split('_')[1]);
  authenticationHelper.generateHashDevice(
      dataAuthenticate['AuthenticationResult']['NewDeviceMetadata']
          ['DeviceGroupKey'],
      dataAuthenticate['AuthenticationResult']['NewDeviceMetadata']
          ['DeviceKey']);

  final deviceSecretVerifierConfig = {
    'Salt': base64.encode(hex.decode(authenticationHelper.getSaltDevices()!)),
    'PasswordVerifier':
        base64.encode(hex.decode(authenticationHelper.getVerifierDevices()!)),
  };

  verifierDevices = deviceSecretVerifierConfig['PasswordVerifier'];
  _deviceGroupKey = dataAuthenticate['AuthenticationResult']
      ['NewDeviceMetadata']['DeviceGroupKey'];
  _randomPassword = authenticationHelper.getRandomPassword();

  final confirmDeviceParamsReq = {
    'DeviceKey': dataAuthenticate['AuthenticationResult']['NewDeviceMetadata']
        ['DeviceKey'],
    'AccessToken': _signInUserSession!.getAccessToken().getJwtToken(),
    'DeviceSecretVerifierConfig': deviceSecretVerifierConfig,
    'DeviceName': deviceName,
  };
  final dataConfirm =
      await client!.request('ConfirmDevice', confirmDeviceParamsReq);
  _deviceKey = dataAuthenticate['AuthenticationResult']['NewDeviceMetadata']
      ['DeviceKey'];
  await cacheDeviceKeyAndPassword();
  if (dataConfirm['UserConfirmationNecessary'] == true) {
    throw CognitoUserDeviceConfirmationNecessaryException(
        signInUserSession: _signInUserSession);
  }

  return _signInUserSession;
}