简体   繁体   中英

Next.js / NextAuth: Why can't I access session in API route

I'm new to Next.js and even newer to NextAuth, so I may be missing something obvious. I'm using the next-auth email provider as a magic link. I am able to authenticate and redirect. I can see the cookies in the Application tab of the Chrome dev tools. I can console log the session in my home page getServerSideProps() like so:

const session = await unstable_getServerSession(context.req, context.res, authOptions)

All of this is working fine...but then when I hit a protected route, the session is null and I get a 401. Here is partial 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.
}

Here is my [...nextauth].ts file:

// 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);

Here is the page that makes the API request (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

Thank you in advance.

...well folks, I believe I found my answer here on Stack Overflow: https://stackoverflow.com/a/69058105/1500241 One must explicitly set cookies when making an HTTP request on the server side!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM