amplify-js: Amplify React Native auth.signout() does not return to Sign In page when called from App component

New iOS App From Scratch Integrated React Native into existing app as per React Native Docs Integrated AWS Amplify Versions: react: 16.4.1 react-native: 0.56.0 aws-amplify: 1.0.7 aws-amplify-react-native: 1.0.7 amazon-cognito-auth-js: 1.2.4 amazon-cognito-identity-js: 2.0.22

Description: Sign Out fails

Steps To Recreate:

Create New iOS App In Xcode Integrate Auth using withAuthenticator into the React Native app as per the instructions here: https://docs.aws.amazon.com/aws-mobile/latest/developerguide/react-native-add-user-sign-in.html Create a sample “App Screen” that only has a single button (which calls Auth.signout()) from the auth package of aws-amplify Build & Launch App Enter credentials on Sign In page Click Login Successfully navigated to main App home page Click “Sign Out” button Notice that you are not returned back to the Sign In page

Things To Note: You are being signed out (if you are running against the RN packager and refresh the app, you are taken directly to Sign In page). So it does appear that the actual sign out is happening, but the only issue that you are not redirected back to the sign in page.

This does happen with aws-amplify: 1.0.7 & aws-amplify-react-native: 1.0.7, but the issue does not occur if i drop back down to 1.0.6 for both packages.

Any help much appreciated. Thanks!

Update: OK so I did a bit more testing, and it seems that:

It does work when you use the greetings.js component (by passing in the true flag as the second param in withAuthenticator) It does not work when you make a call to auth.signout() from within one of your app components. Looking at the greetings.js components, it actually does two things:

Calls auth.signout() Changes the authState to “signedOut” Auth.signOut().then(() => this.changeState('signedOut')).catch(err => this.error(err));

However the app components (to the best of my knowledge) do not have access to the changeState function.

Note: Simply calling auth.signout() from within an app component on V1.0.6 works fine with no extra logic required. Simply upgrading to 1.0.7, 1.0.8 or 2.0.0 causes this to not work. Something has changed with the recent amplify changes it would seem.

Note: This is a reopened version of this issue (but now with updated steps to recreate) which was closed: https://github.com/aws-amplify/amplify-js/issues/1527

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 40 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@markmckim - I simply do this in my App component to load the sign in component again. App is passed to the withAuthenticator.

Auth.signOut() .then(() => { this.props.onStateChange(‘signedOut’, null); }) .catch(err => { console.log('err: ', err) })

When using the Auth.signOut from within the withAuthenticator it will not sign out because it is only updating the session locally in AsyncStorage. You need to have a way to rerender the actual withAuthenticator component.

You can accomplish this with something like this:

// main component (index.js or something)
import MainApp from './App.js'
class AuthWrapper extends React.Component {
  rerender = () => this.forceUpdate()
  render() {
    return <MainApp rerender={this.rerender} />
  }
}

// component that is being wrapped with withAuthenticator component
class App extends Component {
  signOut = async () => {
    await Auth.signOut()
    this.props.rerender()
  }
  render() {
    return (
      <div style={styles.container}>
        <p style={styles.welcome}>Hello World</p>
      </div>
    );
  }
}

// new default export for withAuthenticator (this is to receive props & force the rerender)
export default props =>  {
  const AppComponent = withAuthenticator(App)
  return <AppComponent {...props} />
}

Let me know if this works @ejdigby @markmckim

Just implemented this today and can confirm it works.

Thanks @dabit3

Hey I did a mix of @dabit3 solutions because I needed my Auth.signOut() in an other component. Maybe it can work for you as well @anirudh-goyal

Navbar.jsx

import { Auth } from "aws-amplify";

export default function SimpleMenu(props) {
 return (
  <div>
   <button onClick={() => Auth.signOut()}>Sign out</button>
  </div
}

App.js

import Navbar from "./components/navbar.jsx";
import Amplify from 'aws-amplify';
import { Authenticator} from "aws-amplify-react";

class App extends React.Component {
  constructor(props) {
    super(props);
  };

componentDidMount() {
    Hub.listen('auth', (authData) => {
      console.log('authData: ', authData)
      if (authData.payload.event === 'signOut') {
        this.props.onStateChange('signedOut', null);
      }
    })
  }

render() {
    return (
      <div>
        <Navbar ></Navbar>
      </div>
    );
  }
}

class AppWithAuth extends React.Component {

  render() {
    return (
      <Authenticator>
        <App />
      </Authenticator>
    );
  }
}

export default AppWithAuth;

@et304383 Another way to handle this would be to use the Hub class & listen for auth changes.

import { Hub } from 'aws-amplify'

componentDidMount() {
  Hub.listen('auth', function(authData) {
    console.log('authData: ', authData)
    if (authData.payload.event === 'signOut') {
      // rerender or do something here in the hamburger menu
    }
  })
}

https://aws-amplify.github.io/docs/js/hub#listening-for-messages

@markmckim so if I am understanding correctly, is it something like:

class App extends Component {
     signOut() {
           const { onStateChange } = this.props;
           Auth.signOut().then(() => {
                    onStateChange('signedOut');
           });
     }
     
     render() {
         return (
               <Button onPress={this.signOut} text='sign out'/>
        )
     }
}

export default withAuthenticator(App);

@et304383 sorry you’re having trouble. I’ve put together a gist at https://gist.github.com/dabit3/6c4f0a06b5e39fd53567a4a521143efa

import React from 'react'
import { View, Text } from 'react-native'
import { withAuthenticator } from 'aws-amplify-react-native'

function App(props) {
  function signOut() {
    Auth.signOut()
      .then(() => {
        props.onStateChange('signedOut', null);
      })
      .catch(err => {
        console.log('err: ', err)
      })
  }
  
  return (
    <View>
      <Text>Hello World</Text>
      <Text onPress={signOut}>Sign Out</Text>
    </View>
  )
}

export default withAuthenticator(App)

Have a look & let me know if that helps out. It should be a full working example.

Maybe this commit caused it: https://github.com/aws-amplify/amplify-js/commit/8352bdb

Specifically the changes around line 90