NextJS authentication

with MongoDB and next-auth

This is a simple demo project aiming to show how to realize a NextJS application able to load some credentials from a MongoDB collection and to keep a session until the user performs a logout action. The full code can be found on GitHub: https://github.com/fcalderan/nextjsauth-demo

The /pages/_app.js file exports the function

import Layout from "../components/layout/layout";
import { SessionProvider } from "next-auth/react";

function MyApp({ Component, pageProps }) {
  return (
    <SessionProvider session={pageProps.session}>
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </SessionProvider>
  );
}
export default MyApp;

The Layout component is wrapped into a SessionProvider component, so it's available in all the components of the app.

The Login page can be accessed only when the user is not logged in and there is no session available. To check if a session is available we run the login page on server side through the getServerSideProps function. Since getSession is asynchronous we use async/await:

import { getSession } from "next-auth/react";

[...]

export async function getServerSideProps(context) {
  const session = await getSession({ req: context.req });

  if (session) {
    return {
      redirect: {
        destination: "/profile",
        permanent: false,
      },
    };
  }

  return {
    props: { session },
  };
}

If a session is available the user is redirected to the/profile page. The top navigation is conditionally rendering some links based on the presence of the session.

import Link from "next/link";
import { useSession, signOut } from "next-auth/react";
import { useRouter } from "next/router";
import classes from "./main-navigation.module.css";

function MainNavigation() {
  const router = useRouter();
  const { data: session, status } = useSession();

  return (
    <header className={classes.header}>

      <Link href="/" aria-current={router.pathname === "/" ? "page" : null}>
        Next Auth
      </Link>

      <nav>
        <ul>
          
          {!session && (
            <li>
              <Link
                href="/login"
                aria-current={router.pathname === "/login" ? "page" : null}
              >
                Login
              </Link>
            </li>
          )}

          {session && (
            <>
              <li>
                <Link
                  href="/profile"
                  aria-current={router.pathname === "/profile" ? "page" : null}
                >
                  Profile
                </Link>
              </li>
              <li>
                <button onClick={signOut}>Logout</button>
              </li>
            </>
          )}

        </ul>
      </nav>
    </header>
  );
}

export default MainNavigation;
;