single-page-applicationaws-amplifysolid-js

Unable to catch the 'auth' event in Hub.listen while calling Auth.federatedSignIn


I am using SolidJS and building a SPA (no server rendering). For authentication, I use the @aws-amplify/core and @aws-amplify/auth packages. At the application root I call the Hub.listen function:

Hub.listen('auth', ({ payload }) => console.log(payload));

In the SignUp component I call Auth.federatedSignIn:

const SignUp = () => {
  return (
    <button onClick={() => {
      Auth.federatedSignIn({ provider: CognitoHostedUIIdentityProvider.Google });
    }}>
      Sign up
    </button>
  );
}

I have configured the Amplify as such:

Amplify.configure({
    Auth: {
        region: import.meta.env.VITE_AWS_REGION,
        userPoolId: import.meta.env.VITE_AWS_POOL_ID,
        userPoolWebClientId: import.meta.env.VITE_AWS_POOL_CLIENT_ID,
        oauth: {
            domain: import.meta.env.VITE_AUTH_URL,
            responseType: 'code',
            redirectSignIn: location.origin + '/account/external',
            redirectSignOut: location.origin + '/my',
        },
    },
});

When I click on the button I am redirected to the import.meta.env.VITE_AUTH_URL (simply outside of my app), choose an account, and then return back to the /account/external page. At that time I expect a consoled payload object in Web tools, but there is nothing. I get it when I call Auth.signOut(), so I assume that I configured Amplify correctly and Hub is subscribed to the auth channel.

My thoughts were that Hub cannot catch any events because after returning the application basically renders again in a new context and Hub simply isn't able to catch anything (events aren't sent from AWS?). I tried to declare the urlOpener function under the oauth property in the config and Google's sign page opened in a new tab, but even then I couldn't get any events in the preserved old page (from which I called Auth.federatedSignIn).

Questions:

  1. How should I organize the code to get the signIn and signUp events?
  2. Can I pass some data into the Auth.federatedSignIn to get it back in the Hub.listen, so I will be able to join the CognitoUser with the data that existed at the time of starting Sign in/Sign up (I want to add a new login type to existed user)?

Solution

  • Here is an example regarding the first question. Just check that your listener is set before you call the Auth.federatedSignIn() method.

       export default class SignInService {
          constructor(private landingFacade: LandingFacade) {
            this.setupAuthListeners(); // Should be called at the top level.
          }
        
          private setupAuthListeners() {
            Hub.listen('auth', ({ payload: { event, data } }) => {
              switch (event) {
                case 'signIn':
                  this.landingFacade.signInSuccess();
                  break;
                case 'signIn_failure':
                  console.log('Sign in failure', data);
                  break;
                case 'configured':
                  console.log('the Auth module is configured', data);
              }
            });
          }
        
          public async signIn(): Promise<void> {
            await Auth.federatedSignIn();
          }
        }
    

    For the second one: I'll use a local state and set/query the object you need.