What is next auth?
NextAuth is a library that lets you do authentication
in Next.js
Can you do it w/o next-auth - Yes
Should you - Probably not!
Popoular choices while doing auth include -
External provider -
Firebase auth
- In house using cookies
- NextAuth
Why not use JWT + localstorage?
Next.js is slightly different from React + Express apps
Express app
NextJS app
NextAuth
Nextjs lets you add Authentication
to your Next.js app
It supports various
providers
Login with email
Login with google
Login with facebook
…
Catch all routes
If you want to add a single route handler for
/api/auth/user
/api/auth/random
/api/auth/123
/api/auth/...
You can create a catch all
route
- Create a simple next.js app
npx create-next-app@latest
- Create
app/api/auth/[...nextauth]/route.ts
import { NextRequest, NextResponse } from "next/server"
export function GET(req: NextRequest) {
return NextResponse.json({
message: "Handler"
})
}
- Try going to a few endpoints
http://localhost:3000/api/auth/signin
http://localhost:3000/api/auth/123
http://localhost:3000/api/auth/random/random2
- Try logging the sub-route you’re at
import { NextRequest, NextResponse } from "next/server"
export function GET(req: NextRequest, { params }: { params: { nextauth: string[] } }) {
console.log(params.nextauth[0])
return NextResponse.json({
message: "Handler"
})
}
Give NextAuth access to a catch-all
Ref https://next-auth.js.org/configuration/initialization#route-handlers-app
- Create
/api/auth/[…nextauth]/route.ts
- Install next-auth
npm install next-auth
- Updated handler
import NextAuth from "next-auth"
const handler = NextAuth({
...
})
export { handler as GET, handler as POST }
Adding providers - There are three broad types of providers
OAuth (Login with google)
Email (Passwordless Email login via email OTP)
Credentials (your own strategy)
Let’s them one by one
Credentials provider
This lets you create your own authentication strategy
For example
- Email + Password
- Phone number
- Login with Metamask
Steps to follow
- Add a credentials provider
import NextAuth from "next-auth"
import CredentialsProvider from 'next-auth/providers/credentials';
const handler = NextAuth({
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
username: { label: 'email', type: 'text', placeholder: '' },
password: { label: 'password', type: 'password', placeholder: '' },
},
async authorize(credentials: any) {
return {
id: "user1"
};
},
})
],
secret: process.env.NEXTAUTH_SECRET
})
export { handler as GET, handler as POST }
- Add NEXTAUTH_URL to
.env
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=password_nextauth
- Update
App.tsx
to have a simple Appbar
"use client";
import { signIn, signOut } from "next-auth/react"
export const Appbar = () => {
return <div>
<button onClick={() => signIn()}>Signin</button>
<button onClick={() => signOut()}>Sign out</button>
</div>
}Click
- Add
providers.tsx
'use client';
import React from 'react';
import { SessionProvider } from 'next-auth/react';
export const Providers = ({ children }: { children: React.ReactNode }) => {
return (
<SessionProvider>
{children}
</SessionProvider>
);
};
- Wrap
layout
withProviders
import { Providers } from "./provider";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<Providers>
{children}
</Providers>
</body>
</html>
);
}
- Get the user details in the top level
page.tsx
(client component)
"use client"
import { useSession } from "next-auth/react";
export default function Home() {
const session = useSession();
return (
<div>
{JSON.stringify(session.data?.user)}
</div>
);
}
- Get the user details on the server (server component)
import { getServerSession } from "next-auth"
async function getUser() {
const session = await getServerSession();
return session;
}
export default async function Home() {
const session = await getUser();
return (
<div>
{JSON.stringify(session?.user?.name)}
</div>
);
}
- Get user in an api route (/api/user)
import { getServerSession } from "next-auth"
import { NextResponse } from "next/server";
export async function GET() {
const session = await getServerSession();
return NextResponse.json({
name: session?.user?.name
})
}
- Persist more data (user id) (Ref https://next-auth.js.org/getting-started/example#using-nextauthjs-callbacks) (Ref https://next-auth.js.org/configuration/callbacks)
callbacks: {
jwt: async ({ user, token }: any) => {
if (user) {
token.uid = user.id;
}
return token;
},
session: ({ session, token, user }: any) => {
if (session.user) {
session.user.id = token.uid
}
return session
}
},
- Move auth config to
lib/auth.ts
https://github.com/nextauthjs/next-auth/issues/7658#issuecomment-1683225019
import CredentialsProvider from 'next-auth/providers/credentials';
export const NEXT_AUTH_CONFIG = {
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
username: { label: 'email', type: 'text', placeholder: '' },
password: { label: 'password', type: 'password', placeholder: '' },
},
async authorize(credentials: any) {
return {
id: "user1",
name: "asd",
userId: "asd",
email: "ramdomEmail"
};
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
callbacks: {
jwt: async ({ user, token }: any) => {
if (user) {
token.uid = user.id;
}
return token;
},
session: ({ session, token, user }: any) => {
if (session.user) {
session.user.id = token.uid
}
return session
}
},
}
Adding Google Provider
Ref https://next-auth.js.org/providers/google