As a newcomer to Next.js and NextAuth, I might be overlooking something obvious here. Currently, I am using the next-auth email provider for a magic link authentication process. The authentication and redirection are working smoothly as I can see the cookies in the Application tab of Chrome dev tools. In my home page's getServerSideProps()
, I am able to console log the session like this:
const session = await unstable_getServerSession(context.req, context.res, authOptions)
Everything seems to be functioning properly until I try to access a protected route where the session is null, resulting in a 401 error. Below is a snippet of code for a protected route:
import prisma from 'Utilities/PrismaClient'
import { logDBError } from 'Utilities'
import { unstable_getServerSession } from 'next-auth/next'
import { authOptions } from 'pages/api/auth/[...nextauth]'
export default async function handler (req, res) {
const session = await unstable_getServerSession(req, res, authOptions)
console.log(`SESSION_FROM_BOARD_ROUTE: ${JSON.stringify(session)}`) // SESSION_FROM_BOARD_ROUTE: null
const token = await getToken({ req })
if (!session) {
console.log(401)
return res.status(401).json({ board: {}, tasks: [] })
}
...
// GET
// POST
// etc, etc.
}
This is how my [...nextauth].ts
file looks like:
// src/pages/api/auth/[...nextauth].ts:
import NextAuth from 'next-auth'
import EmailProvider from "next-auth/providers/email";
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import prisma from 'Utilities/PrismaClient'
import type { NextAuthOptions } from 'next-auth'
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
providers: [
EmailProvider({
server: {
host: process.env.EMAIL_SERVER_HOST,
port: process.env.EMAIL_SERVER_PORT,
auth: {
user: process.env.EMAIL_SERVER_USER,
pass: process.env.EMAIL_SERVER_PASSWORD
}
},
from: process.env.EMAIL_FROM
}),
],
}
export default NextAuth(authOptions);
Furthermore, here is the page responsible for making API requests (handleFetchData):
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import Board from 'Components/Screens/Board/Board'
import { useRouter } from 'next/router'
import axios from 'axios'
import { getBaseUrl } from 'Utilities'
import { hydrateTasks } from 'Redux/Reducers/TaskSlice'
const BoardPage = (props) => {
const router = useRouter()
const dispatch = useDispatch()
useEffect(() => {
async function handleRouteChange() {
const { boardId } = router.query
const { board, tasks } = await handleFetchData({ boardId })
dispatch(hydrateTasks({ board, tasks }))
}
handleRouteChange()
}, [router])
return (
<Board {...props}/>
)
}
const handleFetchData = async ({boardId, req}) => {
const baseUrl = getBaseUrl(req)
return axios.get(`${baseUrl}/api/board/${boardId}`, {
withCredentials: true
})
.then(({data}) => data)
.catch(err => { console.log(err)})
}
export async function getServerSideProps ({ query, req }) {
const { boardId } = query
const { board, tasks} = await handleFetchData({boardId, req}) ?? {}
return { props: { board, tasks } }
}
export default BoardPage
Your help is greatly appreciated.