next-auth 搭配 App Router 使用 cookies 等參數

前言

在 Next.Js 中,通常會搭配 next-auth 做權限驗證
而 Next 在 13.4.5 穩定 App Router 後,亦可將NextAuth改寫到 App Router 裡

在官方文件就有提供範例該如何撰寫
官方文件說需要 request, response時,仍得回歸 Page Router 寫法才可以
(官方推薦寫法見此處)

尤其搭配三方登入,會更期望能在callbacks: { ... }裡整合寫法,避免邏輯跳來跳去。若將 cookie 內的參數改成外傳進去的話
就會導致在 React Server Component(RSC) 使用await getServerSession(authOption)變得更加麻煩
因為會變成await getServerSession(authOption(參數)),等於每次使用都得帶上參數,盡管你的邏輯裡其實不需要他!

除非真的有比較特殊的操作
若只是單純需要cookiesheaders的話,其實仍可以繼續維持在 App Router 的寫法,不必再轉回 Page Router

作法

Next.Js 針對 App Router 有提供 cookies()headers() 可以直接在 React Server Component(RSC) 取得 cookies 與 headers
放在 App Router 的 api 裡亦可以取得

直接上 Code!

import type { NextApiRequest, NextApiResponse } from "next"
import NextAuth from "next-auth"
import { cookies, headers } from 'next/headers'


export const authConfig: AuthOptions = {
    providers: [
        GoogleProvider({
            clientId: process.env.GOOGLE_CLIENT_ID as string,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
        })
    ],
    secret: process.env.NEXTAUTH_SECRET,
    session: {
        strategy: 'jwt',
        maxAge: 12 * 60 * 60,
    },
    pages: {
        signIn: '/login',
    },
    callbacks: {
        async signIn({ user, account }) {
            const cookiesInstance = cookies();
            const headersInstance = headers();
            
            const example = cookiesInstance.get('example')?.value; 
            console.log(example); // 取得 cookie 裡的 example,若不存在則回傳 undefined
            const xForwardFor = headersInstance.get('x-forwarded-for'); 
            console.log(xForwardFor); // 取得 ip。若是 localhost 會是 '::1'。若不存在則回傳 undefined
            
            return true;
            
        },
        jwt({ token, user  }) { /** ...略... */}
        async session({ session, token }) {/** ...略... */}
    }
}

const handler = NextAuth(authConfig);

export { handler as GET, handler as POST }

上述範例亦可將 cookiesInstanceheadersInstance 獨立成 function 寫完相關邏輯後再 import 使用
但要特別注意,若在 Page Router call 這 function
cookies(), headers()會是 undefined,無法取得任何內容!
也就是僅限於 App Router 使用

若不打算轉換到 App Router,想要繼續保持 Page Router
則建議使用官方的advance initialization寫法來取得 cookie 與 headers

參考資料

next-auth 官方文件 / initialization