/**
* Copyright 2014 University of Chicago
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* Author: Daniel Yu <danielyu@uchicago.edu>
*/
package edu.uchicago.duo.service;
import com.duosecurity.client.Http;
import edu.uchicago.duo.domain.DuoAllIntegrationKeys;
import edu.uchicago.duo.domain.DuoPhone;
import edu.uchicago.duo.domain.DuoTablet;
import edu.uchicago.duo.domain.DuoToken;
import edu.uchicago.duo.web.DuoEnrollController;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Future;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
@Service("duoTokenService")
public class DuoTokenObjImpl implements DuoObjInterface {
//get log4j handler
private static final Logger logger = Logger.getLogger(DuoEnrollController.class);
private static final String duoTokenApi = "/admin/v1/tokens";
private static final String duoUserApi = "/admin/v1/users";
private String apiURL;
private Http request = null;
@Autowired(required = true)
private DuoAllIntegrationKeys duoAllIKeys;
private JSONObject jResult = null;
private JSONArray jResults = null;
@Autowired
private MessageSource message;
@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 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());
}
}
/**
* Why use UserId instead of UserName??
*
* 1)UserId always SINGLE record, although Username search should only have
* one record also...
*
* 2)The JSON Response code for userID search is either success or User not
* found, easier to capture the exception?
*
* 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;
}
@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());
}
}
@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());
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
private Http genHttpRequest(String getOrPost, String apiURL) {
request = null;
try {
request = new Http(getOrPost, duoAllIKeys.getAdminikeys().getHostkey(), apiURL);
} catch (Exception e) {
}
return request;
}
private Http signHttpRequest() {
try {
request.signRequest(duoAllIKeys.getAdminikeys().getIkey(), duoAllIKeys.getAdminikeys().getSkey());
} catch (Exception e) {
}
return request;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Override
public String getObjById() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String getObjStatusById(String param1) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String createObjByParam(String param1, String param2, String param3, String param4, String param5) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public String objActionById(String param1, String param2) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public List<DuoPhone> getAllPhones(String param1) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public List<DuoTablet> getAllTablets(String param1) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Map<String, Object> verifyObj(String param1, String param2, String param3) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}