做法
建立專案。
1 2
| npx create-next-app@latest cd next-auth-example
|
安裝依賴套件。
實作
建立 Provider
新增 components/Provider.js
檔。
1 2 3 4 5 6 7 8 9 10 11
| 'use client';
import { SessionProvider } from 'next-auth/react';
export default function Provider({ children }) { return ( <SessionProvider> {children} </SessionProvider> ); }
|
修改 layout.js
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import './globals.css' import { Inter } from 'next/font/google' import Provider from '@/components/Provider'
const inter = Inter({ subsets: ['latin'] })
export const metadata = { title: 'Create Next App', description: 'Generated by create next app', }
export default function RootLayout({ children }) { return ( <html lang="en"> <body className={inter.className}> <Provider> {children} </Provider> </body> </html> ) }
|
建立 API
新增 app/api/auth/[...nextauth]/route.js
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import NextAuth from 'next-auth'; import CredentialsProvider from 'next-auth/providers/credentials';
const handler = NextAuth({ pages: { signIn: '/sign-in', }, providers: [ CredentialsProvider({ async authorize({ email, password }) { if (email === '[email protected]' && password === 'password') { return { token: 'token', email }; } throw new Error('Invalid credentials'); }, }), ], callbacks: { async jwt({ token, user }) { if (user) { token.accessToken = user.token; } return token; }, async session({ session, token }) { session.accessToken = token.accessToken; return session; }, }, });
export { handler as GET, handler as POST };
|
建立 UI
修改 app/page.js
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 'use client';
import { useRouter } from 'next/navigation'; import { useEffect } from 'react'
export default function Home() { const router = useRouter(); useEffect(() => { router.push('/sign-in'); }, []); return ( <div /> ); }
|
新增 app/dashboard/page.js
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 'use client';
import { signOut, useSession } from 'next-auth/react'; import { redirect } from 'next/navigation';
export default function Dashboard() { const { data: session } = useSession();
console.log('session', session);
return ( <> <button type="button" onClick={() => signOut()} > Sign Out </button> </> ); }
|
新增 app/sign-in/page.js
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| 'use client';
import { signIn } from 'next-auth/react'; import { useRouter } from 'next/navigation'; import { useState } from 'react';
export default function SignIn() { const router = useRouter();
const [email, setEmail] = useState('[email protected]'); const [password, setPassword] = useState('password');
const submit = async (e) => { e.preventDefault(); const result = await signIn('credentials', { email, password, redirect: false, }); console.log(result); if (result.error) { alert(result.error); return; } router.push('/dashboard'); };
return ( <> <form onSubmit={submit}> <input type='text' placeholder="Email" defaultValue={email} onChange={(e) => setEmail(e.target.value)} /> <input type="password" placeholder="Password" defaultValue={password} onChange={(e) => setPassword(e.target.value)} /> <button type="button" onClick={submit} > Sign In </button> </form> </> ); }
|
新增 app/sign-out/page.js
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 'use client';
import { signOut, useSession } from 'next-auth/react'; import { useEffect } from 'react'; import { useRouter } from 'next/navigation';
export default function SignIn() { const router = useRouter(); const { data: session } = useSession();
useEffect(() => { (async () => { if (session) { await signOut({ redirect: false, }); } router.push('/sign-in'); })(); }, [router, session]);
return ( <div /> ); }
|
建立 Middleware
新增 .env
檔。
新增 middleware.js
檔。
1 2 3 4 5 6 7
| export { default } from 'next-auth/middleware';
export const config = { matcher: [ '/((?!api|sign-up|sign-in|forgot-password|sign-out|_next|.*\\..*|$).*)', ], };
|
啟動
啟動。
前往 http://localhost:8080 瀏覽。
程式碼
參考資料