Auth: Delay of Hub events using federatedSignIn
See original GitHub issueI am referring to the full react sample code from this section of the docs:
// App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import OAuthButton from './OAuthButton';
import Amplify, {Auth, Hub} from 'aws-amplify';
import awsmobile from './aws-exports'; // your Amplify configuration
// your Cognito Hosted UI configuration
const oauth = {
domain: 'your_cognito_domain',
scope: ['phone', 'email', 'profile', 'openid', 'aws.cognito.signin.user.admin'],
redirectSignIn: 'http://localhost:3000/',
redirectSignOut: 'http://localhost:3000/',
responseType: 'code' // or token
};
Amplify.configure(awsmobile);
Auth.configure({ oauth });
class App extends Component {
constructor(props) {
super(props);
this.signOut = this.signOut.bind(this);
// let the Hub module listen on Auth events
Hub.listen('auth', (data) => {
switch (data.payload.event) {
case 'signIn':
this.setState({authState: 'signedIn'});
this.setState({authData: data.payload.data});
break;
case 'signIn_failure':
this.setState({authState: 'signIn'});
this.setState({authData: null});
this.setState({authError: data.payload.data});
break;
default:
break;
}
});
this.state = {
authState: 'loading',
authData: null,
authError: null
}
}
componentDidMount() {
console.log('on component mount');
// check the current user when the App component is loaded
Auth.currentAuthenticatedUser().then(user => {
console.log(user);
this.setState({authState: 'signedIn'});
}).catch(e => {
console.log(e);
this.setState({authState: 'signIn'});
});
}
signOut() {
Auth.signOut().then(() => {
this.setState({authState: 'signIn'});
}).catch(e => {
console.log(e);
});
}
render() {
const { authState } = this.state;
return (
<div className="App">
{authState === 'loading' && (<div>loading...</div>)}
{authState === 'signIn' && <OAuthButton/>}
{authState === 'signedIn' && <button onClick={this.signOut}>Sign out</button>}
</div>
);
}
}
export default App;
// OAuthButton.js
import { withOAuth } from 'aws-amplify-react';
import React, { Component } from 'react';
class OAuthButton extends React.Component {
render() {
return (
<button onClick={this.props.OAuthSignIn}>
Sign in with AWS
</button>
)
}
}
export default withOAuth(OAuthButton);
I found out during testing that this example is a bit misleading. I’m pretty sure the loading
state could just as well be omitted as it cannot possibly affect the UI. After the redirect from the Cognito Hosted UI, there is a delay of a couple of 100ms until the Hub listener receives the signIn
event. However, the Auth.currentAuthenticatedUser
in the componentDidMount
will immediately fire and set the authState
to signIn
. Until this state change in componentDidMount
is finished, React will block any UI rendering, so the “loading…” div cannot possible render.
This causes a glitchy UI in the app because after returning from the Hosted UI it will initially render as signed out and then when the Hub event fires it will update based on the state change to signedIn
. I am currently “solving” this with a setTimeout
hack:
Auth.currentAuthenticatedUser().then(user => {
console.log(user);
this.setState({authState: 'signedIn'});
}).catch(e => {
console.log(e);
setTimeout(() => {
if (this.state.authState === 'loading') {
this.setState({authState: 'signIn'});
}
}, 500)
});
This is how I make sure that the Hub event has fired before rendering anything. But this is adding the 500ms in other scenarios as well when it’s not necessary. Is there a better solution?
Issue Analytics
- State:
- Created 4 years ago
- Reactions:7
- Comments:5 (3 by maintainers)
Top GitHub Comments
This will be fixed by #3258
@tinymarsracing we will work on this issue and also update the sample doc.