gladly-team / next-firebase-auth

Simple Firebase authentication for all Next.js rendering strategies

Home Page:https://nfa-example-git-v1x-gladly-team.vercel.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support dynamic redirect destinations

kmjennison opened this issue · comments

Is your feature request related to a problem? Please describe.
As mentioned in the limitations, there isn't built-in support for custom redirect destinations based on the user's auth status. This limits the usefulness of the redirects.

Describe the solution you'd like and how you'd implement it
Allow users to provide functions for the authPageURL and appPageURL config properties that should return the appropriate URL. We could pass either ctx or window to the function, depending on the context.

// ctx would be defined when server-side redirecting, window for client-side
({ ctx, window }) => {
  // some logic
  return '/my-auth-page?next=/my-app/'
}

Is this a breaking change?
No. We would still support static values for the config options.

Describe alternatives you've considered
None

I like this idea a lot. It does provide flexibility both at CSR and SSR.

Just a few comments / observations:

  • You mention it's for the authPageURL and appPageURL config properties, but I assume it would also work for the option parameters of all withAuthXXX functions right ? I mean, it has too.

  • I believe it's implied, but just for clarity, authPageURL and appPageURL could be provided either as string, or functions right ?

  • I'm not sure that passing window in parameters is a good idea. At CSR it's globally available anyway. The only time I tried to access window like this through a parameter my code did not behave the way I expected it to. Simply using the global window object after checking it exist (ex: if (typeof window !== 'undefined')) was the best/safest option.

  • Shouldn't we expose the AuthUser also ? I know it's available in ctx, but maybe making it explicitly available as a parameter would be easier to understand

// ctx would be defined when server-side redirecting
// window is globally available for client-side
// AuthUser is available for custom logic to be built around
({ ctx, AuthUser }) => {
  // handle CSR vs SSR
  if (typeof window !== 'undefined')
    // do CSR stuff here
  else if (ctx)
    // do SSR stuff here

  // some logic
  return '/my-auth-page?next=/my-app/'
}

@tlays Thanks for the thoughtful feedback! I agree with all of your suggestions.

You mention it's for the authPageURL and appPageURL config properties, but I assume it would also work for the option parameters of all withAuthXXX functions right ?

Yes

I believe it's implied, but just for clarity, authPageURL and appPageURL could be provided either as string, or functions right ?

Yes

I'm not sure that passing window in parameters is a good idea.

I agree

Shouldn't we expose the AuthUser also ?

I agree, this is a good idea

After this is implemented, we should also replace the "custom redirect" example added in #51. A simple demo would be to include the user's email in a URL parameter value when redirecting.

After this is implemented, we should also replace the "custom redirect" example added in #51. A simple demo would be to include the user's email in a URL parameter value when redirecting.

Yes, or maybe add another (a new) example page specific for this redirect technique (with a dynamic redirect at CSR vs SSR). IMO, the example in #51 is still interesting to keep in order to illustrate how to use the built-in / standard SSR support for notFound and redirect.

Any ETA on this awesome feature? :)

Right now I do it like this (maybe that helps others):

getServerSideProps

export const getServerSideProps = withAuthUserTokenSSR()(async (props) => {
  if (!props.AuthUser.id) {
    return {};
  }
  return {
    redirect: {
      destination: "/cockpit",
      permanent: false,
    },
  };
});

useEffect - I have this in _app.js so it works on every page

useEffect(() => {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        router.push("/cockpit");
      } else {
        router.push("/");
      }
    });
  }, []);

Closed by #121 and released in v0.13.0-alpha.3.

Opened an issue to update the documentation and example: #122