private VerificationBean handleError(String error, Exception e) {

    VerificationBean bean = new VerificationBean();
    bean.setVerified(false);

    if (error != null) {
      bean.setError(error);
      log.error(error, e);
    } else {
      bean.setError(e.getMessage());
      log.error(e.getMessage(), e);
    }

    return bean;
  }
  /**
   * This method used to confirm the self registered user account and unlock it.
   *
   * @param username
   * @param code
   * @param captcha
   * @param tenantDomain
   * @return
   * @throws IdentityMgtServiceException
   */
  public VerificationBean confirmUserSelfRegistration(
      String username, String code, CaptchaInfoBean captcha, String tenantDomain)
      throws IdentityMgtServiceException {

    VerificationBean bean = new VerificationBean();

    if (log.isDebugEnabled()) {
      log.debug("User registration verification request received with username :"******" Error while validating captcha for user : "******"Trying to confirm users in unauthorized tenant space";
        log.error(msg);
      }
      if (tenantDomain == null || tenantDomain.isEmpty()) {
        tenantDomain = loggedInTenant;
      }
    }

    UserDTO userDTO = null;
    try {
      userDTO = Utils.processUserId(username + "@" + tenantDomain);

    } catch (IdentityException e) {
      bean =
          handleError(
              VerificationBean.ERROR_CODE_INVALID_USER
                  + " Error verifying user account for user : "******"Error retrieving the user store manager for the tenant : " + tenantDomain, e);
        return bean;
      }

      try {
        bean = processor.verifyConfirmationCode(1, username, code);
        if (bean.isVerified()) {
          UserIdentityManagementUtil.unlockUserAccount(username, userStoreManager);
          bean.setVerified(true);

        } else {
          bean.setVerified(false);
          bean.setKey("");
          log.error("User verification failed against the given confirmation code");
        }
      } catch (IdentityException e) {
        bean = handleError("Error while validating confirmation code for user : " + username, e);
        return bean;
      }
    } finally {
      if (IdentityMgtConfig.getInstance().isSaasEnabled()) {
        PrivilegedCarbonContext.endTenantFlow();
      }
    }
    return bean;
  }
  /**
   * This method is used to register an user in the system. The account will be locked if the
   * Authentication.Policy.Account.Lock.On.Creation is set to true. Else user will be able to login
   * after registration.
   *
   * @param userName
   * @param password
   * @param claims
   * @param profileName
   * @param tenantDomain
   * @return
   * @throws IdentityMgtServiceException
   */
  public VerificationBean registerUser(
      String userName,
      String password,
      UserIdentityClaimDTO[] claims,
      String profileName,
      String tenantDomain)
      throws IdentityMgtServiceException {

    VerificationBean vBean = new VerificationBean();

    org.wso2.carbon.user.core.UserStoreManager userStoreManager = null;
    Permission permission = null;

    if (!IdentityMgtConfig.getInstance().isSaasEnabled()) {
      String loggedInTenant =
          PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
      if (tenantDomain != null && !tenantDomain.isEmpty() && !loggedInTenant.equals(tenantDomain)) {
        String msg = "Trying to create users in unauthorized tenant space";
        log.error(msg);
        throw new IdentityMgtServiceException(msg);
      }
      if (tenantDomain == null || tenantDomain.isEmpty()) {
        tenantDomain = loggedInTenant;
      }
    }

    RealmService realmService = IdentityMgtServiceComponent.getRealmService();
    int tenantId;

    try {

      tenantId = Utils.getTenantId(tenantDomain);
      if (realmService.getTenantUserRealm(tenantId) != null) {
        userStoreManager =
            (org.wso2.carbon.user.core.UserStoreManager)
                realmService.getTenantUserRealm(tenantId).getUserStoreManager();
      }

    } catch (Exception e) {
      vBean =
          handleError(
              VerificationBean.ERROR_CODE_UNEXPECTED
                  + " Error retrieving the user store manager for the tenant",
              e);
      return vBean;
    }

    try {

      if (userStoreManager == null) {
        vBean = new VerificationBean();
        vBean.setVerified(false);
        vBean.setError(
            VerificationBean.ERROR_CODE_UNEXPECTED
                + " Error retrieving the user store manager for the tenant");
        return vBean;
      }

      Map<String, String> claimsMap = new HashMap<String, String>();
      for (UserIdentityClaimDTO userIdentityClaimDTO : claims) {
        claimsMap.put(userIdentityClaimDTO.getClaimUri(), userIdentityClaimDTO.getClaimValue());
      }

      userStoreManager.addUser(userName, password, null, claimsMap, profileName);

      String identityRoleName =
          UserCoreConstants.INTERNAL_DOMAIN
              + CarbonConstants.DOMAIN_SEPARATOR
              + IdentityConstants.IDENTITY_DEFAULT_ROLE;

      if (!userStoreManager.isExistingRole(identityRoleName, false)) {
        permission = new Permission("/permission/admin/login", UserMgtConstants.EXECUTE_ACTION);
        userStoreManager.addRole(
            identityRoleName, new String[] {userName}, new Permission[] {permission}, false);
      } else {
        userStoreManager.updateUserListOfRole(
            identityRoleName, new String[] {}, new String[] {userName});
      }

      IdentityEventListener identityEventListener =
          IdentityUtil.readEventListenerProperty(
              UserOperationEventListener.class.getName(), IdentityMgtEventListener.class.getName());

      boolean isListenerEnable = true;

      if (identityEventListener != null) {
        if (StringUtils.isNotBlank(identityEventListener.getEnable())) {
          isListenerEnable = Boolean.parseBoolean(identityEventListener.getEnable());
        }
      }

      IdentityMgtConfig config = IdentityMgtConfig.getInstance();

      if (isListenerEnable && config.isAuthPolicyAccountLockOnCreation()) {
        UserDTO userDTO = new UserDTO(userName);
        userDTO.setTenantId(tenantId);

        UserRecoveryDTO dto = new UserRecoveryDTO(userDTO);
        dto.setNotification(IdentityMgtConstants.Notification.ACCOUNT_CONFORM);
        dto.setNotificationType("EMAIL");

        RecoveryProcessor processor = IdentityMgtServiceComponent.getRecoveryProcessor();
        vBean = processor.updateConfirmationCode(1, userName, tenantId);

        dto.setConfirmationCode(vBean.getKey());
        NotificationDataDTO notificationDto = processor.notifyWithEmail(dto);
        vBean.setVerified(notificationDto.isNotificationSent());

        //				Send email data only if not internally managed.
        if (!(IdentityMgtConfig.getInstance().isNotificationInternallyManaged())) {
          vBean.setNotificationData(notificationDto);
        }

      } else {
        vBean.setVerified(true);
      }
    } catch (UserStoreException | IdentityException e) {
      UserIdentityManagementUtil.getCustomErrorMessages(e, userName);
      // Rollback if user exists
      try {
        if (userStoreManager.isExistingUser(userName)) {
          userStoreManager.deleteUser(userName);
        }
      } catch (org.wso2.carbon.user.core.UserStoreException e1) {
        UserIdentityManagementUtil.getCustomErrorMessages(e1, userName);
      }

      return vBean;
    }

    return vBean;
  }
  /**
   * Verifies the user against the provided claims and captcha information.
   *
   * @param claims
   * @param captcha
   * @param tenantDomain
   * @return
   * @throws IdentityMgtServiceException
   */
  public VerificationBean verifyAccount(
      UserIdentityClaimDTO[] claims, CaptchaInfoBean captcha, String tenantDomain)
      throws IdentityMgtServiceException {

    VerificationBean vBean = new VerificationBean();

    if (IdentityMgtConfig.getInstance().isCaptchaVerificationInternallyManaged()) {
      try {
        CaptchaUtil.processCaptchaInfoBean(captcha);
      } catch (Exception e) {
        vBean =
            handleError(
                VerificationBean.ERROR_CODE_INVALID_CAPTCHA + " Error processing captcha", e);
        return vBean;
      }
    }

    if (!IdentityMgtConfig.getInstance().isSaasEnabled()) {
      String loggedInTenant =
          PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
      if (tenantDomain != null && !tenantDomain.isEmpty() && !loggedInTenant.equals(tenantDomain)) {
        String msg = "Trying to verify account unauthorized tenant space";
        log.error(msg);
        throw new IdentityMgtServiceException(msg);
      }
      if (tenantDomain == null || tenantDomain.isEmpty()) {
        tenantDomain = loggedInTenant;
      }
    }

    try {
      int tenantId = Utils.getTenantId(tenantDomain);
      String userName = UserIdentityManagementUtil.getUsernameByClaims(claims, tenantId);

      if (userName != null) {
        UserDTO userDTO = new UserDTO(userName);
        userDTO.setTenantId(tenantId);

        UserRecoveryDTO dto = new UserRecoveryDTO(userDTO);
        dto.setNotification(IdentityMgtConstants.Notification.ACCOUNT_ID_RECOVERY);
        dto.setNotificationType("EMAIL");

        RecoveryProcessor processor = IdentityMgtServiceComponent.getRecoveryProcessor();
        NotificationDataDTO notificationDto = processor.notifyWithEmail(dto);

        vBean.setVerified(notificationDto.isNotificationSent());

        //				Send email data only if not internally managed.
        if (!(IdentityMgtConfig.getInstance().isNotificationInternallyManaged())) {
          vBean.setNotificationData(notificationDto);
        }

      } else {
        vBean.setError("User not found");
        vBean.setVerified(false);
      }
    } catch (Exception e) {
      vBean =
          handleError(
              VerificationBean.ERROR_CODE_INVALID_USER + " Error verifying user account", e);
      return vBean;
    }

    return vBean;
  }
  /**
   * This method is to verify the user supplied answer for the challenge question.
   *
   * @param userName
   * @param confirmation
   * @param questionId
   * @param answer
   * @return status and key details about the operation status.
   * @throws IdentityMgtServiceException
   */
  public VerificationBean verifyUserChallengeAnswer(
      String userName, String confirmation, String questionId, String answer)
      throws IdentityMgtServiceException {

    VerificationBean bean = new VerificationBean();
    bean.setVerified(false);

    if (log.isDebugEnabled()) {
      log.debug("User challenge answer request received with username :"******"No challenge question id provided for verification";
      bean.setError(error);
      if (log.isDebugEnabled()) {
        log.debug(error);
      }

      return bean;
    }

    UserDTO userDTO = null;
    try {
      userDTO = Utils.processUserId(userName);
    } catch (IdentityException e) {
      bean =
          handleError(
              VerificationBean.ERROR_CODE_INVALID_USER + " Error verifying user: "******" Error verifying confirmation code for user : "******"");
        bean.setUserId(userName);
        if (log.isDebugEnabled()) {
          log.debug("User answer verification successful for user: "******"Challenge answer verification failed for user : "******""); // clear the key to avoid returning to caller.
        log.error(bean.getError());
      }
    } finally {
      if (IdentityMgtConfig.getInstance().isSaasEnabled()) {
        PrivilegedCarbonContext.endTenantFlow();
      }
    }
    return bean;
  }
  /**
   * To get the challenge question for the user.
   *
   * @param userName
   * @param confirmation
   * @param questionId - Question id returned from the getUserChanllegneQuestionIds method.
   * @return Populated question bean with the question details and the key.
   * @throws IdentityMgtServiceException
   */
  public UserChallengesDTO getUserChallengeQuestion(
      String userName, String confirmation, String questionId) throws IdentityMgtServiceException {

    UserDTO userDTO = null;
    UserChallengesDTO userChallengesDTO = new UserChallengesDTO();

    if (log.isDebugEnabled()) {
      log.debug("User challenge question request received with username :"******"Error validating user : "******"Invalid confirmation code for user : "******"User challenge question retrieved successfully");
        }
      } else {
        if (log.isDebugEnabled()) {
          log.debug("Verification failed for user. Error : " + bean.getError());
        }
        userChallengesDTO.setError(
            VerificationBean.ERROR_CODE_INVALID_USER + " " + bean.getError());
      }
    } finally {
      if (IdentityMgtConfig.getInstance().isSaasEnabled()) {
        PrivilegedCarbonContext.endTenantFlow();
      }
    }

    return userChallengesDTO;
  }
  public ChallengeQuestionIdsDTO getUserChallengeQuestionIds(String username, String confirmation)
      throws IdentityMgtServiceException {

    UserDTO userDTO = null;
    ChallengeQuestionIdsDTO idsDTO = new ChallengeQuestionIdsDTO();

    if (log.isDebugEnabled()) {
      log.debug("User challenge questions id request received with username: "******"Error while getting challenge question ids for user : "******"Error when validating code", e1);
        return idsDTO;
      }
      if (bean.isVerified()) {
        try {
          idsDTO =
              processor
                  .getQuestionProcessor()
                  .getUserChallengeQuestionIds(userDTO.getUserId(), userDTO.getTenantId());
          idsDTO.setKey(bean.getKey());
          if (log.isDebugEnabled()) {
            log.debug("User challenge question response successful for user: "******"Error when getting user challenge questions for user : "******"Verification failed for user. Error : " + bean.getError();
        log.error(msg);
        idsDTO.setError(VerificationBean.ERROR_CODE_UNEXPECTED + " " + msg);
        idsDTO.setKey("");
      }
    } finally {
      if (IdentityMgtConfig.getInstance().isSaasEnabled()) {
        PrivilegedCarbonContext.endTenantFlow();
      }
    }

    return idsDTO;
  }
  /**
   * This method is used to update the password in the system for password recovery process. Before
   * calling this method caller needs to call verifyConfirmationCode and get the newly generated
   * confirmation code.
   *
   * @param username - username
   * @param confirmationCode - newly generated confirmation code
   * @param newPassword - new password
   * @return - VerificationBean with operation status true or false.
   * @throws IdentityMgtServiceException
   */
  public VerificationBean updatePassword(
      String username, String confirmationCode, String newPassword)
      throws IdentityMgtServiceException {

    RecoveryProcessor recoveryProcessor = IdentityMgtServiceComponent.getRecoveryProcessor();
    VerificationBean bean = null;

    if (log.isDebugEnabled()) {
      log.debug("User update password request received with username: "******"No Tenant id for tenant domain " + userDTO.getTenantDomain(), e);
      }

      if (recoveryProcessor
          .verifyConfirmationCode(3, userDTO.getUserId(), confirmationCode)
          .isVerified()) {
        Utils.updatePassword(userDTO.getUserId(), tenantId, newPassword);
        log.info(
            "Credential is updated for user : "******" and tenant domain : "
                + userDTO.getTenantDomain());
        IdentityMgtConfig.getInstance()
            .getRecoveryDataStore()
            .invalidate(userDTO.getUserId(), tenantId);
        bean = new VerificationBean(true);
      } else {
        String msg =
            "Invalid user tried to update credential with user Id : "
                + userDTO.getUserId()
                + " and tenant domain : "
                + userDTO.getTenantDomain();
        bean = new VerificationBean(VerificationBean.ERROR_CODE_INVALID_USER + " " + msg);
        bean.setVerified(false);
        log.error(msg);
      }

    } catch (Exception e) {
      bean =
          handleError(
              VerificationBean.ERROR_CODE_UNEXPECTED
                  + " Error while updating credential for user: "
                  + username,
              e);
      return bean;
    } finally {
      if (IdentityMgtConfig.getInstance().isSaasEnabled()) {
        PrivilegedCarbonContext.endTenantFlow();
      }
    }
    return bean;
  }
  /**
   * This method is used to verify the confirmation code sent to user is correct and validates.
   * Before calling this method it needs to supply a Captcha and should call getCaptcha().
   *
   * @param username - username of whom the password needs to be recovered.
   * @param code - confirmation code sent to user by notification.
   * @param captcha - generated captcha with answer for this communication.
   * @return - VerificationBean with new code to be used in updatePassword().
   * @throws IdentityMgtServiceException
   */
  public VerificationBean verifyConfirmationCode(
      String username, String code, CaptchaInfoBean captcha) throws IdentityMgtServiceException {

    UserDTO userDTO;
    VerificationBean bean = new VerificationBean();

    if (log.isDebugEnabled()) {
      log.debug("User confirmation code verification request received with username :"******" Error while validating captcha for user : "******" invalid user : "******"User confirmation code verification successful for user: "******"");
        log.error(bean.getError());
      }
    } catch (IdentityException e) {
      bean =
          handleError(
              VerificationBean.ERROR_CODE_INVALID_CODE
                  + " Error verifying confirmation code for user : "
                  + username,
              e);
      return bean;
    } finally {
      if (IdentityMgtConfig.getInstance().isSaasEnabled()) {
        PrivilegedCarbonContext.endTenantFlow();
      }
    }

    return bean;
  }