firebase/firebaseui-web-react

Question: How to make use of `redirectUrl` inside `signInSuccessWithAuthResult`

gr-qft opened this issue · 14 comments

Hello,

I'm using email link authentication for my app. In the app, there're two kinds of users, normal users and admin users, and I would like to be able to redirect them differently after a sign-in success. How would I do that? I've checked around but still have no idea. I'm thinking redirectUrl inside signInSuccessWithAuthResult might have something to do with this but I'm not sure. I'll really appreciate any help.

Just a note. I think as the last resort it's always possible to have the same redirect for both users, but render the views differently. But I would really appreciate any help or comment.

Thanks!

I assume you are using custom claims to differentiate between normal and admin users.

If so, you can add a signInSuccessWithAuthResult callback and check the user's custom claims there:

signInSuccessWithAuthResult:(authResult, redirectUrl) => {
   authResult.user.getIdTokenResult().then(tokenResult => {
    if (tokenResult.claims.admin) {
      window.location.assign('/admin');
    } else {
      window.location.assign('/user');
    }
  });
}

@bojeil-google Thanks for the answer. So, we have to use window.location directly, and the parameter redirectUrl is not usable? I'm asking this because signInSuccessUrl, if given a value, will work (if at the end of signInSuccessWithAuthResult I return true).

I've really tried to read the firebase doc and somewhere it mentions passing a url, using emailLinkSignIn . But it seems to me for handling email link sign-in firebase sets the mode as signIn automatically as well as a default continueUrl and it's not possible to overwrite those, is that true?

Thank you!

I assumed that you had a more complicated logic where you check the user claim and redirect based on that.

I haven't tested it in a while but I believe you can also pass the signInSuccessUrl query parameter in the URL and the value of that will be either passed back in the callback or will be redirected to on success.

You can also just set the signInSuccessUrl in the config without setting a callback.

These 2 options assume you know the type of user ahead of time. If you don't know the type of user until sign in is successful, you are better off using the callback approach.

BTW, returning true in signInSuccessWithAuthResult callback will continue the redirect to the expected URL (signInSuccessUrl or redirectUrl) had the callback not been provided.

When using emailLinkSignIn, the url is the object returned is mainly the URL to redirect to when the user clicks the sign in link in their email inbox. You can pass a custom URL there too and then retrieve it in the success callback by checking the current URL via window.location.href. I think you have a variety of options here.

Thanks for the info. I've really tried the option emailLinkSignIn but the sign-in link in the email is always the same (as I wrote, mode and continueUrl seem to be set by firebase and I couldn't do anything to change them). It would be really nice if emailLinkSignIn works as documented. What do you recommend?

I believe the continueUrl is affected by the url value returned in the emailLinkSignIn callback. We use this object when triggering sign in with email link.

I've tried repeatedly many times but it's not working, mode and continueUrl in the sign-in link are always the same regardless of what I do.

Can you provide snippets of your configuration to make sure we are on the same page? The code should use the current URL as the default url but will overwrite it with the one you return in the emailLinkSignIn callback. The mode will always be the same for email link sign in.

Ok here's what I have. I've tried different settings (like returning false inside signInSuccessWithAuthResult and setting handleCodeInApp to false etc. Like I said, I've checked the email sign-in link repeatedly and it's always the same no matter what I do. (https://xxx.firebaseapp.com/__/auth/action?apiKey=xxx&mode=signIn&oobCode=xxx&continueUrl=http://192.168.2.14:3399/login?xxxlang=en). Also, lang=en is set automatically and I don't know how to change that also.

const firebaseAuthConfig = {
  signInFlow: "redirect",
  signInOptions: [
    {
      provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
      signInMethod: firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD
    }
  ],
  signInSuccessUrl: "http://192.168.2.14:3399/me",
  credentialHelper: "none",
  callbacks: {
    signInSuccessWithAuthResult: async (authResult, redirectUrl) => {
      const { user } = authResult;
      const userData = await mapUserData(user);
      setUserCookie(userData);
      return true;
    }
  },
  emailLinkSignIn: () => {
    return {
      url: "http://192.168.2.14:3399/me?showPromo=1234",
      handleCodeInApp: true
    };
  }
};;

Please note that http://192.168.2.14:3399/login is where the I require the sign-in email.

This works as expected. The url http://192.168.2.14:3399/login is set as the continue URL. We always redirect to the action url which redirects back to the continueUrl. If you want to change that, you need to do from the Firebase Console email template section.

As for the language, check these sections:

You need to localize the UI itself and the email link. When you localize the UI, it will propagate the language to the email template.

I'm not following: I set url inside emailLinkSignIn to /me but continueUrl in the link email sent is always /login. The address http://192.168.2.14:3399/login is not explicitly set by me anywhere (I set /me instead). In fact, right now, the only way I get the right redirect is to use signInSuccessUrl, but this is not dynamic. So what I've been seeing is whatever I write inside emailLinkSignIn are ignored.

Thanks for the links about the languages!

Hmm, you are right. I missed the /me path. I will need to test to see why it is not honoring your url. Can you try using just the path /me?showPromo=1234?

I just tried, continueUrl in the link is still /login. Moreover, it seems if I have signInSuccessUrl then eventually I'll be redirected to it whether or not I return true or false inside signInSuccessWithAuthResult.

By the way, it seems because of the above at present there's no way to redirect from inside signInSuccessWithAuthResult.

Thanks!

Hey @gr-qft I tested this on my end with various url returned in the emailLinkSignIn callback:

  • Relative link with just a different path
  • Absolute link with same domain and different path.
  • Link with different domain and path.
  • Link with IP address and path
  • Link with IP address, port number and path
  • Link with IP address, port number, path and query string

I cannot recreate your issue. All of the above are appended in the continueUrl as expected.
To be honest, I have no idea why it is not working for you.

Hey @bojeil-google ,

Thanks for testing! I've tried again and it's still not working, in every case the continueUrl in the link is always /login.

If it helps, the template I see on console is https://xxx.firebaseapp.com/__/auth/action?mode=action&oobCode=code, and mode and continueUrl are set automatically for me!! Also, this is how I use setting:

const FirebaseAuth = () => {
  return (
    <div>
      <StyledFirebaseAuth
        uiConfig={firebaseAuthConfig}
        firebaseAuth={firebase.auth()}
      />
    </div>
  );
};

This is a very weird problem. If it's ok with you, I can give you access to my code. It's mostly based on this:

https://github.com/vercel/next.js/tree/canary/examples/with-firebase-authentication