From f2fd6f7ac3c1f567dd10dae7e9fb5bf7fc838d5e Mon Sep 17 00:00:00 2001 From: Tyler Roach Date: Fri, 14 Jun 2024 16:19:08 -0400 Subject: [PATCH] fix(auth): Fix isSignedIn states (#2830) --- aws-auth-cognito/build.gradle.kts | 1 + .../auth/cognito/AWSCognitoAuthSession.kt | 59 ++++-- .../auth/cognito/RealAWSCognitoAuthPlugin.kt | 23 ++- .../actions/FetchAuthSessionCognitoActions.kt | 12 +- .../AWSCognitoAuthPluginFeatureTest.kt | 15 +- .../featuretest/generators/JsonGenerator.kt | 34 +++- .../generators/SerializationTools.kt | 2 +- .../AuthStateJsonGenerator.kt | 30 +-- .../FetchAuthSessionTestCaseGenerator.kt | 171 +++++++++++++++++- .../CognitoExceptionSerializers.kt | 12 ++ .../utilities/CognitoMockFactory.kt | 4 + .../featureTest/utilities/TimeZoneRule.kt | 17 ++ .../states/SignedIn_SessionEstablished.json | 4 +- ...eturned_after_failed_identity_refresh.json | 95 ++++++++++ ...ssfully_returned_after_failed_refresh.json | 73 ++++++++ ...s_successfully_returned_after_refresh.json | 34 +++- .../auth/exceptions/UnknownException.kt | 2 +- gradle/libs.versions.toml | 3 +- 18 files changed, 506 insertions(+), 85 deletions(-) create mode 100644 aws-auth-cognito/src/test/java/featureTest/utilities/TimeZoneRule.kt create mode 100644 aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_identity_refresh.json create mode 100644 aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_refresh.json diff --git a/aws-auth-cognito/build.gradle.kts b/aws-auth-cognito/build.gradle.kts index 9a62f8569a..f1f5d1e044 100644 --- a/aws-auth-cognito/build.gradle.kts +++ b/aws-auth-cognito/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { testImplementation(libs.test.androidx.core) testImplementation(libs.test.kotlin.reflection) testImplementation(libs.test.kotest.assertions) + testImplementation(libs.test.kotest.assertions.json) androidTestImplementation(libs.gson) //noinspection GradleDependency diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthSession.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthSession.kt index 00c43693dd..8a5c0216ca 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthSession.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthSession.kt @@ -65,21 +65,39 @@ internal fun AmplifyCredential.isValid(): Boolean { } internal fun AmplifyCredential.getCognitoSession( - exception: AuthException = SignedOutException() + exception: AuthException? = null ): AWSAuthSessionBehavior { - fun getCredentialsResult(awsCredentials: CognitoCredentials): AuthSessionResult = - with(awsCredentials) { + + fun getCredentialsResult( + awsCredentials: CognitoCredentials, + exception: AuthException? + ): AuthSessionResult { + if (exception != null && exception !is SignedOutException) { + return AuthSessionResult.failure(exception) + } + + return with(awsCredentials) { AWSCredentials.createAWSCredentials(accessKeyId, secretAccessKey, sessionToken, expiration) }?.let { AuthSessionResult.success(it) } ?: AuthSessionResult.failure(UnknownException("Failed to fetch AWS credentials.")) + } - fun getIdentityIdResult(identityId: String): AuthSessionResult { - return if (identityId.isNotEmpty()) AuthSessionResult.success(identityId) - else AuthSessionResult.failure(UnknownException("Failed to fetch identity id.")) + fun getIdentityIdResult(identityId: String, exception: AuthException?): AuthSessionResult { + return if (exception != null && exception !is SignedOutException) { + AuthSessionResult.failure(exception) + } else if (identityId.isNotEmpty()) { + AuthSessionResult.success(identityId) + } else { + AuthSessionResult.failure(UnknownException("Failed to fetch identity id.")) + } } - fun getUserSubResult(userPoolTokens: CognitoUserPoolTokens?): AuthSessionResult { + fun getUserSubResult(userPoolTokens: CognitoUserPoolTokens?, exception: AuthException?): AuthSessionResult { + if (exception != null && exception !is SignedOutException) { + return AuthSessionResult.failure(exception) + } + return try { AuthSessionResult.success(userPoolTokens?.accessToken?.let(SessionHelper::getUserSub)) } catch (e: Exception) { @@ -88,8 +106,13 @@ internal fun AmplifyCredential.getCognitoSession( } fun getUserPoolTokensResult( - cognitoUserPoolTokens: CognitoUserPoolTokens + cognitoUserPoolTokens: CognitoUserPoolTokens, + exception: AuthException? ): AuthSessionResult { + if (exception != null && exception !is SignedOutException) { + return AuthSessionResult.failure(exception) + } + return AuthSessionResult.success( AWSCognitoUserPoolTokens( accessToken = cognitoUserPoolTokens.accessToken, @@ -113,20 +136,20 @@ internal fun AmplifyCredential.getCognitoSession( "Cognito Identity not configured. Please check amplifyconfiguration.json file." ) ), - userSubResult = getUserSubResult(signedInData.cognitoUserPoolTokens), - userPoolTokensResult = getUserPoolTokensResult(signedInData.cognitoUserPoolTokens) + userSubResult = getUserSubResult(signedInData.cognitoUserPoolTokens, exception), + userPoolTokensResult = getUserPoolTokensResult(signedInData.cognitoUserPoolTokens, exception) ) is AmplifyCredential.UserAndIdentityPool -> AWSCognitoAuthSession( true, - identityIdResult = getIdentityIdResult(identityId), - awsCredentialsResult = getCredentialsResult(credentials), - userSubResult = getUserSubResult(signedInData.cognitoUserPoolTokens), - userPoolTokensResult = getUserPoolTokensResult(signedInData.cognitoUserPoolTokens) + identityIdResult = getIdentityIdResult(identityId, exception), + awsCredentialsResult = getCredentialsResult(credentials, exception), + userSubResult = getUserSubResult(signedInData.cognitoUserPoolTokens, exception), + userPoolTokensResult = getUserPoolTokensResult(signedInData.cognitoUserPoolTokens, exception) ) is AmplifyCredential.IdentityPool -> AWSCognitoAuthSession( false, - identityIdResult = getIdentityIdResult(identityId), - awsCredentialsResult = getCredentialsResult(credentials), + identityIdResult = getIdentityIdResult(identityId, exception), + awsCredentialsResult = getCredentialsResult(credentials, exception), userSubResult = AuthSessionResult.failure(SignedOutException()), userPoolTokensResult = AuthSessionResult.failure(SignedOutException()) ) @@ -137,8 +160,8 @@ internal fun AmplifyCredential.getCognitoSession( ) AWSCognitoAuthSession( true, - identityIdResult = getIdentityIdResult(identityId), - awsCredentialsResult = getCredentialsResult(credentials), + identityIdResult = getIdentityIdResult(identityId, exception), + awsCredentialsResult = getCredentialsResult(credentials, exception), userSubResult = AuthSessionResult.failure(userPoolException), userPoolTokensResult = AuthSessionResult.failure(userPoolException) ) diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt index 17acdf184e..bb23eaa7c6 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPlugin.kt @@ -1127,7 +1127,7 @@ internal class RealAWSCognitoAuthPlugin( when (val authZState = authState.authZState) { is AuthorizationState.Configured -> { authStateMachine.send(AuthorizationEvent(AuthorizationEvent.EventType.FetchUnAuthSession)) - _fetchAuthSession(onSuccess, onError) + _fetchAuthSession(onSuccess) } is AuthorizationState.SessionEstablished -> { val credential = authZState.amplifyCredential @@ -1147,7 +1147,7 @@ internal class RealAWSCognitoAuthPlugin( AuthorizationEvent(AuthorizationEvent.EventType.RefreshSession(credential)) ) } - _fetchAuthSession(onSuccess, onError) + _fetchAuthSession(onSuccess) } else { onSuccess.accept(credential.getCognitoSession()) } @@ -1171,7 +1171,7 @@ internal class RealAWSCognitoAuthPlugin( AuthorizationEvent(AuthorizationEvent.EventType.RefreshSession(amplifyCredential)) ) } - _fetchAuthSession(onSuccess, onError) + _fetchAuthSession(onSuccess) } else { onError.accept(InvalidStateException()) } @@ -1182,8 +1182,7 @@ internal class RealAWSCognitoAuthPlugin( } private fun _fetchAuthSession( - onSuccess: Consumer, - onError: Consumer + onSuccess: Consumer ) { val token = StateChangeListenerToken() authStateMachine.listen( @@ -1198,23 +1197,23 @@ internal class RealAWSCognitoAuthPlugin( authStateMachine.cancel(token) when (val error = authZState.exception) { is SessionError -> { - when (error.exception) { + when (val innerException = error.exception) { is SignedOutException -> { - onSuccess.accept(error.amplifyCredential.getCognitoSession(error.exception)) + onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException)) } is SessionExpiredException -> { - onSuccess.accept(AmplifyCredential.Empty.getCognitoSession(error.exception)) + onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException)) sendHubEvent(AuthChannelEventName.SESSION_EXPIRED.toString()) } is ServiceException -> { - onSuccess.accept(AmplifyCredential.Empty.getCognitoSession(error.exception)) + onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException)) } is NotAuthorizedException -> { - onSuccess.accept(AmplifyCredential.Empty.getCognitoSession(error.exception)) + onSuccess.accept(error.amplifyCredential.getCognitoSession(innerException)) } else -> { - val errorResult = UnknownException("Fetch auth session failed.", error) - onSuccess.accept(AmplifyCredential.Empty.getCognitoSession(errorResult)) + val errorResult = UnknownException("Fetch auth session failed.", innerException) + onSuccess.accept(error.amplifyCredential.getCognitoSession(errorResult)) } } } diff --git a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/actions/FetchAuthSessionCognitoActions.kt b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/actions/FetchAuthSessionCognitoActions.kt index 9b515a2803..29bdc97391 100644 --- a/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/actions/FetchAuthSessionCognitoActions.kt +++ b/aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/actions/FetchAuthSessionCognitoActions.kt @@ -136,11 +136,7 @@ internal object FetchAuthSessionCognitoActions : FetchAuthSessionActions { ) AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(exception)) } catch (e: Exception) { - val exception = SignedOutException( - recoverySuggestion = SignedOutException.RECOVERY_SUGGESTION_GUEST_ACCESS_POSSIBLE, - cause = e - ) - AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(exception)) + AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(e)) } logger.verbose("$id Sending event ${evt.type}") dispatcher.send(evt) @@ -173,11 +169,7 @@ internal object FetchAuthSessionCognitoActions : FetchAuthSessionActions { ) AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(exception)) } catch (e: Exception) { - val exception = SignedOutException( - recoverySuggestion = SignedOutException.RECOVERY_SUGGESTION_GUEST_ACCESS_POSSIBLE, - cause = e - ) - AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(exception)) + AuthorizationEvent(AuthorizationEvent.EventType.ThrowError(e)) } logger.verbose("$id Sending event ${evt.type}") dispatcher.send(evt) diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPluginFeatureTest.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPluginFeatureTest.kt index 5d44c28127..8f8921d868 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPluginFeatureTest.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/AWSCognitoAuthPluginFeatureTest.kt @@ -33,7 +33,9 @@ import com.amplifyframework.statemachine.codegen.data.DeviceMetadata import com.amplifyframework.statemachine.codegen.states.AuthState import featureTest.utilities.CognitoMockFactory import featureTest.utilities.CognitoRequestFactory +import featureTest.utilities.TimeZoneRule import featureTest.utilities.apiExecutor +import io.kotest.assertions.json.shouldEqualJson import io.mockk.clearAllMocks import io.mockk.coEvery import io.mockk.coVerify @@ -43,6 +45,7 @@ import io.mockk.mockkObject import io.mockk.mockkStatic import io.mockk.slot import java.io.File +import java.util.TimeZone import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import kotlin.reflect.full.callSuspend @@ -56,6 +59,7 @@ import kotlinx.serialization.json.Json import org.json.JSONObject import org.junit.After import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized @@ -63,6 +67,8 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) class AWSCognitoAuthPluginFeatureTest(private val testCase: FeatureTestCase) { + @Rule @JvmField val timeZoneRule = TimeZoneRule(TimeZone.getTimeZone("US/Pacific")) + lateinit var feature: FeatureTestCase private var apiExecutionResult: Any? = null @@ -114,6 +120,7 @@ class AWSCognitoAuthPluginFeatureTest(private val testCase: FeatureTestCase) { @Before fun setUp() { + // set timezone to be same as generated json from JsonGenerator Dispatchers.setMain(mainThreadSurrogate) feature = testCase sut.realPlugin = readConfiguration(feature.preConditions.`amplify-configuration`) @@ -189,9 +196,9 @@ class AWSCognitoAuthPluginFeatureTest(private val testCase: FeatureTestCase) { is Cognito -> verifyCognito(validation) is ExpectationShapes.Amplify -> { - val expectedResponse = validation.response - - assertEquals(expectedResponse, apiExecutionResult.toJsonElement()) + val expected = validation.response.toString() + val actual = apiExecutionResult.toJsonElement().toString() + actual shouldEqualJson expected } is ExpectationShapes.State -> { val getStateLatch = CountDownLatch(1) @@ -214,7 +221,7 @@ class AWSCognitoAuthPluginFeatureTest(private val testCase: FeatureTestCase) { coVerify { when (validation) { - is CognitoIdentity -> mockCognitoIdClient to mockCognitoIPClient::class + is CognitoIdentity -> mockCognitoIdClient to mockCognitoIdClient::class is CognitoIdentityProvider -> mockCognitoIPClient to mockCognitoIPClient::class }.apply { second.declaredFunctions.first { diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/JsonGenerator.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/JsonGenerator.kt index 7a7910613f..0f32d1d5dc 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/JsonGenerator.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/JsonGenerator.kt @@ -29,15 +29,22 @@ import com.amplifyframework.auth.cognito.featuretest.generators.testcasegenerato import com.amplifyframework.auth.cognito.featuretest.generators.testcasegenerators.SignOutTestCaseGenerator import com.amplifyframework.auth.cognito.featuretest.generators.testcasegenerators.SignUpTestCaseGenerator import com.amplifyframework.statemachine.codegen.states.AuthState +import org.junit.Ignore +import org.junit.Test interface SerializableProvider { val serializables: List + + // used to reset any global state changes during generation + fun tearDown() { + // default no op + } } /** * Top level generator for generating Json and writing to the destination directory */ -object JsonGenerator { +class JsonGenerator { private val providers: List = listOf( AuthStateJsonGenerator, ResetPasswordTestCaseGenerator, @@ -53,7 +60,26 @@ object JsonGenerator { FetchUserAttributesTestCaseGenerator, ) + @Ignore("Uncomment and run to clean feature test directory") + @Test + fun clean() { + cleanDirectory() + } + + @Ignore("Uncomment and run to clean feature test directory as well as generate json for feature tests.") + @Test + fun cleanAndGenerate() { + cleanDirectory() + generateJson() + } + + @Ignore("Uncomment and run to generate json for feature tests.") + @Test fun generate() { + generateJson() + } + + private fun generateJson() { providers.forEach { provider -> provider.serializables.forEach { when (it) { @@ -64,11 +90,7 @@ object JsonGenerator { } } } + provider.tearDown() } } } - -fun main() { - // cleanDirectory() - JsonGenerator.generate() -} diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/SerializationTools.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/SerializationTools.kt index 0b2c34d7fb..9342b46513 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/SerializationTools.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/SerializationTools.kt @@ -43,7 +43,7 @@ import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive -const val basePath = "aws-auth-cognito/src/test/resources/feature-test" +const val basePath = "src/test/resources/feature-test" fun writeFile(json: String, dirName: String, fileName: String) { val directory = File("$basePath/$dirName") diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/authstategenerators/AuthStateJsonGenerator.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/authstategenerators/AuthStateJsonGenerator.kt index d9dce558d4..18e8aac585 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/authstategenerators/AuthStateJsonGenerator.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/authstategenerators/AuthStateJsonGenerator.kt @@ -29,7 +29,6 @@ import com.amplifyframework.statemachine.codegen.states.AuthenticationState import com.amplifyframework.statemachine.codegen.states.AuthorizationState import com.amplifyframework.statemachine.codegen.states.SignInChallengeState import com.amplifyframework.statemachine.codegen.states.SignInState -import java.time.Instant import java.util.Date /** @@ -40,6 +39,9 @@ object AuthStateJsonGenerator : SerializableProvider { const val dummyToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1l" + "IiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU" + const val dummyToken2 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1l" + + "IiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8" + const val accessKeyId = "someAccessKey" const val secretAccessKey = "someSecretKey" const val identityId = "someIdentityId" @@ -51,7 +53,7 @@ object AuthStateJsonGenerator : SerializableProvider { private val signedInData = SignedInData( userId = userId, username = username, - signedInDate = Date.from(Instant.ofEpochSecond(0)), + signedInDate = Date(1707022800000), signInMethod = SignInMethod.ApiBased(SignInMethod.ApiBased.AuthType.USER_SRP_AUTH), cognitoUserPoolTokens = CognitoUserPoolTokens( idToken = dummyToken, @@ -61,20 +63,20 @@ object AuthStateJsonGenerator : SerializableProvider { ) ) + internal val signedInAmplifyCredential = AmplifyCredential.UserAndIdentityPool( + signedInData, + identityId = identityId, + AWSCredentials( + accessKeyId = accessKeyId, + secretAccessKey = secretAccessKey, + sessionToken = dummyToken, + expiration = expiration + ) + ) + private val signedInState = AuthState.Configured( AuthenticationState.SignedIn(signedInData, DeviceMetadata.Empty), - AuthorizationState.SessionEstablished( - AmplifyCredential.UserAndIdentityPool( - signedInData, - identityId = identityId, - AWSCredentials( - accessKeyId = accessKeyId, - secretAccessKey = secretAccessKey, - sessionToken = dummyToken, - expiration = expiration - ) - ) - ) + AuthorizationState.SessionEstablished(signedInAmplifyCredential) ) private val signedOutState = AuthState.Configured( diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/testcasegenerators/FetchAuthSessionTestCaseGenerator.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/testcasegenerators/FetchAuthSessionTestCaseGenerator.kt index 14b0ab3d9e..f529082ba2 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/testcasegenerators/FetchAuthSessionTestCaseGenerator.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/generators/testcasegenerators/FetchAuthSessionTestCaseGenerator.kt @@ -15,6 +15,8 @@ package com.amplifyframework.auth.cognito.featuretest.generators.testcasegenerators +import aws.sdk.kotlin.services.cognitoidentity.model.TooManyRequestsException +import aws.sdk.kotlin.services.cognitoidentityprovider.model.ResourceNotFoundException import com.amplifyframework.auth.AWSCognitoUserPoolTokens import com.amplifyframework.auth.AWSCredentials import com.amplifyframework.auth.cognito.AWSCognitoAuthSession @@ -31,33 +33,54 @@ import com.amplifyframework.auth.cognito.featuretest.generators.authstategenerat import com.amplifyframework.auth.cognito.featuretest.generators.toJsonElement import com.amplifyframework.auth.exceptions.ConfigurationException import com.amplifyframework.auth.exceptions.SignedOutException +import com.amplifyframework.auth.exceptions.UnknownException import com.amplifyframework.auth.result.AuthSessionResult +import java.util.TimeZone import kotlinx.serialization.json.JsonObject object FetchAuthSessionTestCaseGenerator : SerializableProvider { - private val mockedInitiateAuthResponse = MockResponse( + private val initialTimeZone = TimeZone.getDefault() + + init { + TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific")) + } + + override fun tearDown() { + TimeZone.setDefault(initialTimeZone) + } + + private val mockedRefreshInitiateAuthResponse = MockResponse( CognitoType.CognitoIdentityProvider, "initiateAuth", ResponseType.Success, mapOf( "authenticationResult" to mapOf( - "idToken" to AuthStateJsonGenerator.dummyToken, - "accessToken" to AuthStateJsonGenerator.dummyToken, + "idToken" to AuthStateJsonGenerator.dummyToken2, + "accessToken" to AuthStateJsonGenerator.dummyToken2, "refreshToken" to AuthStateJsonGenerator.dummyToken, "expiresIn" to 300 ) ).toJsonElement() ) - private val mockedIdentityIdResponse = MockResponse( + private val mockedRefreshGetIdResponse = MockResponse( CognitoType.CognitoIdentity, "getId", ResponseType.Success, mapOf("identityId" to "someIdentityId").toJsonElement() ) - private val mockedAWSCredentialsResponse = MockResponse( + private val mockedRefreshGetIdFailureResponse = MockResponse( + CognitoType.CognitoIdentity, + "getId", + ResponseType.Failure, + TooManyRequestsException.invoke { + message = "Error type: Client, Protocol response: (empty response)" + }.toJsonElement() + ) + + private val mockedRefreshGetAWSCredentialsResponse = MockResponse( CognitoType.CognitoIdentity, "getCredentialsForIdentity", ResponseType.Success, @@ -65,12 +88,30 @@ object FetchAuthSessionTestCaseGenerator : SerializableProvider { "credentials" to mapOf( "accessKeyId" to "someAccessKey", "secretKey" to "someSecretKey", - "sessionToken" to AuthStateJsonGenerator.dummyToken, + "sessionToken" to AuthStateJsonGenerator.dummyToken2, "expiration" to 2342134 ) ).toJsonElement() ) + private val mockedRefreshGetAWSCredentialsFailureResponse = MockResponse( + CognitoType.CognitoIdentity, + "getCredentialsForIdentity", + ResponseType.Failure, + TooManyRequestsException.invoke { + message = "Error type: Client, Protocol response: (empty response)" + }.toJsonElement() + ) + + private val mockedRefreshInitiateAuthFailureResponse = MockResponse( + CognitoType.CognitoIdentityProvider, + "initiateAuth", + ResponseType.Failure, + ResourceNotFoundException.invoke { + message = "Error type: Client, Protocol response: (empty response)" + }.toJsonElement() + ) + private val expectedSuccess = AWSCognitoAuthSession( isSignedIn = true, identityIdResult = AuthSessionResult.success("someIdentityId"), @@ -92,12 +133,77 @@ object FetchAuthSessionTestCaseGenerator : SerializableProvider { ) ).toJsonElement() + private val expectedRefreshSuccess = AWSCognitoAuthSession( + isSignedIn = true, + identityIdResult = AuthSessionResult.success("someIdentityId"), + awsCredentialsResult = AuthSessionResult.success( + AWSCredentials.createAWSCredentials( + AuthStateJsonGenerator.accessKeyId, + AuthStateJsonGenerator.secretAccessKey, + AuthStateJsonGenerator.dummyToken2, + AuthStateJsonGenerator.expiration + ) + ), + userSubResult = AuthSessionResult.success(AuthStateJsonGenerator.userId), + userPoolTokensResult = AuthSessionResult.success( + AWSCognitoUserPoolTokens( + accessToken = AuthStateJsonGenerator.dummyToken2, + idToken = AuthStateJsonGenerator.dummyToken2, + refreshToken = AuthStateJsonGenerator.dummyToken + ) + ) + ).toJsonElement() + + private val unknownRefreshException = UnknownException( + message = "Fetch auth session failed.", + cause = ResourceNotFoundException.invoke { } + ) + + private val identityRefreshException = UnknownException( + message = "Fetch auth session failed.", + cause = TooManyRequestsException.invoke { } + ) + + private val expectedRefreshFailure = AWSCognitoAuthSession( + isSignedIn = true, + identityIdResult = AuthSessionResult.failure(unknownRefreshException), + awsCredentialsResult = AuthSessionResult.failure(unknownRefreshException), + userSubResult = AuthSessionResult.failure(unknownRefreshException), + userPoolTokensResult = AuthSessionResult.failure(unknownRefreshException) + ).toJsonElement() + + private val expectedRefreshIdentityFailure = AWSCognitoAuthSession( + isSignedIn = true, + identityIdResult = AuthSessionResult.failure(identityRefreshException), + awsCredentialsResult = AuthSessionResult.failure(identityRefreshException), + userSubResult = AuthSessionResult.failure(identityRefreshException), + userPoolTokensResult = AuthSessionResult.failure(identityRefreshException) + ).toJsonElement() + private val apiReturnValidation = ExpectationShapes.Amplify( AuthAPI.fetchAuthSession, ResponseType.Success, expectedSuccess, ) + private val apiRefreshReturnValidation = ExpectationShapes.Amplify( + AuthAPI.fetchAuthSession, + ResponseType.Success, + expectedRefreshSuccess, + ) + + private val apiRefreshFailureReturnValidation = ExpectationShapes.Amplify( + AuthAPI.fetchAuthSession, + ResponseType.Success, + expectedRefreshFailure, + ) + + private val apiRefreshIdentityFailureReturnValidation = ExpectationShapes.Amplify( + AuthAPI.fetchAuthSession, + ResponseType.Success, + expectedRefreshIdentityFailure, + ) + private val baseCase = FeatureTestCase( description = "AuthSession object is successfully returned for UserAndIdentity Pool", preConditions = PreConditions( @@ -118,14 +224,52 @@ object FetchAuthSessionTestCaseGenerator : SerializableProvider { preConditions = PreConditions( "authconfiguration.json", "SignedIn_SessionEstablished.json", - mockedResponses = listOf(mockedInitiateAuthResponse) + mockedResponses = listOf( + mockedRefreshInitiateAuthResponse, + mockedRefreshGetIdResponse, + mockedRefreshGetAWSCredentialsResponse + ) ), api = API( name = AuthAPI.fetchAuthSession, params = JsonObject(emptyMap()), - JsonObject(emptyMap()) + options = mapOf("forceRefresh" to true).toJsonElement() ), - validations = listOf(apiReturnValidation) + validations = listOf(apiRefreshReturnValidation) + ) + + private val refreshFailureCase: FeatureTestCase = baseCase.copy( + description = "AuthSession object is successfully returned after failed refresh", + preConditions = PreConditions( + "authconfiguration.json", + "SignedIn_SessionEstablished.json", + mockedResponses = listOf(mockedRefreshInitiateAuthFailureResponse) + ), + api = API( + name = AuthAPI.fetchAuthSession, + params = JsonObject(emptyMap()), + options = mapOf("forceRefresh" to true).toJsonElement() + ), + validations = listOf(apiRefreshFailureReturnValidation) + ) + + private val refreshUserPoolSuccessIdentityPoolFailureCase = baseCase.copy( + description = "AuthSession object is successfully returned after failed identity refresh", + preConditions = PreConditions( + "authconfiguration.json", + "SignedIn_SessionEstablished.json", + mockedResponses = listOf( + mockedRefreshInitiateAuthResponse, + mockedRefreshGetIdFailureResponse, + mockedRefreshGetAWSCredentialsFailureResponse + ) + ), + api = API( + name = AuthAPI.fetchAuthSession, + params = JsonObject(emptyMap()), + options = mapOf("forceRefresh" to true).toJsonElement() + ), + validations = listOf(apiRefreshIdentityFailureReturnValidation) ) private val identityPoolCase: FeatureTestCase = baseCase.copy( @@ -193,5 +337,12 @@ object FetchAuthSessionTestCaseGenerator : SerializableProvider { ) ) - override val serializables: List = listOf(baseCase, refreshSuccessCase, identityPoolCase, userPoolCase) + override val serializables: List = listOf( + baseCase, + refreshSuccessCase, + refreshFailureCase, + refreshUserPoolSuccessIdentityPoolFailureCase, + identityPoolCase, + userPoolCase + ) } diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/serializers/CognitoExceptionSerializers.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/serializers/CognitoExceptionSerializers.kt index 0ba26b2a2f..0d3352e620 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/serializers/CognitoExceptionSerializers.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/featuretest/serializers/CognitoExceptionSerializers.kt @@ -18,9 +18,11 @@ package com.amplifyframework.auth.cognito.featuretest.serializers import aws.sdk.kotlin.services.cognitoidentity.model.CognitoIdentityException +import aws.sdk.kotlin.services.cognitoidentity.model.TooManyRequestsException import aws.sdk.kotlin.services.cognitoidentityprovider.model.CodeMismatchException import aws.sdk.kotlin.services.cognitoidentityprovider.model.CognitoIdentityProviderException import aws.sdk.kotlin.services.cognitoidentityprovider.model.NotAuthorizedException +import aws.sdk.kotlin.services.cognitoidentityprovider.model.ResourceNotFoundException import com.amplifyframework.auth.exceptions.UnknownException import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable @@ -38,6 +40,12 @@ private data class CognitoExceptionSurrogate( NotAuthorizedException::class.java.simpleName -> NotAuthorizedException.invoke { message = errorMessage } as T + ResourceNotFoundException::class.java.simpleName -> ResourceNotFoundException.invoke { + message = errorMessage + } as T + TooManyRequestsException::class.java.simpleName -> TooManyRequestsException.invoke { + message = errorMessage + } as T UnknownException::class.java.simpleName -> UnknownException(message = errorMessage ?: "") as T CodeMismatchException::class.java.simpleName -> CodeMismatchException.invoke { message = errorMessage @@ -56,6 +64,10 @@ private data class CognitoExceptionSurrogate( exception!!::class.java.simpleName, exception.message ) + is CognitoIdentityException -> CognitoExceptionSurrogate( + exception!!::class.java.simpleName, + exception.message + ) else -> { error("Exception for $exception not defined!") } diff --git a/aws-auth-cognito/src/test/java/featureTest/utilities/CognitoMockFactory.kt b/aws-auth-cognito/src/test/java/featureTest/utilities/CognitoMockFactory.kt index 954e800442..5f4dc44115 100644 --- a/aws-auth-cognito/src/test/java/featureTest/utilities/CognitoMockFactory.kt +++ b/aws-auth-cognito/src/test/java/featureTest/utilities/CognitoMockFactory.kt @@ -92,6 +92,10 @@ class CognitoMockFactory( this.challengeParameters = responseObject["challengeParameters"]?.let { parseChallengeParams(it as JsonObject) } + + this.authenticationResult = responseObject["authenticationResult"]?.let { + parseAuthenticationResult(it as JsonObject) + } } } } diff --git a/aws-auth-cognito/src/test/java/featureTest/utilities/TimeZoneRule.kt b/aws-auth-cognito/src/test/java/featureTest/utilities/TimeZoneRule.kt new file mode 100644 index 0000000000..846f1f8433 --- /dev/null +++ b/aws-auth-cognito/src/test/java/featureTest/utilities/TimeZoneRule.kt @@ -0,0 +1,17 @@ +package featureTest.utilities + +import java.util.TimeZone +import org.junit.rules.TestWatcher +import org.junit.runner.Description + +class TimeZoneRule(private val timeZone: TimeZone) : TestWatcher() { + private val previous: TimeZone = TimeZone.getDefault() + + override fun starting(description: Description) { + TimeZone.setDefault(timeZone) + } + + override fun finished(description: Description) { + TimeZone.setDefault(previous) + } +} diff --git a/aws-auth-cognito/src/test/resources/feature-test/states/SignedIn_SessionEstablished.json b/aws-auth-cognito/src/test/resources/feature-test/states/SignedIn_SessionEstablished.json index cfe6aab292..33dd7b4365 100644 --- a/aws-auth-cognito/src/test/resources/feature-test/states/SignedIn_SessionEstablished.json +++ b/aws-auth-cognito/src/test/resources/feature-test/states/SignedIn_SessionEstablished.json @@ -5,7 +5,7 @@ "signedInData": { "userId": "userId", "username": "username", - "signedInDate": 0, + "signedInDate": 1707022800000, "signInMethod": { "type": "SignInMethod.ApiBased", "authType": "USER_SRP_AUTH" @@ -25,7 +25,7 @@ "signedInData": { "userId": "userId", "username": "username", - "signedInDate": 0, + "signedInDate": 1707022800000, "signInMethod": { "type": "SignInMethod.ApiBased", "authType": "USER_SRP_AUTH" diff --git a/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_identity_refresh.json b/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_identity_refresh.json new file mode 100644 index 0000000000..b9f6f8d68d --- /dev/null +++ b/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_identity_refresh.json @@ -0,0 +1,95 @@ +{ + "description": "AuthSession object is successfully returned after failed identity refresh", + "preConditions": { + "amplify-configuration": "authconfiguration.json", + "state": "SignedIn_SessionEstablished.json", + "mockedResponses": [ + { + "type": "cognitoIdentityProvider", + "apiName": "initiateAuth", + "responseType": "success", + "response": { + "authenticationResult": { + "idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", + "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", + "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", + "expiresIn": 300 + } + } + }, + { + "type": "cognitoIdentity", + "apiName": "getId", + "responseType": "failure", + "response": { + "errorType": "TooManyRequestsException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + { + "type": "cognitoIdentity", + "apiName": "getCredentialsForIdentity", + "responseType": "failure", + "response": { + "errorType": "TooManyRequestsException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + } + ] + }, + "api": { + "name": "fetchAuthSession", + "params": { + }, + "options": { + "forceRefresh": true + } + }, + "validations": [ + { + "type": "amplify", + "apiName": "fetchAuthSession", + "responseType": "success", + "response": { + "accessToken": null, + "awsCredentialsResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "TooManyRequestsException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + "identityIdResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "TooManyRequestsException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + "isSignedIn": true, + "userPoolTokensResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "TooManyRequestsException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + "userSubResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "TooManyRequestsException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + } + } + } + ] +} \ No newline at end of file diff --git a/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_refresh.json b/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_refresh.json new file mode 100644 index 0000000000..c70b3d27c6 --- /dev/null +++ b/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_failed_refresh.json @@ -0,0 +1,73 @@ +{ + "description": "AuthSession object is successfully returned after failed refresh", + "preConditions": { + "amplify-configuration": "authconfiguration.json", + "state": "SignedIn_SessionEstablished.json", + "mockedResponses": [ + { + "type": "cognitoIdentityProvider", + "apiName": "initiateAuth", + "responseType": "failure", + "response": { + "errorType": "ResourceNotFoundException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + } + ] + }, + "api": { + "name": "fetchAuthSession", + "params": { + }, + "options": { + "forceRefresh": true + } + }, + "validations": [ + { + "type": "amplify", + "apiName": "fetchAuthSession", + "responseType": "success", + "response": { + "accessToken": null, + "awsCredentialsResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "ResourceNotFoundException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + "identityIdResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "ResourceNotFoundException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + "isSignedIn": true, + "userPoolTokensResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "ResourceNotFoundException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + }, + "userSubResult": { + "errorType": "UnknownException", + "errorMessage": "Fetch auth session failed.", + "recoverySuggestion": "See the attached exception for more details", + "cause": { + "errorType": "ResourceNotFoundException", + "errorMessage": "Error type: Client, Protocol response: (empty response)" + } + } + } + } + ] +} \ No newline at end of file diff --git a/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_refresh.json b/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_refresh.json index 111b384960..563d757582 100644 --- a/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_refresh.json +++ b/aws-auth-cognito/src/test/resources/feature-test/testsuites/fetchAuthSession/AuthSession_object_is_successfully_returned_after_refresh.json @@ -10,12 +10,33 @@ "responseType": "success", "response": { "authenticationResult": { - "idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", - "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", + "idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", + "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", "expiresIn": 300 } } + }, + { + "type": "cognitoIdentity", + "apiName": "getId", + "responseType": "success", + "response": { + "identityId": "someIdentityId" + } + }, + { + "type": "cognitoIdentity", + "apiName": "getCredentialsForIdentity", + "responseType": "success", + "response": { + "credentials": { + "accessKeyId": "someAccessKey", + "secretKey": "someSecretKey", + "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", + "expiration": 2342134 + } + } } ] }, @@ -24,6 +45,7 @@ "params": { }, "options": { + "forceRefresh": true } }, "validations": [ @@ -32,7 +54,7 @@ "apiName": "fetchAuthSession", "responseType": "success", "response": { - "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", + "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", "awsCredentialsResult": { "accessKeyId": "someAccessKey", "expiration": 2342134, @@ -41,13 +63,13 @@ "nanos": 0.0 }, "secretAccessKey": "someSecretKey", - "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU" + "sessionToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8" }, "identityIdResult": "someIdentityId", "isSignedIn": true, "userPoolTokensResult": { - "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", - "idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU", + "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", + "idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDI0LCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.po__hnGh2KF0ibpp--a2YZA9oBAKXc9BkX1IwdhvJp8", "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VySWQiLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiZXhwIjoxNTE2MjM5MDIyLCJvcmlnaW5fanRpIjoib3JpZ2luX2p0aSJ9.Xqa-vjJe5wwwsqeRAdHf8kTBn_rYSkDn2lB7xj9Z1xU" }, "userSubResult": "userId" diff --git a/core/src/main/java/com/amplifyframework/auth/exceptions/UnknownException.kt b/core/src/main/java/com/amplifyframework/auth/exceptions/UnknownException.kt index 337d716a02..25458ab2e9 100644 --- a/core/src/main/java/com/amplifyframework/auth/exceptions/UnknownException.kt +++ b/core/src/main/java/com/amplifyframework/auth/exceptions/UnknownException.kt @@ -26,7 +26,7 @@ open class UnknownException( cause: Throwable? = null ) : AuthException( message, - if (cause == null) RECOVERY_SUGGESTION_WITH_THROWABLE else RECOVERY_SUGGESTION_WITHOUT_THROWABLE, + if (cause != null) RECOVERY_SUGGESTION_WITH_THROWABLE else RECOVERY_SUGGESTION_WITHOUT_THROWABLE, cause ) { companion object { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c9d8a2eff8..6a0fc6e37c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,7 +27,7 @@ gson = "2.8.9" json = "20210307" jsonassert = "1.5.0" junit = "4.13.2" -kotest = "5.6.2" +kotest = "5.9.0" kotlin = "1.9.10" kotlin-serialization = "1.6.0" maplibre = "9.6.0" @@ -111,6 +111,7 @@ test-json = { module = "org.json:json", version.ref = "json" } test-jsonassert = { module = "org.skyscreamer:jsonassert", version.ref="jsonassert" } test-junit = { module = "junit:junit", version.ref = "junit" } test-kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } +test-kotest-assertions-json = { module = "io.kotest:kotest-assertions-json", version.ref = "kotest" } test-kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref="coroutines" } test-kotlin-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref="kotlin" } test-kotlin-kotlinTest = { module = "org.jetbrains.kotlin:kotlin-test", version.ref="kotlin" }