private void handleEnterCodeRequest(
      final PwmRequest pwmRequest, final UpdateProfileBean updateProfileBean)
      throws PwmUnrecoverableException, IOException, ServletException, ChaiUnavailableException {
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final PwmSession pwmSession = pwmRequest.getPwmSession();
    final String userEnteredCode = pwmRequest.readParameterAsString(PwmConstants.PARAM_TOKEN);

    boolean tokenPassed = false;
    ErrorInformation errorInformation = null;
    try {
      final TokenPayload tokenPayload =
          pwmApplication
              .getTokenService()
              .processUserEnteredCode(
                  pwmSession, pwmRequest.getUserInfoIfLoggedIn(), null, userEnteredCode);
      if (tokenPayload != null) {
        if (TokenType.UPDATE_EMAIL.matchesName(tokenPayload.getName())) {
          LOGGER.debug(pwmRequest, "email token passed");

          updateProfileBean
              .getTokenVerificationProgress()
              .getPassedTokens()
              .add(TokenVerificationProgress.TokenChannel.EMAIL);
          updateProfileBean
              .getTokenVerificationProgress()
              .getIssuedTokens()
              .add(TokenVerificationProgress.TokenChannel.EMAIL);
          updateProfileBean.getTokenVerificationProgress().setPhase(null);
          tokenPassed = true;
        } else if (TokenType.UPDATE_SMS.matchesName(tokenPayload.getName())) {
          LOGGER.debug(pwmRequest, "SMS token passed");
          updateProfileBean
              .getTokenVerificationProgress()
              .getPassedTokens()
              .add(TokenVerificationProgress.TokenChannel.SMS);
          updateProfileBean
              .getTokenVerificationProgress()
              .getIssuedTokens()
              .add(TokenVerificationProgress.TokenChannel.SMS);
          updateProfileBean.getTokenVerificationProgress().setPhase(null);
          tokenPassed = true;
        } else {
          final String errorMsg = "token name/type is not recognized: " + tokenPayload.getName();
          errorInformation = new ErrorInformation(PwmError.ERROR_TOKEN_INCORRECT, errorMsg);
        }
      }
    } catch (PwmOperationalException e) {
      final String errorMsg = "token incorrect: " + e.getMessage();
      errorInformation = new ErrorInformation(PwmError.ERROR_TOKEN_INCORRECT, errorMsg);
    }

    if (!tokenPassed) {
      if (errorInformation == null) {
        errorInformation = new ErrorInformation(PwmError.ERROR_TOKEN_INCORRECT);
      }
      LOGGER.debug(pwmSession, errorInformation.toDebugStr());
      pwmRequest.setResponseError(errorInformation);
    }
  }
  private void handleAgreeRequest(
      final PwmRequest pwmRequest, final UpdateProfileBean updateProfileBean)
      throws ServletException, IOException, PwmUnrecoverableException, ChaiUnavailableException {
    LOGGER.debug(pwmRequest, "user accepted agreement");

    if (!updateProfileBean.isAgreementPassed()) {
      updateProfileBean.setAgreementPassed(true);
      AuditRecord auditRecord =
          pwmRequest
              .getPwmApplication()
              .getAuditManager()
              .createUserAuditRecord(
                  AuditEvent.AGREEMENT_PASSED,
                  pwmRequest.getUserInfoIfLoggedIn(),
                  pwmRequest.getSessionLabel(),
                  "UpdateProfile");
      pwmRequest.getPwmApplication().getAuditManager().submit(auditRecord);
    }
  }
  public void initializeToken(
      final PwmRequest pwmRequest,
      final UpdateProfileBean updateProfileBean,
      final TokenVerificationProgress.TokenChannel tokenType)
      throws PwmUnrecoverableException {
    final PwmSession pwmSession = pwmRequest.getPwmSession();
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();

    if (pwmApplication.getConfig().getTokenStorageMethod() == TokenStorageMethod.STORE_LDAP) {
      throw new PwmUnrecoverableException(
          new ErrorInformation(
              PwmError.CONFIG_FORMAT_ERROR,
              null,
              new String[] {
                "cannot generate new user tokens when storage type is configured as STORE_LDAP."
              }));
    }

    final MacroMachine macroMachine =
        pwmRequest.getPwmSession().getSessionManager().getMacroMachine(pwmApplication);
    final Configuration config = pwmApplication.getConfig();

    switch (tokenType) {
      case SMS:
        {
          final String telephoneNumberAttribute =
              pwmRequest.getConfig().readSettingAsString(PwmSetting.SMS_USER_PHONE_ATTRIBUTE);
          final String toNum = updateProfileBean.getFormData().get(telephoneNumberAttribute);
          final String tokenKey;
          try {
            final TokenPayload tokenPayload =
                pwmApplication
                    .getTokenService()
                    .createTokenPayload(
                        TokenType.UPDATE_SMS,
                        Collections.<String, String>emptyMap(),
                        pwmRequest.getUserInfoIfLoggedIn(),
                        Collections.singleton(toNum));
            tokenKey =
                pwmApplication
                    .getTokenService()
                    .generateNewToken(tokenPayload, pwmRequest.getSessionLabel());
          } catch (PwmOperationalException e) {
            throw new PwmUnrecoverableException(e.getErrorInformation());
          }

          final String message =
              config.readSettingAsLocalizedString(
                  PwmSetting.SMS_UPDATE_PROFILE_TOKEN_TEXT,
                  pwmSession.getSessionStateBean().getLocale());

          try {
            TokenService.TokenSender.sendSmsToken(
                pwmApplication, null, macroMachine, toNum, message, tokenKey);
          } catch (Exception e) {
            throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNKNOWN));
          }

          updateProfileBean
              .getTokenVerificationProgress()
              .getIssuedTokens()
              .add(TokenVerificationProgress.TokenChannel.SMS);
          updateProfileBean.getTokenVerificationProgress().setTokenDisplayText(toNum);
          updateProfileBean
              .getTokenVerificationProgress()
              .setPhase(TokenVerificationProgress.TokenChannel.SMS);
        }
        break;

      case EMAIL:
        {
          final EmailItemBean configuredEmailSetting =
              config.readSettingAsEmail(
                  PwmSetting.EMAIL_UPDATEPROFILE_VERIFICATION, pwmRequest.getLocale());
          final String emailAddressAttribute =
              pwmRequest.getConfig().readSettingAsString(PwmSetting.EMAIL_USER_MAIL_ATTRIBUTE);
          final String toAddress = updateProfileBean.getFormData().get(emailAddressAttribute);

          final String tokenKey;
          try {
            final TokenPayload tokenPayload =
                pwmApplication
                    .getTokenService()
                    .createTokenPayload(
                        TokenType.UPDATE_EMAIL,
                        Collections.<String, String>emptyMap(),
                        pwmRequest.getUserInfoIfLoggedIn(),
                        Collections.singleton(toAddress));
            tokenKey =
                pwmApplication
                    .getTokenService()
                    .generateNewToken(tokenPayload, pwmRequest.getSessionLabel());
          } catch (PwmOperationalException e) {
            throw new PwmUnrecoverableException(e.getErrorInformation());
          }

          updateProfileBean
              .getTokenVerificationProgress()
              .getIssuedTokens()
              .add(TokenVerificationProgress.TokenChannel.EMAIL);
          updateProfileBean
              .getTokenVerificationProgress()
              .setPhase(TokenVerificationProgress.TokenChannel.EMAIL);
          updateProfileBean.getTokenVerificationProgress().setTokenDisplayText(toAddress);

          final EmailItemBean emailItemBean =
              new EmailItemBean(
                  toAddress,
                  configuredEmailSetting.getFrom(),
                  configuredEmailSetting.getSubject(),
                  configuredEmailSetting.getBodyPlain().replace("%TOKEN%", tokenKey),
                  configuredEmailSetting.getBodyHtml().replace("%TOKEN%", tokenKey));

          try {
            TokenService.TokenSender.sendEmailToken(
                pwmApplication, null, macroMachine, emailItemBean, toAddress, tokenKey);
          } catch (Exception e) {
            throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNKNOWN));
          }
        }
        break;

      default:
        LOGGER.error("Unimplemented token purpose: " + tokenType);
        updateProfileBean.getTokenVerificationProgress().setPhase(null);
    }
  }
  static boolean checkAuthentication(
      final PwmRequest pwmRequest, final ConfigManagerBean configManagerBean)
      throws IOException, PwmUnrecoverableException, ServletException {
    final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
    final PwmSession pwmSession = pwmRequest.getPwmSession();
    final ConfigurationReader runningConfigReader =
        ContextManager.getContextManager(pwmRequest.getHttpServletRequest().getSession())
            .getConfigReader();
    final StoredConfigurationImpl storedConfig = runningConfigReader.getStoredConfiguration();

    boolean authRequired = false;
    if (storedConfig.hasPassword()) {
      authRequired = true;
    }

    if (PwmApplication.MODE.RUNNING == pwmRequest.getPwmApplication().getApplicationMode()) {
      if (!pwmSession.getSessionStateBean().isAuthenticated()) {
        throw new PwmUnrecoverableException(PwmError.ERROR_AUTHENTICATION_REQUIRED);
      }

      if (!pwmRequest
          .getPwmSession()
          .getSessionManager()
          .checkPermission(pwmRequest.getPwmApplication(), Permission.PWMADMIN)) {
        final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNAUTHORIZED);
        pwmRequest.respondWithError(errorInformation);
        return true;
      }

      if (pwmSession.getLoginInfoBean().getAuthenticationType()
          != AuthenticationType.AUTHENTICATED) {
        throw new PwmUnrecoverableException(
            new ErrorInformation(
                PwmError.ERROR_AUTHENTICATION_REQUIRED,
                "Username/Password authentication is required to edit configuration.  This session has not been authenticated using a user password (SSO or other method used)."));
      }
    }

    if (PwmApplication.MODE.CONFIGURATION != pwmRequest.getPwmApplication().getApplicationMode()) {
      authRequired = true;
    }

    if (!authRequired) {
      return false;
    }

    if (!storedConfig.hasPassword()) {
      final String errorMsg = "config file does not have a configuration password";
      final ErrorInformation errorInformation =
          new ErrorInformation(PwmError.CONFIG_FORMAT_ERROR, errorMsg, new String[] {errorMsg});
      pwmRequest.respondWithError(errorInformation, true);
      return true;
    }

    if (configManagerBean.isPasswordVerified()) {
      return false;
    }

    String persistentLoginValue = null;
    boolean persistentLoginAccepted = false;
    boolean persistentLoginEnabled = false;
    if (pwmRequest.getConfig().isDefaultValue(PwmSetting.PWM_SECURITY_KEY)) {
      LOGGER.debug(pwmRequest, "security not available, persistent login not possible.");
    } else {
      persistentLoginEnabled = true;
      final PwmSecurityKey securityKey = pwmRequest.getConfig().getSecurityKey();

      if (PwmApplication.MODE.RUNNING == pwmRequest.getPwmApplication().getApplicationMode()) {
        persistentLoginValue =
            SecureEngine.hash(
                storedConfig.readConfigProperty(ConfigurationProperty.PASSWORD_HASH)
                    + pwmSession.getUserInfoBean().getUserIdentity().toDelimitedKey(),
                PwmHashAlgorithm.SHA512);

      } else {
        persistentLoginValue =
            SecureEngine.hash(
                storedConfig.readConfigProperty(ConfigurationProperty.PASSWORD_HASH),
                PwmHashAlgorithm.SHA512);
      }

      {
        final String cookieStr =
            ServletHelper.readCookie(
                pwmRequest.getHttpServletRequest(), PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN);
        if (securityKey != null && cookieStr != null && !cookieStr.isEmpty()) {
          try {
            final String jsonStr = pwmApplication.getSecureService().decryptStringValue(cookieStr);
            final PersistentLoginInfo persistentLoginInfo =
                JsonUtil.deserialize(jsonStr, PersistentLoginInfo.class);
            if (persistentLoginInfo != null && persistentLoginValue != null) {
              if (persistentLoginInfo.getExpireDate().after(new Date())) {
                if (persistentLoginValue.equals(persistentLoginInfo.getPassword())) {
                  persistentLoginAccepted = true;
                  LOGGER.debug(
                      pwmRequest,
                      "accepting persistent config login from cookie (expires "
                          + PwmConstants.DEFAULT_DATETIME_FORMAT.format(
                              persistentLoginInfo.getExpireDate())
                          + ")");
                }
              }
            }
          } catch (Exception e) {
            LOGGER.error(
                pwmRequest, "error examining persistent config login cookie: " + e.getMessage());
          }
          if (!persistentLoginAccepted) {
            Cookie removalCookie = new Cookie(PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN, null);
            removalCookie.setMaxAge(0);
            pwmRequest.getPwmResponse().addCookie(removalCookie);
            LOGGER.debug(pwmRequest, "removing non-working persistent config login cookie");
          }
        }
      }
    }

    final String password = pwmRequest.readParameterAsString("password");
    boolean passwordAccepted = false;
    if (!persistentLoginAccepted) {
      if (password != null && password.length() > 0) {
        if (storedConfig.verifyPassword(password)) {
          passwordAccepted = true;
          LOGGER.trace(pwmRequest, "valid configuration password accepted");
          updateLoginHistory(pwmRequest, pwmRequest.getUserInfoIfLoggedIn(), true);
        } else {
          LOGGER.trace(pwmRequest, "configuration password is not correct");
          pwmApplication.getIntruderManager().convenience().markAddressAndSession(pwmSession);
          pwmApplication
              .getIntruderManager()
              .mark(
                  RecordType.USERNAME,
                  PwmConstants.CONFIGMANAGER_INTRUDER_USERNAME,
                  pwmSession.getLabel());
          final ErrorInformation errorInformation =
              new ErrorInformation(PwmError.ERROR_WRONGPASSWORD);
          pwmRequest.setResponseError(errorInformation);
          updateLoginHistory(pwmRequest, pwmRequest.getUserInfoIfLoggedIn(), false);
        }
      }
    }

    if ((persistentLoginAccepted || passwordAccepted)) {
      configManagerBean.setPasswordVerified(true);
      pwmApplication.getIntruderManager().convenience().clearAddressAndSession(pwmSession);
      pwmApplication
          .getIntruderManager()
          .clear(RecordType.USERNAME, PwmConstants.CONFIGMANAGER_INTRUDER_USERNAME);
      if (persistentLoginEnabled
          && !persistentLoginAccepted
          && "on".equals(pwmRequest.readParameterAsString("remember"))) {
        final int persistentSeconds = figureMaxLoginSeconds(pwmRequest);
        if (persistentSeconds > 0) {
          final Date expirationDate =
              new Date(System.currentTimeMillis() + (persistentSeconds * 1000));
          final PersistentLoginInfo persistentLoginInfo =
              new PersistentLoginInfo(expirationDate, persistentLoginValue);
          final String jsonPersistentLoginInfo = JsonUtil.serialize(persistentLoginInfo);
          final String cookieValue =
              pwmApplication.getSecureService().encryptToString(jsonPersistentLoginInfo);
          pwmRequest
              .getPwmResponse()
              .writeCookie(
                  PwmConstants.COOKIE_PERSISTENT_CONFIG_LOGIN, cookieValue, persistentSeconds);
          LOGGER.debug(
              pwmRequest,
              "set persistent config login cookie (expires "
                  + PwmConstants.DEFAULT_DATETIME_FORMAT.format(expirationDate)
                  + ")");
        }
      }

      if (configManagerBean.getPrePasswordEntryUrl() != null) {
        final String originalUrl = configManagerBean.getPrePasswordEntryUrl();
        configManagerBean.setPrePasswordEntryUrl(null);
        pwmRequest.getPwmResponse().sendRedirect(originalUrl);
        return true;
      }
      return false;
    }

    if (configManagerBean.getPrePasswordEntryUrl() == null) {
      configManagerBean.setPrePasswordEntryUrl(
          pwmRequest.getHttpServletRequest().getRequestURL().toString());
    }

    forwardToJsp(pwmRequest);
    return true;
  }