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

1.7k Views Asked by At

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)?
2

There are 2 best solutions below

4
hackmajoris On BEST ANSWER

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.

0
smirad91 On
  1. Move hub.listen method in file where you called Amplify.configure(awsconfig)

  2. When calling federated sign in, send custom state like this:

import {CognitoHostedUIIdentityProvider} from "@aws-amplify/auth/lib/types"

Auth.federatedSignIn({provider:CognitoHostedUIIdentityProvider.Google, customState:'whatever'})

Then hub listen event customOAuthState will return text 'whatever'