From 656385f0845578d5a6159785bde7bce970aadd9e Mon Sep 17 00:00:00 2001 From: Tuan Pham Date: Tue, 30 Jul 2024 09:56:08 -0500 Subject: [PATCH] chore(auth): update getCurrentUser to check for SessionExpiredException --- .../auth/cognito/RealAWSCognitoAuthPlugin.kt | 18 ++-- .../cognito/RealAWSCognitoAuthPluginTest.kt | 98 +++++++++++++++++++ 2 files changed, 110 insertions(+), 6 deletions(-) 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 bb23eaa7c..886ef257c 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 @@ -1818,12 +1818,18 @@ internal class RealAWSCognitoAuthPlugin( when (authState.authNState) { is AuthenticationState.SignedIn -> { GlobalScope.async { - val accessToken = getSession().userPoolTokensResult.value?.accessToken - accessToken?.run { - val userid = SessionHelper.getUserSub(accessToken) ?: "" - val username = SessionHelper.getUsername(accessToken) ?: "" - onSuccess.accept(AuthUser(userid, username)) - } ?: onError.accept(InvalidUserPoolConfigurationException()) + val userPoolToken = getSession().userPoolTokensResult + val userPoolTokenResultError = userPoolToken.error + if (userPoolTokenResultError != null && userPoolTokenResultError is SessionExpiredException) { + onError.accept(userPoolTokenResultError) + } else { + val accessToken = userPoolToken.value?.accessToken + accessToken?.run { + val userid = SessionHelper.getUserSub(accessToken) ?: "" + val username = SessionHelper.getUsername(accessToken) ?: "" + onSuccess.accept(AuthUser(userid, username)) + } ?: onError.accept(InvalidUserPoolConfigurationException()) + } } } is AuthenticationState.SignedOut -> { diff --git a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPluginTest.kt b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPluginTest.kt index 9ab7a83f2..b8085eb2b 100644 --- a/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPluginTest.kt +++ b/aws-auth-cognito/src/test/java/com/amplifyframework/auth/cognito/RealAWSCognitoAuthPluginTest.kt @@ -52,6 +52,7 @@ import com.amplifyframework.auth.AuthCodeDeliveryDetails import com.amplifyframework.auth.AuthDevice import com.amplifyframework.auth.AuthException import com.amplifyframework.auth.AuthSession +import com.amplifyframework.auth.AuthUser import com.amplifyframework.auth.AuthUserAttribute import com.amplifyframework.auth.AuthUserAttributeKey import com.amplifyframework.auth.MFAType @@ -59,6 +60,7 @@ import com.amplifyframework.auth.TOTPSetupDetails import com.amplifyframework.auth.cognito.exceptions.configuration.InvalidUserPoolConfigurationException import com.amplifyframework.auth.cognito.helpers.AuthHelper import com.amplifyframework.auth.cognito.helpers.SRPHelper +import com.amplifyframework.auth.cognito.helpers.SessionHelper import com.amplifyframework.auth.cognito.options.AWSCognitoAuthResendUserAttributeConfirmationCodeOptions import com.amplifyframework.auth.cognito.options.AWSCognitoAuthSignInOptions import com.amplifyframework.auth.cognito.options.AWSCognitoAuthUpdateUserAttributeOptions @@ -67,6 +69,7 @@ import com.amplifyframework.auth.cognito.options.AWSCognitoAuthVerifyTOTPSetupOp import com.amplifyframework.auth.cognito.options.AuthFlowType import com.amplifyframework.auth.cognito.usecases.ResetPasswordUseCase import com.amplifyframework.auth.exceptions.InvalidStateException +import com.amplifyframework.auth.exceptions.SessionExpiredException import com.amplifyframework.auth.exceptions.SignedOutException import com.amplifyframework.auth.options.AuthConfirmResetPasswordOptions import com.amplifyframework.auth.options.AuthConfirmSignUpOptions @@ -91,6 +94,7 @@ import com.amplifyframework.statemachine.codegen.data.DeviceMetadata import com.amplifyframework.statemachine.codegen.data.SignInMethod import com.amplifyframework.statemachine.codegen.data.SignedInData import com.amplifyframework.statemachine.codegen.data.UserPoolConfiguration +import com.amplifyframework.statemachine.codegen.errors.SessionError import com.amplifyframework.statemachine.codegen.states.AuthState import com.amplifyframework.statemachine.codegen.states.AuthenticationState import com.amplifyframework.statemachine.codegen.states.AuthorizationState @@ -235,6 +239,100 @@ class RealAWSCognitoAuthPluginTest { verify(exactly = 0) { onSuccess.accept(any()) } } + @Test + fun testGetCurrentUserSucceedsIfSignedIn() { + // GIVEN + val onSuccess = mockk>() + val onError = mockk>() + mockkObject(SessionHelper) + every { SessionHelper.getUsername(any()) } returns "username" + every { SessionHelper.getUserSub(any()) } returns "sub" + // WHEN + plugin.getCurrentUser(onSuccess, onError) + + // THEN + verify { onSuccess.accept(any()) } + verify(exactly = 0) { onError.accept(any()) } + } + + @Test + fun testGetCurrentUserFailsWithInvalidStateException() { + // GIVEN + val onSuccess = mockk>() + val onError = mockk>(relaxed = true) + + setupCurrentAuthState(authNState = AuthenticationState.NotConfigured()) + + // WHEN + plugin.getCurrentUser(onSuccess, onError) + + // THEN + verify(exactly = 0) { onSuccess.accept(any()) } + verify { onError.accept(InvalidStateException()) } + } + + @Test + fun testGetCurrentUserFailsWithSignedOutException() { + // GIVEN + val onSuccess = mockk>() + val onError = mockk>(relaxed = true) + + setupCurrentAuthState( + authNState = AuthenticationState.SignedOut(mockk()), + authZState = AuthorizationState.Configured() + ) + // WHEN + plugin.getCurrentUser(onSuccess, onError) + + // THEN + verify(exactly = 0) { onSuccess.accept(any()) } + verify { onError.accept(SignedOutException()) } + } + + @Test + fun testGetCurrentUserFailsWithExpiredSessionException() { + // GIVEN + val onGetCurrentUserSuccess = mockk>() + val onGetCurrentUserError = mockk>(relaxed = true) + val sessionExpiredException = SessionExpiredException() + val sessionError = SessionError(sessionExpiredException, credentials) + val authNState = AuthenticationState.SignedIn( + mockk { + every { username } returns "username" + }, + mockk() + ) + val authZState = AuthorizationState.Error(sessionError) + + setupCurrentAuthState( + authNState = authNState, + authZState = authZState + ) + + val sessionErrorState = mockk { + every { this@mockk.authNState } returns AuthenticationState.SignedIn( + mockk { + every { username } returns "username" + }, + mockk() + ) + every { this@mockk.authZState } returns AuthorizationState.Error(sessionError) + } + + every { + authStateMachine.listen(any(), captureLambda(), null) + } answers { + lambda<(AuthState) -> Unit>().invoke(sessionErrorState) + } + + // WHEN + plugin.getCurrentUser(onGetCurrentUserSuccess, onGetCurrentUserError) + + // THEN + verify(exactly = 0) { onGetCurrentUserSuccess.accept(any()) } + verify(timeout = 1000L) { onGetCurrentUserError.accept(sessionExpiredException) } + } + @Test fun testCustomSignInWithSRPSucceedsWithChallenge() { // GIVEN