diff --git a/gradle.properties b/gradle.properties index 274deb5c..9c3b4333 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -currentVersion=1.2.0.0 +currentVersion=1.2.0.1 diff --git a/src/main/java/org/secureauth/sarestapi/util/HMACUtil.java b/src/main/java/org/secureauth/sarestapi/util/HMACUtil.java index 02a14acb..fd6b76cc 100755 --- a/src/main/java/org/secureauth/sarestapi/util/HMACUtil.java +++ b/src/main/java/org/secureauth/sarestapi/util/HMACUtil.java @@ -1,5 +1,6 @@ package org.secureauth.sarestapi.util; +import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; @@ -50,6 +51,8 @@ private HMACUtil() { public static byte[] encode(String secret, String data) throws Exception { // get the bytes of the hmac key and data string + if(!secret.matches("^[0-9a-fA-F]+$")) + throw new DecoderException(String.format("Secret '%s' is not a valid hex string", secret)); byte[] secretByte = new Hex(StandardCharsets.UTF_8).decode(secret.getBytes(StandardCharsets.UTF_8)); byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); SecretKeySpec secretKey = new SecretKeySpec(secretByte, "HmacSHA256"); diff --git a/src/main/java/org/secureauth/sarestapi/util/RestApiHeader.java b/src/main/java/org/secureauth/sarestapi/util/RestApiHeader.java index 4815e609..5346bbaf 100755 --- a/src/main/java/org/secureauth/sarestapi/util/RestApiHeader.java +++ b/src/main/java/org/secureauth/sarestapi/util/RestApiHeader.java @@ -5,6 +5,7 @@ import org.apache.commons.codec.binary.Base64; import org.secureauth.sarestapi.data.*; +import org.secureauth.sarestapi.exception.SARestAPIException; import org.secureauth.sarestapi.resources.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,61 +53,51 @@ private RestApiHeader() { // Payload in header public static String getAuthorizationHeader(SAAuth saAuth, String requestMethod, String uriPath, Object object, - String ts) { + String ts) throws SARestAPIException { // Build our string for the AuthHeader StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(requestMethod).append("\n") .append(ts).append("\n") .append(saAuth.getApplicationID()).append("\n") - .append(Resource.SLASH + uriPath).append("\n") + .append(Resource.SLASH).append(uriPath).append("\n") .append(JSONUtil.convertObjectToJSON(object)); String authHeader = ""; // Create a SHA256 Hash - String base64Sha = ""; - try { - base64Sha = new String( - Base64.encodeBase64(HMACUtil.encode(saAuth.getApplicationKey(), stringBuilder.toString()))); - } catch (Exception e) { - logger.error("Exception occurred while generating Authorization Header\n" + e.getMessage() + "\n", e); - } - - String appId = saAuth.getApplicationID() + ":" + base64Sha; - logger.trace("Auth Header before second encoding " + appId + "\n"); - try { - authHeader = "Basic " + Base64.encodeBase64String(appId.getBytes("UTF-8")); - } catch (UnsupportedEncodingException uee) { - logger.error("Exception Encoding\n" + uee.getMessage() + "\n", uee); - } + String appId = encodeAppId(saAuth.getApplicationKey(), saAuth.getApplicationID(), stringBuilder.toString()); + authHeader = "Basic " + Base64.encodeBase64String(appId.getBytes(StandardCharsets.UTF_8)); return authHeader; } // No Payload in header - public static String getAuthorizationHeader(SAAuth saAuth, String requestMethod, String uriPath, String ts) { + public static String getAuthorizationHeader(SAAuth saAuth, String requestMethod, String uriPath, String ts) throws SARestAPIException { // Build our string for the AuthHeader + String authHeader = ""; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(requestMethod).append("\n") .append(ts).append("\n") .append(saAuth.getApplicationID()).append("\n") - .append(Resource.SLASH + uriPath); - - String authHeader = ""; - // Create a SHA256 Hash - String base64Sha = ""; - try { - base64Sha = new String( - Base64.encodeBase64(HMACUtil.encode(saAuth.getApplicationKey(), stringBuilder.toString()))); - } catch (Exception e) { - logger.error("Exception occurred while generating Authorization Header\n" + e.getMessage() + "\n", e); - } + .append(Resource.SLASH).append(uriPath); - String appId = saAuth.getApplicationID() + ":" + base64Sha; - logger.trace("Auth Header before second encoding " + appId + "\n"); + String appId = encodeAppId(saAuth.getApplicationKey(), saAuth.getApplicationID(), stringBuilder.toString()); authHeader = "Basic " + Base64.encodeBase64String(appId.getBytes(StandardCharsets.UTF_8)); return authHeader; } + private static String encodeAppId(String applicationKey, String applicationID, String data) throws SARestAPIException { + + try { + // Create a SHA256 Hash + String base64Sha = new String(Base64.encodeBase64(HMACUtil.encode(applicationKey, data))); + String appId = applicationID + ":" + base64Sha; + logger.trace("Auth Header before second encoding " + appId + "\n"); + return appId; + } catch (Exception e) { + throw new SARestAPIException("Exception occurred while generating Authorization Header", e); + } + } + } diff --git a/src/test/java/org/secureauth/restapi/test/SAAccessTDD.java b/src/test/java/org/secureauth/restapi/test/SAAccessTDD.java index 37c65b13..09b465a3 100644 --- a/src/test/java/org/secureauth/restapi/test/SAAccessTDD.java +++ b/src/test/java/org/secureauth/restapi/test/SAAccessTDD.java @@ -81,6 +81,7 @@ public class SAAccessTDD { private static RetrievePropertiesUtils retrievePropertiesUtils; private static Boolean assumeTest; + private static Boolean assumeTestTransitive; @Before public void setup() { @@ -112,7 +113,7 @@ private void setupStrings() { validYubicoToken = getValue(Property.VALID_YUBICO_TOKEN); validIp = getValue(Property.VALID_IP); assumeTest = Boolean.valueOf(getValue(Property.ASSUME_TEST)); - + assumeTestTransitive = Boolean.valueOf(getValue(Property.ASSUME_TEST_TRANSITIVE)); } private String getValue(Property property) { @@ -307,27 +308,17 @@ public void testValidateOathOTPWithInvalidFactorId() throws Exception { String invalidFactorId = "zzzz0000z0000a00zzzz000z0zz0z00z"; BaseResponse response = saAccess.validateOath(validUsername, validUserOtp, invalidFactorId); - String expectedResponse = String.format("Request validation failed with: Unknown factor id %s", - invalidFactorId); assertNotNull(response); assertEquals(INVALID_MESSAGE, response.getStatus()); - assertEquals(expectedResponse, response.getMessage()); + assertTrue(response.getMessage().contains(invalidFactorId)); } @Test - public void testValidateOathOTPWithInvalidCode() throws Exception { - /* - * Response would return: - * { - * "status" : "invalid", - * "message" : "OTP is invalid." - * } - */ + public void testValidateOathOTPWithInvalidCode() throws Exception { BaseResponse response = saAccess.validateOath(validUsername, validUserOtp, validFactorIdForOathOtp); assertNotNull(response); assertEquals(INVALID_MESSAGE, response.getStatus()); - assertEquals(INVALID_OTP_MESSAGE, response.getMessage()); } @Test @@ -609,6 +600,7 @@ public void testUserPINWithInvalidStrings() throws Exception { @Test public void testUpdateUserProfileKBQKBAOrderedValid() throws Exception { + Assume.assumeTrue(assumeTestTransitive); NewUserProfile newUserProfile = new NewUserProfile(); newUserProfile.getKnowledgeBase().put("nonFormated1", new UserProfileKB("kbq1", "kba1")); newUserProfile.getKnowledgeBase().put("nonFormated3", new UserProfileKB("kbq3", "kba3")); @@ -629,6 +621,7 @@ public void testUpdateUserProfileKBQKBAOrderedValid() throws Exception { @Test public void testCreateUserProfileKBQKBAOrderedValid() throws Exception { + Assume.assumeTrue(assumeTestTransitive); NewUserProfile newUserProfile = new NewUserProfile(); newUserProfile.getKnowledgeBase().put("NonFormated2", new UserProfileKB("Kbq2", "kba2")); @@ -653,6 +646,7 @@ public void testCreateUserProfileKBQKBAOrderedValid() throws Exception { @Test(expected = SARestAPIException.class) public void testCreateUserProfileKBQKBAOrderedInValid() throws Exception { + Assume.assumeTrue(assumeTestTransitive); NewUserProfile newUserProfile = new NewUserProfile(); newUserProfile.getKnowledgeBase().put("nonFormated1", new UserProfileKB("kbq1", "kba1")); @@ -705,6 +699,7 @@ public void testDFPScoreWithValidNotFound() throws Exception { @Test public void testDeleteUserValid() throws Exception { + Assume.assumeTrue(assumeTestTransitive); // when BaseResponse responseObj = saAccess.deleteUser(NEW_USERNAME, userDomain, Boolean.FALSE); // then @@ -843,6 +838,7 @@ public void testDFPSaveWithValidFound() throws Exception { * "message": "" * } */ + Assume.assumeTrue(assumeTestTransitive); String fingerprintJSON = "{\n" + " \"fingerprint\" : {\"uaString\" : \"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0\",\n" + @@ -948,6 +944,7 @@ public void testDFPSaveWithValidNotFound() throws Exception { * "message": "" * } */ + Assume.assumeTrue(assumeTestTransitive); String emptyFingerprintJSON = "{}"; DFPValidateResponse response = saAccess.DFPSaveFingerprint(validUsername, validHostAddress, validFingerprintId, @@ -993,6 +990,7 @@ public void testWhenUserIdIsNotValidThenNotifyAuthenticatedResultFail() { // This tests the creation of a real user @Test public void testCreateUserWithSpecialCharacters() { + Assume.assumeTrue(assumeTestTransitive); NewUserProfile userProfile = new NewUserProfile(); userProfile.setUserId(NEW_USERNAME_QP); userProfile.setPassword(NEW_USER_PASSWORD); @@ -1003,6 +1001,7 @@ public void testCreateUserWithSpecialCharacters() { @Test public void testGetCreatedUserWithSpecialCharacters() { + Assume.assumeTrue(assumeTestTransitive); String userName = validUsername; BaseResponse response = saAccess.getUserProfileQP(userName); @@ -1011,6 +1010,7 @@ public void testGetCreatedUserWithSpecialCharacters() { @Test public void testGetCreatedFactorsUserWithSpecialCharacters() { + Assume.assumeTrue(assumeTestTransitive); String userName = validUsername; BaseResponse response = saAccess.factorsByUserQP(userName); @@ -1019,6 +1019,7 @@ public void testGetCreatedFactorsUserWithSpecialCharacters() { @Test public void testGetCreatedThrottleUserWithSpecialCharacters() { + Assume.assumeTrue(assumeTestTransitive); String userName = validUsername; BaseResponse response = saAccess.getThrottleReqQP(userName); diff --git a/src/test/java/org/secureauth/sarestapi/guid/SAAccessUnitTest.java b/src/test/java/org/secureauth/sarestapi/guid/SAAccessUnitTest.java index 639732e1..c94f2516 100644 --- a/src/test/java/org/secureauth/sarestapi/guid/SAAccessUnitTest.java +++ b/src/test/java/org/secureauth/sarestapi/guid/SAAccessUnitTest.java @@ -63,8 +63,8 @@ private SAAccess createSAAccessWithTransactionId(String transactionId) { false, true, "Realm01", - "Realm01-ApplicationId", - "Realm01-ApplicationKey", + "971e6dea94f443ee932f0a3447672aea", + "19d4364f56975fed0f58716b78693922507de3d37fdb8784edba5c29af2416fd", transactionId ); } diff --git a/src/test/java/org/secureauth/sarestapi/stateful/SAAccessUnitTest.java b/src/test/java/org/secureauth/sarestapi/stateful/SAAccessUnitTest.java index e6a47d69..b38f3440 100644 --- a/src/test/java/org/secureauth/sarestapi/stateful/SAAccessUnitTest.java +++ b/src/test/java/org/secureauth/sarestapi/stateful/SAAccessUnitTest.java @@ -27,8 +27,8 @@ public void setup() { false, true, "Realm01", - "Realm01-ApplicationId", - "Realm01-ApplicationKey" + "971e6dea94f443ee932f0a3447672aea", + "19d4364f56975fed0f58716b78693922507de3d37fdb8784edba5c29af2416fd" ); } diff --git a/src/test/java/org/secureauth/sarestapi/util/Property.java b/src/test/java/org/secureauth/sarestapi/util/Property.java index 1536580c..9d0d82b9 100644 --- a/src/test/java/org/secureauth/sarestapi/util/Property.java +++ b/src/test/java/org/secureauth/sarestapi/util/Property.java @@ -20,7 +20,8 @@ public enum Property { VALID_FINGERPRINT_ID("valid.fingerprint.id"), VALID_YUBICO_TOKEN("valid.yubico.token"), VALID_IP("user.ip"), - ASSUME_TEST("assume.test"); + ASSUME_TEST("assume.test"), + ASSUME_TEST_TRANSITIVE("assume.test.transitive"); private final String value; diff --git a/src/test/java/org/secureauth/sarestapi/util/RestApiHeaderTest.java b/src/test/java/org/secureauth/sarestapi/util/RestApiHeaderTest.java index 67b8dcf4..63077b94 100644 --- a/src/test/java/org/secureauth/sarestapi/util/RestApiHeaderTest.java +++ b/src/test/java/org/secureauth/sarestapi/util/RestApiHeaderTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; import org.secureauth.sarestapi.data.Requests.StatusRequest; import org.secureauth.sarestapi.data.SAAuth; +import org.secureauth.sarestapi.exception.SARestAPIException; import org.secureauth.sarestapi.queries.StatusQuery; import org.secureauth.sarestapi.resources.Resource; @@ -25,15 +26,15 @@ public void setup() { saAuth = new SAAuth(applicationID,applicationKey,realm); } - // Maybe could change this to check throws DecoderException and Throw the exception instead of logging @Test void getAuthorizationHeaderWithoutEncodingKey() { String query = StatusQuery.queryStatus(saAuth.getRealm(), "userId"); saAuth.setApplicationKey("applicationKey"); - String header = RestApiHeader.getAuthorizationHeader(saAuth, Resource.METHOD_GET, query, getServerTime()); - - assertEquals("Basic YXBwbGljYXRpb25JRDo=", header); + assertThrows(SARestAPIException.class, () -> { + String header = RestApiHeader.getAuthorizationHeader(saAuth, Resource.METHOD_GET, query, getServerTime()); + assertEquals("Basic YXBwbGljYXRpb25JRDo=", header); + }); } @Test diff --git a/src/test/resources/test.properties b/src/test/resources/test.properties index 646819e4..6d2cabff 100644 --- a/src/test/resources/test.properties +++ b/src/test/resources/test.properties @@ -23,4 +23,5 @@ user.otp.oath= #Valid_Tokens valid.yubico.token= -assume.test=false \ No newline at end of file +assume.test=false +assume.test.transitive=false