Next Auth Login Web3 with Next13
Tags: beginners, tutorial, web3, nextjs
Published: 2023-03-08 16:47:32

Primero creamos un projecto en Nextjs you utilizo yarn pero puedes elegir el que mas te guste

```
yarn create next-app
```
en mi caso me gusta usar typescript pero  puedes utilizar javascript si te es más cómodo
`✔ Would you like to use TypeScript with this project? … No / Yes
`
Puedes crear tu project o con tus preferencias en este caso usaremos la carpeta experimental app, luego de que se instalen todas las dependencias corra el projecto 

ahora vamos a agregar next auth 

```
yarn add next-auth
```
otras dependencias 
```
yarn add siwe@beta ethers wagmi
```
aqui vamos a usar algo feo debido a que aun no he visto otra manera de integrar nextAuth crearemos la carpeta al mismo nivel que la carpeta app `pages/api/auth/[...nextauth].ts`

ahora nuestro archivo debe verse así 

```ts
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { getCsrfToken } from "next-auth/react";
import { SiweMessage } from "siwe";

// For more information on each option (and a full list of options) go to
// https://next-auth.js.org/configuration/options
export default async function auth(req: any, res: any) {
  const providers = [
    CredentialsProvider({
      name: "Ethereum",
      credentials: {
        message: {
          label: "Message",
          type: "text",
          placeholder: "0x0",
        },
        signature: {
          label: "Signature",
          type: "text",
          placeholder: "0x0",
        },
      },
      async authorize(credentials) {
        try {
          const siwe = new SiweMessage(
            JSON.parse(credentials?.message || "{}")
          );
          const nextAuthUrl = new URL(process.env.NEXTAUTH_URL || "");

          const result = await siwe.verify({
            signature: credentials?.signature || "",
            domain: nextAuthUrl.host,
            nonce: await getCsrfToken({ req }),
          });

          if (result.success) {
            return {
              id: siwe.address,
            };
          }
          return null;
        } catch (e) {
          return null;
        }
      },
    }),
  ];

  const isDefaultSigninPage =
    req.method === "GET" && req.query.nextauth.includes("signin");

  // Hide Sign-In with Ethereum from default sign page
  if (isDefaultSigninPage) {
    providers.pop();
  }

  // eslint-disable-next-line no-return-await
  return await NextAuth(req, res, {
    // https://next-auth.js.org/configuration/providers/oauth
    providers,
    session: {
      strategy: "jwt",
    },
    secret: process.env.NEXTAUTH_SECRET,
    callbacks: {
      async session({ session, token }: { session: any; token: any }) {
        // eslint-disable-next-line no-param-reassign
        session.address = token.sub;
        // eslint-disable-next-line no-param-reassign
        session.user.name = token.sub;
        // eslint-disable-next-line no-param-reassign
        session.user.image = "https://www.fillmurray.com/128/128";
        return session;
      },
    },
  });
}

```
creemos nuestras variables de entorno, ahora para la Create a NEXTAUTH_SECRET puedes usar el siguiente comando `openssl rand -base64 32` pero yo te recomiendo usar el que te genera [GENERATE-SECRET](https://generate-secret.vercel.app/32)


```
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=clave generada 
```

ahora creamos nuestra carpeta app y creamos una folder llamada container donde crearemos las siguientes files
`wagmi.container.ts`

```tsx
import React from "react";
import { configureChains, createClient, WagmiConfig } from "wagmi";
import { mainnet, bsc, polygon, bscTestnet, goerli } from "wagmi/chains";
import { publicProvider } from "wagmi/providers/public";
import { InjectedConnector } from "wagmi/connectors/injected";

// Config
const { chains, provider } = configureChains(
  [mainnet, bsc, polygon, bscTestnet, goerli],
  [publicProvider()]
);

const client = createClient({
  autoConnect: true,
  connectors: [new InjectedConnector({ chains })],
  provider,
});

// Provider
const WagmiProvider: React.FC<{
  children: React.ReactNode;
}> = ({ children }) => {
  return <WagmiConfig client={client}>{children}</WagmiConfig>;
};

export default WagmiProvider;


```

and 
root.provider.ts

```tsx
"use client";

import React from "react";
import { Session } from "next-auth";
import { SessionProvider } from "next-auth/react";
import WagmiProvider from "./wagmi.container";

// Root Provider
function RootProvider({
  children,
  session,
}: {
  children: React.ReactNode;
  // eslint-disable-next-line react/require-default-props
  session?: Session;
}) {
  return (
    <WagmiProvider>
      <SessionProvider session={session} refetchInterval={0}>
        {children}
      </SessionProvider>
    </WagmiProvider>
  );
}

export default RootProvider;

```
creamos el middleware este archivo va al mismo nivel de la carpeta app 

```ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { getToken } from "next-auth/jwt";

export async function middleware(req: NextRequest) {
  const session = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });

  if (!session) {
    const requestedPage = req.nextUrl.pathname;
    const url = req.nextUrl.clone();
    url.pathname = `/`;
    url.search = `p=${requestedPage}`;
    return NextResponse.redirect(url);
  }

  return NextResponse.next();
}

// See "Matching Paths" below to learn more
export const config = {
  matcher: ["/home", ""], // array con todas las routas que quieres proteger
};

```

en este projecto uso tailwind pero puedes usar la liberia que te guste 

este es el componente para realizar el login 

```tsx
   <button
          // lassName="h-10 bg-blue-600 text-white px-6 rounded-full hover:bg-blue-800 transition-colors ease-in-out duration-200"
            type="button"
            onClick={(e) => {
              e.preventDefault();
              if (!isConnected) {
                connect();
              } else {
                handleLogin();
              }
            }}
          >
            Connect Wallet
          </button>
```

en la app creamos un page `app/home/page.tsx`

```tsx

import React from "react";
import { useSession } from "next-auth/react";
import { useDisconnect } from "wagmi";
import { signOut } from "next-auth/react";

function Home() {
  const { data: session } = useSession();
  const address = session?.user?.email ?? session?.user?.name;
  const { disconnect } = useDisconnect();
  const callbackUrl = "/";
  return (
    <div>
      <p>{address}</p>
<button
            type="button"
            onClick={(e) => {
              e.preventDefault();
              disconnect();
              signOut({
                redirect: true,
                callbackUrl,
              });
            }}
          >
            Disconnect Wallet
          </button>
    </div>
  );
}
```
hasta aqui tienes las bases para crear tu primera Dapp seguire subiendo tutoriales de como intreracturar con contratos y como crear tu propios smart contracts