@Override
  public void associateObjs(String userId, String tokenId) {

    apiURL = new String();
    apiURL = duoUserApi + "/" + userId + "/tokens";

    request = genHttpRequest("POST", apiURL);
    request.addParam("token_id", tokenId);
    request = signHttpRequest();

    try {
      request.executeRequest();
      logger.debug("2FA Debug - " + "Successfully Linked Token to User account");
    } catch (Exception ex) {
      logger.error("2FA Error - " + "Unable to Link Token to User account!!!!");
      logger.error("2FA Error - " + "The Error is(TokenObjImp): " + ex.toString());
    }
  }
  private Http signHttpRequest() {

    try {
      request.signRequest(
          duoAllIKeys.getAdminikeys().getIkey(), duoAllIKeys.getAdminikeys().getSkey());

    } catch (Exception e) {
    }

    return request;
  }
  @Override
  public void resyncObj(
      String tokenId, String resyncCode1, String resyncCode2, String resyncCode3) {
    apiURL = new String();
    apiURL = duoTokenApi + "/" + tokenId + "/resync";

    request = genHttpRequest("POST", apiURL);
    request.addParam("code1", resyncCode1);
    request.addParam("code2", resyncCode2);
    request.addParam("code3", resyncCode3);
    request = signHttpRequest();

    try {
      request.executeRequest();
      logger.debug("2FA Debug - " + "Successfully RESYNC Token to User account");
    } catch (Exception ex) {
      logger.error("2FA Error - " + "Unable to RESYNC Token for User account!!!!");
      logger.error("2FA Error - " + "The Error is(TokenObjImp): " + ex.toString());
    }
  }
  @Override
  public String getObjByParam(String tokenSerial, String tokenType, String attribute) {
    String returnObj = null;
    JSONArray users;

    request = genHttpRequest("GET", duoTokenApi);
    request.addParam("serial", tokenSerial);
    request.addParam("type", tokenType);
    request = signHttpRequest();

    try {
      jResults = (JSONArray) request.executeRequest();

      switch (attribute) {
        case "username":
          if (jResults.getJSONObject(0).getJSONArray("users").length() > 0) {
            users = jResults.getJSONObject(0).getJSONArray("users");
            returnObj = "|";
            for (int i = 0; i < users.length(); i++) {
              returnObj += users.getJSONObject(i).getString("username") + "|";
            }
            logger.debug("2FA Debug - " + "Token's Users Retrieved:" + returnObj);
          }
          break;
        case "tokenId":
          returnObj = jResults.getJSONObject(0).getString("token_id");
          logger.debug("2FA Debug - " + "Token's ID is:" + returnObj);
          break;
      }
    } catch (Exception ex) {
      if (jResults.length() == 0) {
        logger.error("2FA Error - " + "Token Not Exist!!!");
      } else {
        logger.error("2FA Error - " + "Token Search Encounter a problem!!!!");
      }
      logger.error("2FA Error - " + "The Error is: " + ex.toString());
    }

    return returnObj;
  }
  @Override
  public void deleteObj(String tokenId, String userId) {
    apiURL = new String();
    apiURL = duoUserApi + "/" + userId + "/tokens/" + tokenId;

    request = genHttpRequest("DELETE", apiURL);
    request = signHttpRequest();

    try {
      request.executeRequest();
      logger.debug("2FA Debug - " + "Successfully Disassociate Token, ID=" + tokenId);
    } catch (Exception ex) {
      logger.error("2FA Error - " + "Unable to Disassociate Token from Useraccount!!!");
      logger.error("2FA Error - " + "The Error is(TokenObjImp): " + ex.toString());
    }
  }
  /**
   * Why use UserId instead of UserName??
   *
   * <p>1)UserId always SINGLE record, although Username search should only have one record also...
   *
   * <p>2)The JSON Response code for userID search is either success or User not found, easier to
   * capture the exception?
   *
   * <p>3)Return a JSON object instead of JSON Array, safe one layer of parsing
   */
  @Override
  public List<DuoToken> getAllTokens(String userId) {
    apiURL = new String();
    apiURL = duoUserApi + "/" + userId;
    request = genHttpRequest("GET", apiURL);
    request = signHttpRequest();

    jResults = null;

    DuoToken duoToken;
    JSONArray jTokens;
    List<DuoToken> tokens = new ArrayList<>();

    try {
      jResult = (JSONObject) request.executeRequest();
      jTokens = jResult.getJSONArray("tokens");

      logger.debug(
          "2FA Debug - "
              + "Total Number of Tokens(DuoTokenImp) "
              + userId
              + " has:"
              + jTokens.length());

      for (int t = 0; t < jTokens.length(); t++) {

        duoToken = new DuoToken();
        duoToken.setId(jTokens.getJSONObject(t).getString("token_id"));
        duoToken.setType(jTokens.getJSONObject(t).getString("type"));
        duoToken.setSerial(jTokens.getJSONObject(t).getString("serial"));

        tokens.add(duoToken);
      }

    } catch (Exception ex) {
      logger.error("2FA Error - " + "Unable to Excute Method 'GetAllTokens'");
      logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
    }

    return tokens;
  }
 private Response sendPreAuthRequest(String username) throws Exception {
   Http request = new Http("POST", host, "/auth/v2/preauth", 10);
   request.addParam("username", username);
   request.signRequest(ikey, skey);
   return request.executeHttpRequest();
 }