mydogspies
mydogspies

Reputation: 167

Can I check if a Auth0 user is logged in already at the level of my custom NextJS _app.js?

Working on a NextJS app using nextjs-auth0 (to which I'm totally new) for authentication. I wrapped my _app.js with UserProvider as the docs suggest and using getInitialProps to set a global online/offline status to the entire app as so;

import App from "next/app";
import { UserProvider} from '@auth0/nextjs-auth0';

export default function MyApp({Component, pageProps, status}) {

        return (
            <UserProvider>
                <Component {...pageProps} status={status}/>
            </UserProvider>
        );
};

MyApp.getInitialProps = async (appContext) => {
    const appProps = await App.getInitialProps(appContext);
    const status = await getSiteStatus();
    return {appProps, status};
};

This works fine and I can pick up the status of the site, even make a global offline landing page right here if I wished. I can also pick up the auth0 session from any other page using the useUser hook.

But here is the catch: I would like to set a global div strip above all content, informing the user that he/she is logged in and can see the site although it's offline. So literally every visitor will be met by a single "offline" page while people logged in still have the access to the all other pages and are informed they are viewing an offline site.

To me the easiest way would be to simply bake that into the app page, something in style with this;

export default function MyApp({Component, pageProps, status, user}) {

        if(status)  {

          return (
              <UserProvider>
                  <Component {...pageProps} status={status}/>
              </UserProvider>
          );

        } else if (user && !status) {

           return (
              <UserProvider>
                  <div class="somestyle">You are logged in but the site is offline!</div>
                  <Component {...pageProps} status={status}/>
             </UserProvider>

        } else {

           return (
              <SiteOffline />
           )
        
};

The big question: How do I get the Auth0 user session in this scenario and pass it as user in this case? I can not use the useUser hook since _app.js is in itself not wrapped in UserProvider and thus throws an error I can not use hooks here.

I guess best would be to somehow get the auth session with getInitialProps but how without hooks? Can't seem to find any scenario like this mentioned anywhere and using an additional wrapper component sitting between this and any other component seems hugely awkward. Any ideas?

Upvotes: 1

Views: 4986

Answers (2)

mydogspies
mydogspies

Reputation: 167

Thank you to @juliomalves for an elegant solution that works! Meanwhile just a few more observations I did while working on this;

a) Using getInitialProps will forfeit Automatic Static Optimization but the Nextjs docs seem to imply you can still have the cake if one defines getStaticProps in every page one wishes to be optimized. Did not confirm this and the docs also advice to rather not use getInitialProps at all. Not sure how to get around my problem in any other way though.

b) The bigger issue is having parts of the site to be always online, such as admin/user/backend login pages. This seems cumbersome with logic directly in the app.js. I would somehow need to override the Nextjs router to bypass the "offline" page logic before it hits _app.js when the route is a login/admin page. Not pretty.

So in the end the most efficient solution for this particular case seems to be to use the wrapper as in the answer, pass the status on to the children and then let each page component decide what to do with the information - redirect to offline or ignore.

Upvotes: 1

juliomalves
juliomalves

Reputation: 50338

You can move the logic to a separate component that would wrap your page Component.

// components/page-wrapper

import { useUser } from '@auth0/nextjs-auth0';

export default function PageWrapper({ children, status }) {
    const { user } = useUser();

    return status || user ? (
        <> 
            {!status && <div class="somestyle">You are logged in but the site is offline!</div>}
            {children}
        </>
    ) : (
        <SiteOffline />
    );       
};

You would then use it in _app as a child of the UserProvider, thus providing access to the useUser hook.

// pages/_app

import { UserProvider} from '@auth0/nextjs-auth0';
import PageWrapper from '<path-to>/components/page-wrapper'

export default function MyApp({ Component, pageProps, status }) {
    return (
        <UserProvider>
            <PageWrapper status={status}>
                <Component {...pageProps} status={status}/>
            </PageWrapper>
        </UserProvider>
    );
};

Upvotes: 1

Related Questions