diff --git a/CHANGELOG.md b/CHANGELOG.md index 32c185ff..bdf1acca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,17 @@ ## [4.6.0] #### Added -- Skip Type 4 TextOutputCallback [SDKS-3227] -- Allow developers to customize SDK Storage [SDKS-3378] -- Support PingOne Protect Marketplace Node [SDKS-3279] +- Allow developers to customize SDK storage [SDKS-3378] +- Support PingOne Protect Marketplace nodes [SDKS-3297] +- Support reCAPTCHA Enterprise node [SDKS-3325] - Expose Realm, Success Url with SSOToken [SDKS-3351] - Support Android 15 [SDKS-3098] -- Allow http/https scheme for Centralize Login redirect [SDKS-3433] +- Support http/https scheme for Centralize Login redirect [SDKS-3433] #### Fixed -- Potential CustomTabManager ServiceConnection leak. [SDKS-3346] +- Skip Type 4 TextOutputCallback [SDKS-3227] +- Potential CustomTabManager ServiceConnection leak [SDKS-3346] +- access_token api call triggered twice on force refresh [SDKS-3254] +- Allow http/https as redirect scheme in centralize login flow [SDKS-3433] ## [4.5.0] #### Added diff --git a/README.md b/README.md index f4ed61bb..6f157472 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Use the SDKs to leverage _[Intelligent Authentication](https://www.forgerock.com * Access Management (AM) 6.5.2+ * Android API level 23+ - * Android 6.0 (Marshmallow), 7.0 (Nougat), 8.0 (Oreo), 9.0 (Pie), 10.0, 11.0, 12.0, 13.0, 14.0 + * Android 6.0 (Marshmallow), 7.0 (Nougat), 8.0 (Oreo), 9.0 (Pie), 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 diff --git a/forgerock-integration-tests/src/androidTest/AndroidManifest.xml b/forgerock-integration-tests/src/androidTest/AndroidManifest.xml index 0db558ec..f15aa650 100644 --- a/forgerock-integration-tests/src/androidTest/AndroidManifest.xml +++ b/forgerock-integration-tests/src/androidTest/AndroidManifest.xml @@ -15,6 +15,7 @@ diff --git a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/AndroidBaseTest.java b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/AndroidBaseTest.java index a9e92766..dfce5723 100644 --- a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/AndroidBaseTest.java +++ b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/AndroidBaseTest.java @@ -99,12 +99,12 @@ public void onCallbackReceived(Node node) { firstQuestion.setSelectedQuestion(firstQuestion.getPredefinedQuestions().get(0)); firstQuestion.setSelectedAnswer("Test"); - // Uncomment this block if there are more than one KbaCreateCallbacks in the tree - /* - KbaCreateCallback secondQuestion = (KbaCreateCallback) callbacks.get(1); - secondQuestion.setSelectedQuestion(secondQuestion.getPredefinedQuestions().get(1)); - secondQuestion.setSelectedAnswer("Test"); - */ + // If there are more than one KBA questions, answer the second one + if (callbacks.size() > 1) { + KbaCreateCallback secondQuestion = (KbaCreateCallback) callbacks.get(1); + secondQuestion.setSelectedQuestion(secondQuestion.getPredefinedQuestions().get(1)); + secondQuestion.setSelectedAnswer("Test"); + } node.next(context, this ); } diff --git a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BaseDeviceBindingTest.java b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BaseDeviceBindingTest.java index e7aae22a..833d73b7 100644 --- a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BaseDeviceBindingTest.java +++ b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BaseDeviceBindingTest.java @@ -23,6 +23,7 @@ import org.forgerock.android.auth.Logger; import org.forgerock.android.auth.RetryTestRule; import org.junit.After; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.rules.ExpectedException; @@ -36,7 +37,7 @@ public abstract class BaseDeviceBindingTest { protected static Context context = ApplicationProvider.getApplicationContext(); // This test uses dynamic configuration with the following settings: - protected final static String AM_URL = "https://openam-dbind.forgeblocks.com/am"; + protected final static String AM_URL = "https://openam-sdks2.forgeblocks.com/am"; protected final static String REALM = "alpha"; protected final static String OAUTH_CLIENT = "AndroidTest"; protected final static String OAUTH_REDIRECT_URI = "org.forgerock.demo:/oauth2redirect"; @@ -86,8 +87,15 @@ public static void setUpSDK() { } } + @Before + public void logoutSessionBeforeTest() { + if (FRSession.getCurrentSession() != null) { + FRSession.getCurrentSession().logout(); + } + } + @After - public void logoutSession() { + public void logoutSessionAfterTest() { if (FRSession.getCurrentSession() != null) { FRSession.getCurrentSession().logout(); } diff --git a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BasePingOneProtectTest.kt b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BasePingOneProtectTest.kt index 0cf75fad..9d6ac51d 100644 --- a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BasePingOneProtectTest.kt +++ b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/BasePingOneProtectTest.kt @@ -21,9 +21,9 @@ import java.util.concurrent.TimeUnit abstract class BasePingOneProtectTest { val context: Context = ApplicationProvider.getApplicationContext() - private val AM_URL = "https://openam-protect2.forgeblocks.com/am" + private val AM_URL = "https://openam-sdks2.forgeblocks.com/am" private val REALM = "alpha" - private val COOKIE_NAME = "c1c805de4c9b333" + private val COOKIE_NAME = "9dfa82bc124226d" private val OAUTH_CLIENT = "AndroidTest" private val OAUTH_REDIRECT_URI = "org.forgerock.demo:/oauth2redirect" private val SCOPE = "openid profile email address phone" diff --git a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/DeviceBindingCallbackTest.java b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/DeviceBindingCallbackTest.java index 64503806..9f08eee3 100644 --- a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/DeviceBindingCallbackTest.java +++ b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/DeviceBindingCallbackTest.java @@ -22,17 +22,20 @@ import org.forgerock.android.auth.NodeListenerFuture; import org.forgerock.android.auth.devicebind.ApplicationPinDeviceAuthenticator; import org.junit.Assert; +import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; import java.util.concurrent.ExecutionException; @RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) // These tests must run in order public class DeviceBindingCallbackTest extends BaseDeviceBindingTest { protected final static String TREE = "device-bind"; @Test - public void testDeviceBindingDefaults() throws ExecutionException, InterruptedException { + public void test01DeviceBindingDefaults() throws ExecutionException, InterruptedException { NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "default") { final NodeListener nodeListener = this; @@ -68,7 +71,7 @@ public void onCallbackReceived(Node node) { } @Test - public void testDeviceBindingCustom() throws ExecutionException, InterruptedException { + public void test02DeviceBindingCustom() throws ExecutionException, InterruptedException { NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "custom") { final NodeListener nodeListener = this; @@ -103,7 +106,7 @@ public void onCallbackReceived(Node node) { } @Test - public void testDeviceBindingBind() throws ExecutionException, InterruptedException { + public void test03DeviceBindingBind() throws ExecutionException, InterruptedException { final int[] hit = {0}; NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "custom") { final NodeListener nodeListener = this; @@ -141,7 +144,7 @@ public void onException(Exception e) { } @Test - public void testDeviceBindingExceed() throws ExecutionException, InterruptedException { + public void test04DeviceBindingExceed() throws ExecutionException, InterruptedException { final int[] hit = {0}; NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "exceed-limit") { final NodeListener nodeListener = this; @@ -174,7 +177,7 @@ public void onCallbackReceived(Node node) { } @Test - public void testDeviceBindingCustomOutcome() throws ExecutionException, InterruptedException { + public void test05DeviceBindingCustomOutcome() throws ExecutionException, InterruptedException { final int[] hit = {0}; NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "custom") { final NodeListener nodeListener = this; @@ -210,7 +213,7 @@ public void onCallbackReceived(Node node) { } @Test - public void testDeviceBindingApplicationPin() throws ExecutionException, InterruptedException { + public void test06DeviceBindingApplicationPin() throws ExecutionException, InterruptedException { final int[] bindSuccess = {0}; ActivityScenario scenario = ActivityScenario.launch(DummyActivity.class); @@ -254,7 +257,7 @@ public void onException(Exception e) { } @Test - public void testDeviceBindApplicationIdNotMatchingError() { + public void test07DeviceBindApplicationIdNotMatchingError() { final int[] bindSuccess = {0}; boolean executionExceptionOccurred = false; NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "wrong-app-id") { @@ -299,7 +302,7 @@ public void onException(Exception e) { } @Test - public void testDeviceBindingDeviceDataVariable() throws ExecutionException, InterruptedException { + public void test08DeviceBindingDeviceDataVariable() throws ExecutionException, InterruptedException { // This test is to ensure that the Device Binding node sets DeviceBinding.DEVICE variable in shared state final int[] bindSuccess = {0}; final int[] deviceDataVarPresentInAM = {0}; @@ -351,7 +354,7 @@ public void onException(Exception e) { * Make sure that when user does NOT exist, the Device Binding node triggers the failure outcome (SDKS-2935) */ @Test - public void testDeviceBindingUnknownUser() throws ExecutionException, InterruptedException { + public void test09DeviceBindingUnknownUser() throws ExecutionException, InterruptedException { final int[] hit = {0}; final int[] failureOutcome = {0}; NodeListenerFuture nodeListenerFuture = new DeviceBindingNodeListener(context, "default") diff --git a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/ReCaptchaEnterpriseCallbackFailureTest.kt b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/ReCaptchaEnterpriseCallbackFailureTest.kt index 0fbe09ef..c83a8daa 100644 --- a/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/ReCaptchaEnterpriseCallbackFailureTest.kt +++ b/forgerock-integration-tests/src/androidTest/java/org/forgerock/android/auth/callback/ReCaptchaEnterpriseCallbackFailureTest.kt @@ -14,6 +14,7 @@ import org.forgerock.android.auth.FRSession import org.forgerock.android.auth.Logger import org.forgerock.android.auth.Node import org.forgerock.android.auth.NodeListener +import org.json.JSONObject import org.junit.Assert import org.junit.FixMethodOrder import org.junit.Test @@ -49,11 +50,29 @@ class ReCaptchaEnterpriseCallbackFailureTest : ReCaptchaEnterpriseCallbackBaseTe if (node.getCallback(TextOutputCallback::class.java) != null) { nodeTextOutputHit[0]++ - // Note: The journey sends back to us the content of CaptchaEnterpriseNode.FAILURE - // in the message of the TextOutputCallback... so we can parse it here and verify results... + /* + Note: + The journey sends back to us the content of CaptchaEnterpriseNode.FAILURE + in the message of the TextOutputCallback... so we can parse it here and verify results... + However, tt is also possible that the score is equal exactly to 1.0 (when running on real device) + In that case the node will succeed, and the journey will send back the content of the + CaptchaEnterpriseNode.ASSESSMENT_RESULT variable. We need to account for this in the test, + and make sure tha the score is exactly 1.0... + */ + val message = node.getCallback(TextOutputCallback::class.java).message - Assertions.assertThat(message).contains("VALIDATION_ERROR") + if (!message.contains("VALIDATION_ERROR")) { + // If the node doesn't fail, make sure that in case the node doesn't fail the score is exactly 1.0 + val jsonObject = JSONObject(message) + Assert.assertNotNull(jsonObject) + Logger.debug("RecaptchaEnterpriseCallbackTest", jsonObject.toString(2)) + val score = jsonObject.getJSONObject("riskAnalysis").getDouble("score") + Assertions.assertThat(score).isEqualTo(1.0) + } + else { + Assertions.assertThat(message).contains("VALIDATION_ERROR") + } node.next(context, nodeListener) } super.onCallbackReceived(node) diff --git a/forgerock-integration-tests/src/androidTest/res/values/strings.xml b/forgerock-integration-tests/src/androidTest/res/values/strings.xml index f670ebbd..9e06fd2b 100644 --- a/forgerock-integration-tests/src/androidTest/res/values/strings.xml +++ b/forgerock-integration-tests/src/androidTest/res/values/strings.xml @@ -14,15 +14,15 @@ AndroidTest org.forgerock.demo:/oauth2redirect openid profile email address phone - https://openam-sdks.forgeblocks.com/am + https://openam-sdks2.forgeblocks.com/am 30 - https://openam-sdks.forgeblocks.com/am + https://openam-sdks2.forgeblocks.com/am alpha 30 - 5421aeddf91aa20 + 9dfa82bc124226d NamePasswordCallbackTest diff --git a/gradle.properties b/gradle.properties index 94a7340e..4cd954ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,8 +22,8 @@ org.gradle.jvmargs=-Xmx1536m kotlin.code.style=official android.useAndroidX=true GROUP=org.forgerock -VERSION=4.6.0-beta2 -VERSION_CODE=24 +VERSION=4.6.0 +VERSION_CODE=25 android.nonTransitiveRClass=false android.nonFinalResIds=false android.suppressUnsupportedCompileSdk=35 \ No newline at end of file