전반적인 세팅 방법
https://blog.bitsrc.io/adding-nextauth-to-nextjs-13-and-authenticating-with-github-40539ca6a81c
https://velog.io/@js43o/next-auth-간단한-사용법과-유의사항
api/auth/[...nextauth]/route.ts
import nextAuth, { NextAuthOptions } from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import GitHubProvider from 'next-auth/providers/github';
import CredentialsProvider from 'next-auth/providers/credentials';
import { PrismaAdapter } from '@auth/prisma-adapter';
import prisma from '@/prisma/client';
import bcrypt from 'bcrypt';
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
CredentialsProvider({
name: 'Credentials',
credentials: {
email: { label: 'Email', type: 'email', placeholder: 'Email' },
password: { label: 'password', type: 'password', placeholder: 'Password' },
},
async authorize(credentials, req) {
if (!credentials?.email || !credentials.password) return null;
const user = await prisma.user.findUnique({
where: { email: credentials.email },
});
if (!user) return null;
const passwordsMatch = await bcrypt.compare(credentials.password, user.hashedPassword!);
return passwordsMatch ? user : null;
},
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
],
session: {
strategy: 'jwt',
},
};
const handler = nextAuth(authOptions);
export { handler as GET, handler as POST };
'use client';
import { useSession } from 'next-auth/react';
import Link from 'next/link';
import React from 'react';
const Navbar = () => {
const { status, data: session } = useSession();
return (
<nav className='flex gap-4 p-4'>
<Link href={'/'}>Go to Home page</Link>
<Link href={'/users'}>Go to Users tab</Link>
<Link href={'/admin'}>Go to Admin tab</Link>
{status === 'authenticated' && (
<div>
{session.user!.name}
<Link href={'/api/auth/signout'} className='ml-4'>
로그아웃
</Link>
</div>
)}
{status === 'unauthenticated' && <Link href={'/api/auth/signin'}>로그인</Link>}
</nav>
);
};
export default Navbar;
import { getServerSession } from 'next-auth';
import ProductCard from './components/ProductCard/ProductCard';
import { authOptions } from './api/auth/[...nextauth]/route';
export default async function Home() {
const session = await getServerSession(authOptions);
return (
<main>
<h1>Hello {session && <span>{session.user!.name}</span>}</h1>
<ProductCard />
</main>
);
}
https://velog.io/@s_soo100/Next.js-13-Next-auth-커스텀-로그인-페이지-구현하기
authOptions에 pages를 추가한다.
pages: {
signIn: '/auth/signin',
signOut: '/auth/signout',
error: '/auth/error', // Error code passed in query string as ?error=
verifyRequest: '/auth/verify-request', // (used for check email message)
newUser: '/auth/new-user' // New users will be directed here on first sign in
}
해당 페이지를 만든다.
// 공식 문서 예제 코드
// app/auth/signin/page.tsx
import type {
GetServerSidePropsContext,
InferGetServerSidePropsType
} from 'next'
import { getProviders, signIn } from 'next-auth/react'
import { getServerSession } from 'next-auth/next'
import { authOptions } from '../[...nextauth]/route'
export default function SignInPage({
providers
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<>
{Object.values(providers).map(provider => (
<div key={provider.name}>
<button onClick={() => signIn(provider.id)}>
Sign in with {provider.name}
</button>
</div>
))}
</>
)
}
export async function getServerSideProps(context: GetServerSidePropsContext) {
const session = await getServerSession(context.req, context.res, authOptions)
if (session) {
return { redirect: { destination: '/' } }
}
const providers = await getProviders()
return {
props: { providers: providers ?? [] }
}
}
getServerSideProps
는 더이상 쓰지 않는다?signIn()
을 사용한다.