aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.4k stars 2.11k forks source link

Sessions aren't persisting between app reloads in React Native #4351

Closed CodySwannGT closed 4 years ago

CodySwannGT commented 4 years ago

Describe the bug Sessions aren't persisting between app reloads in Expo

To Reproduce Steps to reproduce the behavior:

  1. Open the app
  2. Sign in
  3. Reload the app
  4. See error

Expected behavior User still signed in

Sample code

import React, { useState, useEffect } from 'react';
import Amplify from 'aws-amplify';
import Auth from '@aws-amplify/auth'
import awsmobile from './aws-exports';
import { withAuthenticator } from 'aws-amplify-react-native';
import { Text } from 'react-native-elements';

const Test = () => console.log("OK OK OK HERE") || <Text>Hi</Text>

const TestWithAuth = withAuthenticator(Test)

Amplify.configure(awsmobile);

const App = () => {
  useEffect(() => {
    Auth.currentAuthenticatedUser()
      .then(cognitoUser => console.log(cognitoUser))
      .catch(err => console.log(err) || console.log(null))
  }, []);

  return (
    <TestWithAuth />
  );
}

export default App
bthomas16 commented 4 years ago

I have been seeing the exact same issue. Glad to see this bug is being filed. Using Expo + React Native, I thought I had messed up in my soon to be production codebase. So I just created a new, basic, bare-bones application using Expo + React Native + Amplify (Cognito) and still cannot persist state when refreshing the application

APP.JS

import React from 'react';
import { StyleSheet, Text, View, AsyncStorage } from 'react-native';
import Amplify, {Auth, Analytics} from 'aws-amplify';
import aws_exports from './aws-exports';
import { withAuthenticator } from 'aws-amplify-react-native'

Amplify.configure(aws_exports);
Analytics.disable()

class App extends React.Component {
  render() {
    return (
        <View style={styles.container}>
          <Text>Open up App.js to start working on your app!</Text>
        </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

export default  withAuthenticator(App);

AWS-EXPORTS

// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "us-east-2",
    "aws_cognito_identity_pool_id": "us-east-2:xxxxxxcxcxcxcxcxcxcxcx",
    "aws_cognito_region": "us-east-2",
    "aws_user_pools_id": "us-east-x_xxxxxxxxxx",
    "aws_user_pools_web_client_id": "7rh4ap4nxxxxxxxxxxxxx",
    "oauth": {}
};

export default awsmobile;
ctomichael commented 4 years ago

I was having this myself and was tearing my hair out trying to figure it out. I discovered that the current amplify sdk is using the old version of async-storage from before they broke it out into being a react-native community package. When I inspected what was in the async-storage, I found the tokens would intermittently disappear, which would cause my session to break sometimes. I implemented a replacement storage service and passed that into my Amplify.configure Auth object. Note that I'm explicitly importing the react-native-community/async-storage package in the StorageService. Code below:


import AsyncStorage from '@react-native-community/async-storage'

/*
 * Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
 * the License. A copy of the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
 * and limitations under the License.
 */

const MEMORY_KEY_PREFIX = '@StorageService:'
let dataMemory: any = {}

/** @class */
export class MemoryStorageNew {
  static syncPromise: Promise<any> | null = null
  /**
   * This is used to set a specific item in storage
   * @param {string} key - the key for the item
   * @param {object} value - the value
   * @returns {string} value that was set
   */
  static setItem(key: any, value: any) {
    AsyncStorage.setItem(MEMORY_KEY_PREFIX + key, value)
    dataMemory[key] = value
    return dataMemory[key]
  }

  /**
   * This is used to get a specific key from storage
   * @param {string} key - the key for the item
   * This is used to clear the storage
   * @returns {string} the data item
   */
  static getItem(key: string) {
    return Object.prototype.hasOwnProperty.call(dataMemory, key)
      ? dataMemory[key]
      : undefined
  }

  /**
   * This is used to remove an item from storage
   * @param {string} key - the key being set
   * @returns {string} value - value that was deleted
   */
  static removeItem(key: string) {
    AsyncStorage.removeItem(MEMORY_KEY_PREFIX + key)
    return delete dataMemory[key]
  }

  /**
   * This is used to clear the storage
   * @returns {string} nothing
   */
  static clear() {
    dataMemory = {}
    return dataMemory
  }

  /**
   * Will sync the MemoryStorage data from AsyncStorage to storageWindow MemoryStorage
   * @returns {void}
   */
  static sync() {
    if (!MemoryStorageNew.syncPromise) {
      MemoryStorageNew.syncPromise = new Promise((res, rej) => {
        AsyncStorage.getAllKeys((errKeys, keys) => {
          if (errKeys) rej(errKeys)
          const memoryKeys = keys!.filter(key =>
            key.startsWith(MEMORY_KEY_PREFIX)
          )
          AsyncStorage.multiGet(memoryKeys, (err, stores) => {
            if (err) rej(err)
            stores!.map((result, index, store) => {
              const key = store[index][0]
              const value = store[index][1]
              const memoryKey = key.replace(MEMORY_KEY_PREFIX, '')
              dataMemory[memoryKey] = value
            })
            res()
          })
        })
      })
    }
    return MemoryStorageNew.syncPromise
  }
}

/** @class */
export default class StorageHelper {
  private storageWindow: any
  /**
   * This is used to get a storage object
   * @returns {object} the storage
   */
  constructor() {
    this.storageWindow = MemoryStorageNew
  }

  /**
   * This is used to return the storage
   * @returns {object} the storage
   */
  getStorage() {
    return this.storageWindow
  }
}
import { MemoryStorageNew } from './StorageService'
Amplify.configure({
    Auth: {
      ...
      storage: MemoryStorageNew,
    },
  })
bthomas16 commented 4 years ago

I will definitely try this shortly and update with my progress. But this seems like extra steps (granted, temporarily) that shouldn't be needed for an otherwise "out of the box" solution to Auth. Either way, thanks for doing the deep dive that was in my near future :).

A fallback solution seems to be to rollback to the last version of Amplify before this bug was introduced

Erlix322 commented 4 years ago

I will definitely try this shortly and update with my progress. But this seems like extra steps (granted, temporarily) that shouldn't be needed for an otherwise "out of the box" solution to Auth. Either way, thanks for doing the deep dive that was in my near future :).

A fallback solution seems to be to rollback to the last version of Amplify before this bug was introduced

which version of amplify is using the working storage? I'll most likely downgrade because I use expo and will not link the community storage

EDIT

For those who are using Expo and don't want to eject for now it is enough to apply the solution from @district-michael above and replace the line:

import AsyncStorage from '@react-native-community/async-storage'

with

import {AsyncStorage} from 'react-native'

and override your Configuration

Amplify.configure({
  Auth:{
    region: ...,    
    userPoolId: ...,
    userPoolWebClientId: ...,
    storage: MemoryStorageNew
  }
});
anthonyhumphreys commented 4 years ago

@bthomas16 thank you so much for this patch - saved me from going insane, I thought I'd broken my build...

bthomas16 commented 4 years ago

For all those interested, @district-michael is the hero here (along with @Erlix322). That said, I tried modifying his solution to fit vanilla Javascript implementations, this proved difficult and not worth the effort. And after creating a new bare-bones applications with Typescript, Michael's solution worked like a charm. Typescript is becoming a best practice anyways, so I am choosing to see this as a positive for my project's future development

anthonyhumphreys commented 4 years ago

@bthomas16 i used http://www.typescriptlang.org/play/ to get the JS because I'm lazy and wanted to move on with the build :p

Here is the transpiled (if that is the correct term between TS and JS??):

import AsyncStorage from '@react-native-community/async-storage';
/*
 * Copyright 2017-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
 * the License. A copy of the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
 * and limitations under the License.
 */
const MEMORY_KEY_PREFIX = '@StorageService:';
let dataMemory = {};
/** @class */
export class MemoryStorageNew {
  /**
   * This is used to set a specific item in storage
   * @param {string} key - the key for the item
   * @param {object} value - the value
   * @returns {string} value that was set
   */
  static setItem(key, value) {
    AsyncStorage.setItem(MEMORY_KEY_PREFIX + key, value);
    dataMemory[key] = value;
    return dataMemory[key];
  }
  /**
   * This is used to get a specific key from storage
   * @param {string} key - the key for the item
   * This is used to clear the storage
   * @returns {string} the data item
   */
  static getItem(key) {
    return Object.prototype.hasOwnProperty.call(dataMemory, key)
      ? dataMemory[key]
      : undefined;
  }
  /**
   * This is used to remove an item from storage
   * @param {string} key - the key being set
   * @returns {string} value - value that was deleted
   */
  static removeItem(key) {
    AsyncStorage.removeItem(MEMORY_KEY_PREFIX + key);
    return delete dataMemory[key];
  }
  /**
   * This is used to clear the storage
   * @returns {string} nothing
   */
  static clear() {
    dataMemory = {};
    return dataMemory;
  }
  /**
   * Will sync the MemoryStorage data from AsyncStorage to storageWindow MemoryStorage
   * @returns {void}
   */
  static sync() {
    if (!MemoryStorageNew.syncPromise) {
      MemoryStorageNew.syncPromise = new Promise((res, rej) => {
        AsyncStorage.getAllKeys((errKeys, keys) => {
          if (errKeys) rej(errKeys);
          const memoryKeys = keys.filter(key =>
            key.startsWith(MEMORY_KEY_PREFIX),
          );
          AsyncStorage.multiGet(memoryKeys, (err, stores) => {
            if (err) rej(err);
            stores.map((result, index, store) => {
              const key = store[index][0];
              const value = store[index][1];
              const memoryKey = key.replace(MEMORY_KEY_PREFIX, '');
              dataMemory[memoryKey] = value;
            });
            res();
          });
        });
      });
    }
    return MemoryStorageNew.syncPromise;
  }
}
MemoryStorageNew.syncPromise = null;
/** @class */
export default class StorageHelper {
  /**
   * This is used to get a storage object
   * @returns {object} the storage
   */
  constructor() {
    this.storageWindow = MemoryStorageNew;
  }
  /**
   * This is used to return the storage
   * @returns {object} the storage
   */
  getStorage() {
    return this.storageWindow;
  }
}

I've actually got a branch on my project to move over to TS now - but for the MVP we're sticking with JS. That's gonna be the mother of all PR's......

Also thanks @district-michael and @erlix322 :) I mistagged before

CodySwannGT commented 4 years ago

This did it for me with one minor edit since we're on managed Expo

import { AsyncStorage } from 'react-native';

instead of (which requires linking)

import AsyncStorage from '@react-native-community/async-storage';
anthonyhumphreys commented 4 years ago

Ah true, sorry!


From: Cody Swann notifications@github.com Sent: Thursday, November 7, 2019 9:53:20 PM To: aws-amplify/amplify-js amplify-js@noreply.github.com Cc: Humphreys, Anthony anthony.humphreys@lancaster.ac.uk; Comment comment@noreply.github.com Subject: [External Sender] Re: [aws-amplify/amplify-js] Sessions aren't persisting between app reloads in React Native (#4351)

This email originated from outside of the University. Do not click links or open attachments unless you recognise the sender and know the content is safe.

This did it for me with one minor edit since we're on managed Expo

import { AsyncStorage } from 'react-native';

instead of (which requires linking)

import AsyncStorage from '@react-native-community/async-storage';

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Faws-amplify%2Famplify-js%2Fissues%2F4351%3Femail_source%3Dnotifications%26email_token%3DACP2QUX2LJIY2HPUQKCGDLTQSSE5BA5CNFSM4JJNMPP2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDN6RRI%23issuecomment-551282885&data=02%7C01%7Canthony.humphreys%40lancaster.ac.uk%7C384ad2188fad4a7b5a2d08d763cce97d%7C9c9bcd11977a4e9ca9a0bc734090164a%7C1%7C0%7C637087604052185062&sdata=88vQvvuF1zrXn6TTdtbDH1LH5pr31KryWXRZzj55enU%3D&reserved=0, or unsubscribehttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FACP2QUVU3ZQVCCWEXKVTX5TQSSE5BANCNFSM4JJNMPPQ&data=02%7C01%7Canthony.humphreys%40lancaster.ac.uk%7C384ad2188fad4a7b5a2d08d763cce97d%7C9c9bcd11977a4e9ca9a0bc734090164a%7C1%7C0%7C637087604052185062&sdata=q6I84ltRiqxPARPeSXVVm4Skl7vWoUB5zkBirLccEks%3D&reserved=0.

bthomas16 commented 4 years ago

Now that we have a workaround... great. But what actually happened to cause this and when will we be able to rely on Amplify without this work around?

hiren0412 commented 4 years ago

We are Facing same issue.Here is the Steps that i found the issue with React-native amplify library.

1.) WORKING FLOW:

2.) FLOW WITH ISSUE:

After Reloading the App the Session is not maintained. Also Auth.currentSession() is also returns null value.

3.)EXPECTED BEHAVIOUR

kgpasta commented 4 years ago

Thank you @district-michael and @Erlix322 for the solutions, worked for me. If you have federated providers (like Facebook and Google) you additionally need to do the following:

const refreshToken = async () => {
    await MemoryStorageNew.sync();
    const federatedInfo = MemoryStorageNew.getItem("aws-amplify-federatedInfo");
    const federatedInfoParsed = JSON.parse(federatedInfo);
    const { token } = federatedInfoParsed;

    return {
        token,
    };
};

and then in your configure:

Auth.configure({
        refreshHandlers: {
            google: refreshToken,
            facebook: refreshToken
        },
        storage: MemoryStorageNew
    });
Ashish-Nanda commented 4 years ago

Hi,

I initially thought that the issue here would be related to Async Storage deprecation, and opened the PR #4402 to migrate to the community version. However after looking at the issue description and comments, it seems the issue occurs on Expo as well, where RN is still <0.60. Also the workaround suggested by @Erlix322 and @CodySwannGT for managed Expo still uses Async storage.

Additionally even in the case of stand alone React Native apps as mentioned in this comment, the issue was not observed on even 0.61.4 with a previous version of Amplify. So it seems to me the issue might be with some commit in the last 1 month, rather than Async Storage deprecation? (it is still part of RN but would be removed soon)

We are still investigating the cause but let us know if that makes sense. Would appreciate your insights and suggestions.

Additionally if we switch to the community edition of Async Storage, it seems to break managed expo users as they will need to eject to use the native module until Expo themselves includes it. Here is a thread related to that. Expo users let us know your thoughts on us switching to the community version and ejecting your app, or using previous versions of Amplify until Expo supports it for managed apps.

CodySwannGT commented 4 years ago

As improved ejected expo is, we still avoid it at all cost, so we would vote very strongly against forcing us to eject.

Ashish-Nanda commented 4 years ago

Most likely expo will include it in the SDK. Seems to be in progress as well. https://expo.canny.io/feature-requests/p/continued-support-for-asyncstorage

dantasfiles commented 4 years ago

@Ashish5591

The Auth package uses StorageHelper().getStorage() to determine where to store the user data.

For web, it's supposed to use window.localStorage or, failing that, in-memory storage. For react native, it's supposed to use AsyncStorage.

There was an issue in core/package.json that prevented the correct react native versions of ClientDevice (this affects Analytics and Push Notifications), RNComponents, and StorageHelper from being used correctly.

You can test this with the code

  useEffect(() => {
    AsyncStorage.clear();
    const storage = new StorageHelper().getStorage();
    storage.setItem('test1', 'test2');
    console.log('storage.getItem(test1) = ', storage.getItem('test1'));
    AsyncStorage.getAllKeys().then(async keys => {
      console.log('AsyncStorage.getAllKeys = ', keys);
    });
  }, []);

In the aws-amplify@latest (1.2.4), the result is

 LOG  storage.getItem(test1) =  test2
 LOG  AsyncStorage.getAllKeys =  []

In aws-amplify@next (2.1.0), the result is

 LOG  storage.getItem(test1) =  test2
 LOG  AsyncStorage.getAllKeys =  ["@MemoryStorage:test1"]

The reason the workaround of creating a MemoryStorage class to be passed into the Auth config worked, is that it basically manually replaced the incorrect web version of StorageHelper with a copy of the react native version.

Ashish-Nanda commented 4 years ago

@dantasfiles Thanks for your detailed response!

Looking into that further, the fix for the react native source files not being included made it into our master branch but seems to not have been included in a new 1.x.x release.

It went straight to 2.x.x which needs to be installed through aws-amplify@next as you said and people using @latest would not have picked up the change.

Installing aws-amplify@next should resolve the issue:

npm install aws-amplify@next

That said we will also do a release to @latest with the fix early next week.

gvankeerberghen commented 4 years ago

@Ashish-Nanda did this fix make it into a release to @latest yet? I checked in the PRs and releases but honestly couldn't find much in the amount of them.

@dantasfiles Thanks for your detailed response!

Looking into that further, the fix for the react native source files not being included made it into our master branch but seems to not have been included in a new 1.x.x release.

It went straight to 2.x.x which needs to be installed through aws-amplify@next as you said and people using @latest would not have picked up the change.

Installing aws-amplify@next should resolve the issue:

npm install aws-amplify@next

That said we will also do a release to @latest with the fix early next week.

KristineTrona commented 4 years ago

I've just updated to the newest release of 2.2.0 and still experiencing the same issue - refreshing the projct clears the cognito user from the storage.

ajdinahmetovic commented 4 years ago

Tested now, still not working. Please fix.

Ashish-Nanda commented 4 years ago

Hi @gvankeerberghen the fix is in @latest.

@KristineTrona and @ajdinahmetovic I just tested with 2.2.0 and it worked fine as far as I can tell. This was with a standalone RN app created through the RN cli and not expo. RN version is 0.61.4

Could you tell me more about your setup? Are you using expo or stand alone RN and what is in your package.json?

Looking at this comment it seems 2.1.0 was working for other users as well.

If any other users have tried @latest please let us know if the issue is resolved for you.

KristineTrona commented 4 years ago

@Ashish-Nanda My setup is exactly the same and after testing again - it is indeed fixed. :) Perhaps I hadn't rebuilt the project since the aws-amplify update.

ericclemmons commented 4 years ago

@KristineTrona Thanks for the validation!

@ajdinahmetovic Can you do another upgrade to @latest & let us know if it's been resolved for you and, if not, more about your reproduction steps?

ajdinahmetovic commented 4 years ago

@ericclemmons Hey, after upgrade it works for me. Thank you 🙂

Ashish-Nanda commented 4 years ago

Thanks for confirming that the fix works for you. Since the problem is resolved I'm going to go ahead and close out this issue.

markmckim commented 4 years ago

@KristineTrona - How did you finally get it to work? I've updated to 2.2.0, deleted node_modules, did a fresh pod install etc. etc. and I am still seeing the issue. Thanks!

mikedizon commented 4 years ago

@KristineTrona - How did you finally get it to work? I've updated to 2.2.0, deleted node_modules, did a fresh pod install etc. etc. and I am still seeing the issue. Thanks!

If using yarn -- did you delete the yarn.lock file?

markmckim commented 4 years ago

I tried deleting package-lock.json and made no difference

ericclemmons commented 4 years ago

@markmckim What does npm view aws-amplify return for you?

markmckim commented 4 years ago

amplify@0.0.11 | MIT | deps: none | versions: 11
Amplify is a wrapper around the NodeJS http packages to help make development easier.

dist
.tarball: https://registry.npmjs.org/amplify/-/amplify-0.0.11.tgz
.shasum: fd81c7068c862823f2508b8f3c650eb76753f58c

maintainers:
- chafnan <chafnan@gmail.com>

dist-tags:
latest: 0.0.11  

published over a year ago by chafnan <chafnan@gmail.com>

Although this seems weird? My package.json has 2.2.0

ericclemmons commented 4 years ago

That's weird. Did you run npm view aws-amplify or npm view amplify?

The amplify package is owned by someone else: https://github.com/chafnan/amplify

(I've made this mistake a lot 😉)

In fact, a better command would be:

npx envinfo --system --binaries --browsers --npmPackages --npmGlobalPackages

Run that and copy/paste what you get back, which should help 🤞

markmckim commented 4 years ago

Whoops! My bad. When I run that against the proper package this time 😀 then I get this...


{\rtf1\ansi\ansicpg1252\cocoartf2511
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 Menlo-Bold;\f1\fnil\fcharset0 Menlo-Regular;}
{\colortbl;\red255\green255\blue255;\red57\green192\blue38;\red0\green0\blue0;\red56\green185\blue199;
\red170\green171\blue37;}
{\*\expandedcolortbl;;\cssrgb\c25704\c77963\c19556;\csgray\c0;\cssrgb\c25544\c77008\c82022;
\cssrgb\c72330\c71683\c18597;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\partightenfactor0

\f0\b\fs22 \cf2 \ul \ulc2 \CocoaLigature0 aws-amplify\cf3 \ulc3 @\cf2 \ulc2 2.2.0
\f1\b0 \cf3 \ulnone  | \cf2 Apache-2.0\cf3  | deps: \cf4 11\cf3  | versions: \cf5 542\cf3 \
AWS Amplify is a JavaScript library for Frontend and mobile developers building cloud-enabled applications.\
\cf4 https://aws-amplify.github.io/\cf3 \
\
dist\
.tarball: \cf4 https://registry.npmjs.org/aws-amplify/-/aws-amplify-2.2.0.tgz\cf3 \
.shasum: \cf5 10560dd838f2d7b9f5d21622cb6c9c723dcbbeb3\cf3 \
.integrity: \cf5 sha512-3eG/qRzl29y4Ro5PHZrmzRB64eg0+/xYU9w1Kb3iJG8CdMux3W5+1fQnfjKOFSSImlUdgDos2Wlrm243NRb+Nw==\cf3 \
.unpackedSize: \cf5 8.5\cf3  MB\
\
dependencies:\
\cf5 @aws-amplify/analytics\cf3 : ^2.2.0    \cf5 @aws-amplify/predictions\cf3 : ^2.1.1  \
\cf5 @aws-amplify/api\cf3 : ^2.1.1          \cf5 @aws-amplify/pubsub\cf3 : ^2.1.1       \
\cf5 @aws-amplify/auth\cf3 : ^2.1.1         \cf5 @aws-amplify/storage\cf3 : ^2.1.1      \
\cf5 @aws-amplify/cache\cf3 : ^2.1.1        \cf5 @aws-amplify/ui\cf3 : ^1.1.3           \
\cf5 @aws-amplify/core\cf3 : ^2.2.0         \cf5 @aws-amplify/xr\cf3 : ^1.1.1           \
\cf5 @aws-amplify/interactions\cf3 : ^2.1.1 \
\
maintainers:\
- \cf5 amzn-oss\cf3  <\cf4 osa-3p@amazon.com\cf3 >\
- \cf5 aws-amplify-ops\cf3  <\cf4 aws-amplify@amazon.com\cf3 >\
- \cf5 elorzafe\cf3  <\cf4 elorzafe@amazon.com\cf3 >\
- \cf5 haverchuck\cf3  <\cf4 dustin.noyes.dev@gmail.com\cf3 >\
- \cf5 jamesiri\cf3  <\cf4 jamesiri@amazon.com\cf3 >\
- \cf5 jpeddicord\cf3  <\cf4 jacob@peddicord.net\cf3 >\
- \cf5 kaustavghosh06\cf3  <\cf4 kaustav.ghosh19@gmail.com\cf3 >\
- \cf5 manuel.iglesias\cf3  <\cf4 manuel.iglesias@gmail.com\cf3 >\
- \cf5 michaelzhou\cf3  <\cf4 michaelzhou.net@gmail.com\cf3 >\
- \cf5 mlabieniec\cf3  <\cf4 michaellabieniec@gmail.com\cf3 >\
- \cf5 powerful23\cf3  <\cf4 wenzhuo235@gmail.com\cf3 >\
- \cf5 undefobj\cf3  <\cf4 rthrelkeld1980@gmail.com\cf3 >\
\
dist-tags:\

\f0\b \cf2 beta
\f1\b0 \cf3 : 1.1.24-beta.10                  
\f0\b \cf2 preview
\f1\b0 \cf3 : 1.1.31-preview.41            \

\f0\b \cf2 latest
\f1\b0 \cf3 : 2.2.0                         
\f0\b \cf2 rn-hosted-ui
\f1\b0 \cf3 : 1.1.20-rn-hosted-ui2.3  \

\f0\b \cf2 next
\f1\b0 \cf3 : 2.1.0                           
\f0\b \cf2 unstable
\f1\b0 \cf3 : 2.2.1-unstable.5            \
\
published \cf5 a week ago\cf3  by \cf5 aws-amplify-ops\cf3  <\cf4 aws-amplify@amazon.com\cf3 >}

Thanks!

ericclemmons commented 4 years ago

Huh! That's the correct version, alright!

Can you help me understand step-by-step what actions your taking to still see this error? Honestly, even starting with the basics (e.g. npm install, npm run-script android, click "Sign In", etc.) will help!

markmckim commented 4 years ago

@ericclemmons So I was previously running an older version (can't remember exactly as I'm not at home right now. Say something like 1.x.x) and I was seeing the broken behaviour where app refreshes would lose auth state and I would be returned to my Sign In screen.

After reading the comments above last night, I updated the value in my package.json to 2.2.0, and did an npm install followed by a pod install. This didn't work.

I then tried doing all the following before trying again:

Some additional info which may/may not have an impact on this.

This code was working perfectly for months before upgrading to the broken version a few weeks ago, and all I did then was update the package.json version, so I assumed that once again upgrading the latest version would fix the issue.

It's possible, but I can't see anywhere in my code that would be causing this, since it's just a call to Auth.currentAuthenticatedUser() and it feels like maybe something cached somewhere or a stale version somewhere....but I've tried deleting the app from the device and reinstalling and just can't seem to pin it down. Any help much appreciated!

ericclemmons commented 4 years ago

@markmckim This is extremely helpful!

First, let's try Auth.currentAuthenticatedUser({ bypassCache: true }), which should force a round-trip to Cognito:

https://aws-amplify.github.io/docs/js/authentication#retrieve-current-authenticated-user

However, we're addressing a known bug (race-condition) that exists with Auth.currentAuthenticatedUser where the first attempt returns a Not Authenticated error, but a subsequent call succeeds. This sounds a lot like what you're seeing.

Lastly, try a Hub.listen("auth", ...) call to the section of code where you're calling Auth.currentAuthenticatedUser(), as seen here:

https://aws-amplify.github.io/docs/js/authentication#oauth-and-hosted-ui)

Please report back if the signIn or signOut calls are being called with the user object, or if the bypassCache option works for you. 🙏

benmgreene commented 4 years ago

Hi there -- been watching this issue for a while and am excited for the progress.

Is there a commit tied to this issue? Couldn't find one mentioned above.

We're using the amazon-cognito-identity-js library, which doesn't seem to have been updated at the same time as aws-amplify... so I'm thinking that our problems probably haven't been addressed quite yet. :-/

ericclemmons commented 4 years ago

@benmgreene Can you share some details on you're use-case with amazon-cognito-identity-js directly vs. the Auth module (linked above)?

You're right, aws-amplify gets the majority of usage & testing, so there could be something specific to amazon-cognito-identity-js & you're use-case that we need to dig into.

benmgreene commented 4 years ago

@ericclemmons From what I can tell from the Auth module, for React Native apps it seems to rely upon amazon-cognito-identity-js anyhow. One of the major problems we currently have is that the import { AsyncStorage } from 'react-native'; line has not been updated to pull from @react-native-community. Though it may well be that there are other issues contributing to our sporadic session loss that have now been addressed, it's not clear to me what changes those were.

As to what's different in our usage of the Auth vs amazon-cognito-identity-js, I imagine we could and will migrate to Auth at some point, but not without significant investment.

markmckim commented 4 years ago

That's interesting @benmgreene ... I have amazon-cognito-identity-js listed in my package.json as instructed here: https://aws-amplify.github.io/docs/js/authentication#configure-your-app

I currently have 3.2.0 of amazon-cognito-identity-js. I wonder could this be related to my issue?

I am however using the Auth module directly in my code, and only including amazon-cognito-identity-js in package.json due to the instructions linked above.

@ericclemmons - Thanks for the help...I'll try your suggested steps now and report back.

markmckim commented 4 years ago

@ericclemmons - Ran a few tests...

Thanks!

ericclemmons commented 4 years ago

@markmckim Ok, we'll need to dig into this more then! I should be able to replicate your scenario by setting up a project via https://aws-amplify.github.io/docs/js/start#option-2-use-react-native-cli-recommended-if-you-have-mobile-development-experience for iOS correct?

I want to ensure I'm following your reproduction steps as close as possible...

markmckim commented 4 years ago

Thanks @ericclemmons - This is probably the closest instructions for configuring my iOS app: https://facebook.github.io/react-native/docs/integration-with-existing-apps

However I imagine that your link would probably be close enough (and quicker). Also I am using CocoaPods, but again, not sure if that is related.

Ashish-Nanda commented 4 years ago

@markmckim what version of RN are you using? You only need to do pod install for RN 0.60+

Regarding the new version of amplify not being picked up: Maybe the packager cache is using the old version of amplify you had installed.

Could you try the following: 1) Stop packager 2) Delete node modules 3) npm install 4) rm -fr $TMPDIR/metro* 5) npm start --reset-cache (on a different terminal tab/window) 6) npx react-native run-ios

Hopefully that will pick up the version 2.2.0 that you have installed and fix the issue related to sessions not being persisted.

Ashish-Nanda commented 4 years ago

@ericclemmons From what I can tell from the Auth module, for React Native apps it seems to rely upon amazon-cognito-identity-js anyhow. One of the major problems we currently have is that the import { AsyncStorage } from 'react-native'; line has not been updated to pull from @react-native-community. Though it may well be that there are other issues contributing to our sporadic session loss that have now been addressed, it's not clear to me what changes those were.

As to what's different in our usage of the Auth vs amazon-cognito-identity-js, I imagine we could and will migrate to Auth at some point, but not without significant investment.

Hi @benmgreene This issue is not related to the community version of AsyncStorage not being used. That was what everyone felt initially but we realized that it does not have anything to do with it for reasons explained in this comment

Also the root cause was found out and elaborated on both here and in this comment.

Now we will need to move to the community edition once RN actually removes AsyncStorage from a future version, but we are not going to be doing it till then since it will break Expo users until Expo itself includes the community edition. So we are not doing it beforehand to avoid breaking RN users who use Amplify with Expo and dont want to eject.
Also in this case it does not cause the issue related to sessions not persisting, and the fix has been confirmed by users above.

Could you elaborate more about your issue. Are you only using amazon-cognito-identity-js and not Auth from Amplify? If your case seems different from most users on this thread, it might be better to file a new issue with details of your setup, the issue itself and which version introduced it for you.

markmckim commented 4 years ago

@Ashish-Nanda I tried all of the above steps and it made no difference unfortunately.

I am using React Native 0.61.5 (hence the pod install).

Here is my package.json dependencies list:

"devDependencies": {
    "babel-eslint": "10.0.3",
    "babel-preset-react-native": "5.0.2",
    "eslint": "6.7.2",
    "eslint-config-airbnb": "18.0.1",
    "eslint-config-prettier": "6.7.0",
    "eslint-plugin-import": "2.18.2",
    "eslint-plugin-jest": "23.1.1",
    "eslint-plugin-jsx-a11y": "6.2.3",
    "eslint-plugin-prettier": "3.1.1",
    "eslint-plugin-react": "7.17.0",
    "eslint-plugin-react-native": "3.8.1",
    "jest": "24.9.0",
    "prettier": "1.18.2"
  },
  "dependencies": {
    "@react-native-community/async-storage": "1.6.2",
    "@react-native-community/geolocation": "2.0.2",
    "amazon-cognito-identity-js": "3.2.0",
    "aws-amplify": "2.2.0",
    "native-base": "2.13.8",
    "prop-types": "15.7.2",
    "react": "16.12.0",
    "react-native": "0.61.5",
    "react-native-camera": "3.13.1",
    "react-native-device-info": "5.3.1",
    "react-native-flip-card": "3.5.5",
    "react-native-gesture-handler": "1.5.2",
    "react-native-image-header-scroll-view": "0.10.3",
    "react-native-maps": "0.26.1",
    "react-native-qrcode-svg": "6.0.1",
    "react-native-reanimated": "1.4.0",
    "react-native-sound": "0.11.0",
    "react-native-spinkit": "1.5.0",
    "react-native-svg": "9.13.3",
    "react-native-swiper": "1.6.0-rc.3",
    "react-native-vector-icons": "6.6.0",
    "react-native-webview": "7.6.0",
    "react-navigation": "4.0.10",
    "react-navigation-stack": "1.10.3",
    "react-navigation-tabs": "2.6.2",
    "react-redux": "7.1.3",
    "redux": "4.0.4",
    "redux-devtools-extension": "2.13.8",
    "redux-persist": "6.0.0",
    "redux-thunk": "2.3.0",
    "shortid": "2.2.15"
  }
claudioviola commented 4 years ago

Hello @Ashish-Nanda From my side very weird case.

Until yesterday I builded and released many versions with this configuration: "amazon-cognito-identity-js": "^3.0.15", "aws-amplify": "^1.1.29", "react": "16.9.0", "react-native": "0.61.4", It worked very well.

Today I faced the issue session wasn't anymore persistent. So I updated my dependecies to latest "amazon-cognito-identity-js": "^3.2.0", "aws-amplify": "^2.2.0", Issue is gone away and session is again persistent.

Do you know how would it be possible?

mikedizon commented 4 years ago

Sounds like a few of the folks in this thread are having some issues with dependencies. FWIW, I've added dependabot to my repository and haven't seen any issues since the fix was pushed.

mickadoua commented 4 years ago

I stile have the same issue, its weird because 2days ago, i thought every was fine,

I tested @latest and @next but the result is the same,

after relstart the application user is disconnected

  Auth.currentSession()
    .then(data => console.log(data))
    .catch(err => console.log(err));
ajdinahmetovic commented 4 years ago

I agree with @mickadoua, I tesed few days ago it was working fine. Now I have same issues again 😕

I tried deleting node_modules, reseting cache, reseting android folder, tried @latest and @next I couldnt manage to get it working now.

mickadoua commented 4 years ago

in Android I dont have any issue