Implementing Authentication In Next.js Using Next Auth
Tags: nextjs, javascript, webdev
Published: 2022-09-25 11:29:14


In this post, we will be implementing GitHub, Twitter and email authentication in Next JS using NextAuth.js

## What is Next Auth?

NextAuth.js is a complete open-source authentication solution for [Next.js](http://nextjs.org/) applications. It has built-in hooks that let you access the user from the client side.

## Getting Started

1. I assume that you have maltreated created/initiated your next js project if not, just run `yarn create next-app` to create next js boilerplate code 
2. Now, we can install next-auth by running  `yarn add next-auth` or `npm install next-auth` 
3. Now, we can create an API route for the authentication by editing the `pages/api/auth/[...nextauth].js` file
```javascript
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"

export const authOptions = {
  // Configure one or more authentication providers
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
    // ...add more providers here
  ],
}

export default NextAuth(authOptions)

```javascript
<!--kg-card-end: markdown-->
- You might need a provider which is a database. For this instance, I will be using the MongoDB 

4. Now, we can access the user from the client side  by wrapping our component `pages/_app.jsx` with **SessionProvider**

<!--kg-card-begin: markdown-->
```javascript
import { SessionProvider } from "next-auth/react"

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  )
}

```javascript
<!--kg-card-end: markdown-->

3. Now, we'll create a simple home page by editing `pages/index.js`

<!--kg-card-begin: markdown-->
```javascript
import { Center, VStack, Text, Button } from '@chakra-ui/react';
import { useSession, signIn } from 'next-auth/react';
import React from 'react';

export default function Home() {
    const { data } = useSession();
    return (
        <Center height="100%" my={'10rem'}>
            <VStack>
                <Text fontSize={'2xl'}>
                    Current User: {data?.user?.email || 'None'}{' '}
                </Text>

                {!data?.user && <Button onClick={() => signIn()}>Login</Button>}
            </VStack>
        </Center>
    );
}

```javascript
<!--kg-card-end: markdown-->

4. Let's create an authentication page(`pages/auth.js`) where the users will be able to log in/Register using OAuth Providers like GitHub, discord

<!--kg-card-begin: markdown-->
```javascript
import {
    Box,
    Center,
    Container,
    Flex,
    Icon,
    VStack,
    Button,
} from '@chakra-ui/react';
import {
    getProviders,
    getSession,
    GetSessionParams,
    signIn,
    useSession,
} from 'next-auth/react';
import { FcGoogle } from 'react-icons/fc';
import { FaDiscord, FaGithub } from 'react-icons/fa';
import { GetServerSideProps } from 'next';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
export default function SignIn({ providers }) {
    const router = useRouter();
    const user = useSession();
    useEffect(() => {
        // if (router.query.callbackUrl) {
        // router.push(router.query.callbackUrl as string);
        // }
        if (user?.data?.user) {
            router.push('/');
        }
    });
    let icons = [
        {
            name: 'Google',
            icon: FcGoogle,
        },
        {
            name: 'Github',
            icon: FaGithub,
        },
        {
            name: 'Discord',
            icon: FaDiscord,
        },
    ];
    return (
        <Flex h="100vh" alignItems={'center'} justifyContent="center">
            <Box
                border="1px"
                borderColor="gray.200"
                p={4}
                rounded="xl"
                // translateY={'50%'}
            >
                <VStack>
                    {Object.values(providers).map((provider: any) => (
                        <Button
                            leftIcon={
                                <Icon
                                    as={
                                        icons.find(
                                            (i) =>
                                                i.name.toLowerCase() ===
                                                provider.name.toLowerCase()
                                        ).icon
                                    }
                                />
                            }
                            onClick={async () => signIn(provider.id)}
                            key={provider.id}
                        >{`Sign in with ${provider.name}`}</Button>
                    ))}
                </VStack>
            </Box>
        </Flex>
    );
}

export const getServerSideProps: GetServerSideProps = async (context) => {
    const session = await getSession(context);
    const providers = await getProviders();
    // console.log(context.query);
    if (session) {
        return {
            redirect: {
                destination: (context?.query?.callbackUrl as string) || '/',
                permanent: false,
            },
        };
    }
    return {
        props: { providers },
    };
};

```javascript
<!--kg-card-end: markdown-->

5. You may use the `useSession()` hook to obtain the user details on the client side or you may use `getSession()` on the server side

<!--kg-card-begin: markdown-->

Client-Side

```javascript
import { useSession } from "next-auth/react"

export default function Component() {
  const { data: session, status } = useSession()

  if (status === "authenticated") {
    return <p>Signed in as {session.user.email}</p>
  }

  return <a href="/api/auth/signin">Sign in</a>
}

```

Server-side

```javascript
async function myFunction() {
  const session = await getSession() 
  /* ... */
}

```
<!--kg-card-end: markdown-->

6. We have successfully now added authentication to our next js site, you may now run `yarn dev` and the dev server might start running

## Conclusion  

- I have used the [Chakra UI](https://chakra-ui.com/) library to style up the frontend 
- Full source code is available on [GitHub](https://github.com/raghavmri/simple-next-authentication)

P.S:- [Vultr](https://www.vultr.com/?ref=9086643-8H)(Get a $100 credit by registering using this link) is an excellent hosting choice if you're looking for one.