Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Amplify Auth calls no longer fire after screen orientation change #2964

Closed
1 task done
cHunter791 opened this issue Dec 13, 2024 · 9 comments
Closed
1 task done

Amplify Auth calls no longer fire after screen orientation change #2964

cHunter791 opened this issue Dec 13, 2024 · 9 comments
Labels
bug Something isn't working pending-maintainer-response Issue is pending response from an Amplify team member

Comments

@cHunter791
Copy link

Before opening, please confirm:

Language and Async Model

Kotlin - Coroutines

Amplify Categories

Authentication

Gradle script dependencies

// Put output below this line
amplify = "2.23.0"
amplify-core = { group = "com.amplifyframework", name = "core-kotlin", version.ref = "amplify" }
amplify-cognito = { group = "com.amplifyframework", name = "aws-auth-cognito", version.ref = "amplify" }

implementation(libs.amplify.core)
implementation(libs.amplify.cognito)

Environment information

# Put output below this line
------------------------------------------------------------
Gradle 8.9
------------------------------------------------------------

Build time:    2024-07-11 14:37:41 UTC
Revision:      d536ef36a19186ccc596d8817123e5445f30fef8

Kotlin:        1.9.23
Groovy:        3.0.21
Ant:           Apache Ant(TM) version 1.10.13 compiled on January 4 2023
Launcher JVM:  17.0.13 (Homebrew 17.0.13+0)
Daemon JVM:    /opt/homebrew/Cellar/openjdk@17/17.0.13/libexec/openjdk.jdk/Contents/Home (no JDK specified, using current Java home)
OS:            Mac OS X 15.1.1 aarch64


Please include any relevant guides or documentation you're referencing

https://docs.amplify.aws/android/build-a-backend/auth/set-up-auth/

Describe the bug

We have code in our MainActivity on activity create to check a user's auth status using Amplify (fetchAuthSession) to decide where to navigate them initially. This works on initial app open and returning from the background. The MainActivity is locked to portrait orientation however we have a video player in the app that will force the MainActivity into landscape mode. Doing this destroys and recreates the MainActivity.

We noticed that after a user navigates to the video player and then back to the original screen, when we attempt to check their auth status to navigate them to correct page the fetchAuthSession call to Amplify never completes. Digging into the AWSCognitoAuthPlugin code we see the fetchAuthSession coroutine being added to the queueChannel but then it never gets consumed.

    override fun fetchAuthSession(
        options: AuthFetchSessionOptions,
        onSuccess: Consumer<AuthSession>,
        onError: Consumer<AuthException>
    ) {
        queueChannel.trySend(
            pluginScope.launch(start = CoroutineStart.LAZY) {
                try {
                    val result = queueFacade.fetchAuthSession(options)
                    pluginScope.launch { onSuccess.accept(result) }
                } catch (e: Exception) {
                    pluginScope.launch { onError.accept(e.toAuthException()) }
                }
            }
        )
    }

Reproduction steps (if applicable)

No response

Code Snippet

MainActivity

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    lifecycleScope.launch {
        userAuthStateRepository.isUserLoggedIn()
        // handle navigation logic based on result of above call
    }
}

UserAuthStateRepository

suspend fun isUserLoggedIn(): Boolean {
    return try {
         (auth.fetchAuthSession() as AWSCognitoAuthSession).userPoolTokensResult.value?.idToken != null
    } catch (exception: AuthException) {
        false
    }
}

Log output

// Put your logs below this line


amplifyconfiguration.json

No response

GraphQL Schema

// Put your schema below this line

Additional information and screenshots

As a workaround we specify the configuration changes we will handle ourselves for the MainActivity to include orientation change. This means that the activity will not be destroyed and recreated and we no longer run into this issue. However I do not believe we should have to do this to get around this issue. Amplify calls should continue to be ran even if the Activity is destroyed and recreated

<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize"
    android:exported="true"
    android:launchMode="singleTask"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="adjustPan">
@github-actions github-actions bot added pending-triage Issue is pending triage pending-maintainer-response Issue is pending response from an Amplify team member labels Dec 13, 2024
@tylerjroach
Copy link
Member

Thank you for providing details for us to replicate. We will look into this.

As a way to unblock yourself, I would also look into using a MVVM pattern where fetchAuthSession is called within the ViewModel which will survive orientation changes. You can then observe on an isLoggedIn value from within the activity.

@tylerjroach tylerjroach added the bug Something isn't working label Dec 13, 2024
@github-actions github-actions bot removed pending-maintainer-response Issue is pending response from an Amplify team member pending-triage Issue is pending triage labels Dec 13, 2024
@cHunter791
Copy link
Author

Thank you for providing details for us to replicate. We will look into this.

As a way to unblock yourself, I would also look into using a MVVM pattern where fetchAuthSession is called within the ViewModel which will survive orientation changes. You can then observe on an isLoggedIn value from within the activity.

Thanks, we did also put in some caching for the value to avoid having to call fetchAuthSession however the issue we're seeing still occurs elsewhere in the app when we are forced to use fetchAuthSession e.g. accessing the access token to send to our backend. The call will hang there as well, not only in the MainActivity call location

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 13, 2024
@tylerjroach
Copy link
Member

tylerjroach commented Dec 13, 2024

@cHunter791 I don't doubt that you are running into a lockup, as we had a very similar case that was previously fixed #2822.

I am, however, unable to replicate it with the description you have given.

class RootActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        lifecycleScope.launch {
            Log.d("RootActivity", "isLoggedIn ${UserRepository.isUserLoggedIn()}")
        }

    }
}

object UserRepository {
    suspend fun isUserLoggedIn(): Boolean {
        return try {
            (Amplify.Auth.fetchAuthSession() as AWSCognitoAuthSession).userPoolTokensResult.value?.idToken != null
        } catch (exception: AuthException) {
            false
        }
    }
}

After each rotation, I am seeing isLoggedIn true printed in my logs. Is there any way you could provide a sample app that can recreate this scenario, or suggest a change to the snippet I provided that would cause the deadlock.

I also want to make sure that you are initializing Amplify within the extended Application class, not the Activity. Can you confirm this?

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 13, 2024
@cHunter791
Copy link
Author

@tylerjroach we are initializing Amplify in the extended Application class yes. I will need to see if I can get some time to put together a sample app. I'll look into doing this.

One thing we are doing differently that your code snippet is injecting the Amplify.Auth instance into our UserRepository so we can mock it for our unit tests

class UserAuthStateRepository(
    private val auth: Auth,
)

Could this potentially cause an issue?

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 16, 2024
@tylerjroach
Copy link
Member

That should not cause an issue. We will be on the lookout for a sample app!

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 16, 2024
@cHunter791
Copy link
Author

@tylerjroach I have spent this afternoon attempting to recreate in a sample application with no success. Like you, after performing screen rotations the Amplify calls complete successfully.

Here is some other information for how we are using Amplify in our application, in case you can spot anything that might odd

Originally we would call fetchAuthSession on app start once and store the access token locally. If the access token expires we'd call fetchAuthSession again to update with the refreshed token. We moved away from this to avoid storing access tokens in Shared Preferences and instead directly access Amplify for the token each time. Since making this change we have started seeing this issue. Even adding in-memory caching, we see this issue.

We are moving towards using the Kotlin Amplify functions for Coroutine support, existing Amplify functions in the app are using the Callbacks approach. I noticed in the Application we are using com.amplifyframework.core.Amplify instead of com.amplifyframework.kotlin.core.Amplify when initializing the application but using either in the sample application caused no issues. However we are not mixing and matching callbacks and coroutines

We are requesting the access token in the following places when we perform a screen rotation change. Could we be accessing Amplify too many times? I checked logs and we are accessing Amplify 9 times after screen rotation for fetchAuthSession
a. MainActivity onCreate to determine the start navigation location
b. MainActivity onResume to refresh data
c. OkHttpInterceptor for every web call we retrieve the access token to attach to the Authorization header

If there is nothing that comes to mind we can close this issue as we cannot reproduce and we have a workaround

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 16, 2024
@tylerjroach
Copy link
Member

All that you have just stated sounds fine. I am not sure what scenario is resulting in a lockup, but if you have a sufficient workaround and we are not able to replicate, you can close the issue if you are no longer concerned. If anything changes, please let us know

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 16, 2024
@cHunter791
Copy link
Author

Will do, thanks again for your time and help!

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify team member label Dec 16, 2024
Copy link
Contributor

This issue is now closed. Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working pending-maintainer-response Issue is pending response from an Amplify team member
Projects
None yet
Development

No branches or pull requests

2 participants