amplify-js
amplify-js copied to clipboard
fetchAuthSession(): credentials / sessionToken Not Persisted Across Restarts
Before opening, please confirm:
- [X] I have searched for duplicate or closed issues and discussions.
- [X] I have read the guide for submitting bug reports.
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React Native
Amplify APIs
Authentication, GraphQL API, Storage
Amplify Version
v6
Amplify Categories
auth, storage, api
Backend
Amplify CLI
Environment information
# Put output below this line
System:
OS: macOS 14.4.1
CPU: (10) arm64 Apple M1 Max
Memory: 643.94 MB / 64.00 GB
Shell: 5.2.26 - /opt/homebrew/bin/bash
Binaries:
Node: 21.7.1 - /opt/homebrew/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 9.2.0 - /usr/local/bin/npm
Watchman: 2024.04.01.00 - /opt/homebrew/bin/watchman
Browsers:
Brave Browser: 124.1.65.123
Chrome: 124.0.6367.94
Safari: 17.4.1
npmGlobalPackages:
@aws-amplify/cli: 10.0.0
@graphql-inspector/cli: 3.4.0
appcenter-cli: 2.11.0
expo-cli: 5.4.12
gulp: 4.0.2
ios-deploy: 1.11.4
localtunnel: 1.9.1
lodash: 4.17.10
node-gyp: 3.6.2
npm-check-updates: 3.1.1
npm: 9.2.0
pm2: 5.1.2
serve: 10.0.2
serverless: 3.24.1
yarn-deduplicate: 1.0.2
Describe the bug
We're using React Native, and whenever the app restarts, a call to fetchAuthSession()
results in new credentials
(accessKeyId
, secretAccessKey
, & sessionToken
) being created, even if a session had been established on previous app run. This means that a network connection is required in order to start up the app and get the session.
To complicate things further, when the network connection is offline, fetchAuthSession()
will hang indefinitely. It doesn't appear that there is any way to configure a timeout for it?
In our case, we need to be able to detect these offline scenarios so that we can fall back to offline behavior. I realize that we can use the NetInfo package to try to detect when the app is offline, but we've found it not be the most reliable, so we prefer to make GraphQL requests and handle errors if those fail.
It's interesting to note that the idToken
(JWT) is retained through an app restart. In our case, all we're trying to fetch is the idToken
(for GraphQL client authentication), not the credentials
. But it doesn't seem there's any way for us to get the idToken
without refreshing the credentials
.
Expected behavior
fetchAuthSession()
should persist the session so that it can be re-used on subsequent app runs until expiration. Amplify v5 worked this way via the Auth.currentSession()
call, which no longer exists in v6. It appears that due to lack of session persistence, a call to fetchAuthSession()
on app launch will require a new session be obtained.
I realize that, even with session persistence, it's possible that on launch the session token may have expired and require a new session to be obtained. It would be great if there was some v6 equivalent to the v5 Auth.currentSession()
so that we could get the current session, if any, without requiring a call to the server.
Reproduction steps
- In a React Native app, call
fetchAuthSession()
on startup. - Launch the app to establish an auth session.
- Quit the app.
- Take the network connection offline.
- Launch the app again.
-
fetchAuthSession()
will attempt to fetch a session (credentials
) from the server, but since there is no network connection, it will hang indefinitely.
Code Snippet
// Put your code below this line.
await fetchAuthSession();
Log output
// Put your logs below this line
aws-exports.js
No response
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response
Hello, @brianlenz 👋. While this was opened as a bug, it looks like it's very similar to the feature request in #10393 regarding improved offline session management. Also, the behavior described here for the fetchAuthSession()
API after the app goes offline and gets restarted seems expected. When loading up (or reloading/restarting) an app, fetchAuthSession()
will attempt to get the credentials again due to them being persisted in-memory.
I'll mark this as a duplicate of #10393, but let us know if you have additional questions. Feel free to add any context, upvotes, etc. on that issue and track it for updates on this feature request too. Thanks!
@cwomack I appreciate the response! I can see how #10393 is related, but that's an old feature request from 2022 in the context of v5, whereas this is v6-specific. v5 supported what we're trying to do here, but v6 does not, so this feels more like a regression than a feature request.
I've been doing more testing, and it looks like the issue also applies to getCurrentUser()
. In v5, you could invoke Auth.currentAuthenticatedUser()
to get the current user without needing to hit the server, even if the session had expired. getCurrentUser()
, however, requires a session in order to complete, which means that if the session/token has expired, it will attempt a request to the server, so there is no way in v6 to ensure we can check a user is signed in to Amplify without an internet connection. This feels like a bug to me since it was possible in v5?
We are going to work around these limitations by reworking our logic, leveraging NetInfo and some internal state to determine if a user is signed in since we can no longer reliably rely on Amplify for that. To me, it feels like these improvements would still be warranted from an Amplify framework standpoint, but I'll leave it to you to determine how best to handle within the issues here since you know the project much better than I do 👍 Thanks!
Hi @cwomack @brianlenz , I am investigating an issue that might be related to the one currently being discussed. I've noticed in the code at this section: https://github.com/aws-amplify/amplify-js/blob/main/packages/auth/src/providers/cognito/credentialsProvider/credentialsProvider.ts#L119-L148 that when guest user credentials expire, the SDK sends a request with the existing Cognito Identity ID as a parameter to getCredentialsForIdentity. Interestingly, the identity ID is replaced with the one that is returned. In my local tests, however, the same identity ID is returned even after the guest user token expires (after 1 hour). Yet, the identity ID is replaced in the if condition on line 142. Can you clarify if the guest Cognito ID can change and under what circumstances? How can we reproduce this behavior? Please let me know if you need more information, or another issue should be opened.