9

I'm new to NextJS and Next-Auth. I'm trying to write a secure api route that is only available if a user is logged in. I sucessfully accessing the session on the client side using useSession() but when I try to implement the logic in an api route the session always returns null. I have tried to copy the simpliest example from the docs. Am I missing something?

Here is my route in src/pages/api/users/getUser.ts:

import { getServerSession } from 'next-auth/next'
import { authOptions } from '../auth/[...nextauth]'
import { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const session = await getServerSession(req, res, authOptions)
  console.log('session', session)

  if (session) {
    res.send({ content: 'SUCCESS' })
  } else {
    res.send({ error: 'ERROR' })
  }
}

Here is my authOptions in src/pages/api/auth/[...nextauth].ts

import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github'
import { PrismaAdapter } from '@next-auth/prisma-adapter'
import prisma from '../../../../prisma/db/prismadb'

export const authOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_ID || '',
      clientSecret: process.env.GITHUB_SECRET || '',
    }),
  ],
  pages: {
    signIn: '/',
    signOut: '/',
  },
}

export default NextAuth(authOptions)

Here are my dependencies:

 "dependencies": {
    "@next-auth/prisma-adapter": "^1.0.5",
    "@next/font": "13.1.6",
    "@prisma/client": "^4.10.1",
    "@types/node": "18.11.19",
    "@types/react": "18.0.27",
    "@types/react-dom": "18.0.10",
    "axios": "^1.3.2",
    "dotenv-cli": "^7.0.0",
    "eslint": "8.33.0",
    "eslint-config-next": "13.1.6",
    "next": "13.1.6",
    "next-auth": "^4.19.2",
    "prisma": "^4.9.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "styled-components": "^5.3.6",
    "typescript": "4.9.5"
  },
  "devDependencies": {
    "@types/styled-components": "^5.1.26"
  }
2
  • I am facing exactly same issue. Did you figure out? Commented Mar 1, 2023 at 17:08
  • Here is the solution in this post answers: stackoverflow.com/a/76655327/13084168 Commented Aug 6, 2023 at 10:45

5 Answers 5

14

If you're calling the API route from a server component, the cookies are not passed via fetch by default, so you have to send the headers through your API call.

So you can do this:

import { headers } from "next/headers"

const response = await fetch("api/posts", {
  method: "GET",
  headers: headers()
})

Note that if you're in a server component, you don't have to call the API, you can do the stuff directly like fetching data from database or other things.

Sign up to request clarification or add additional context in comments.

3 Comments

This was the fix for me thank you
Nextjs app router is poorly documented. It took me a while to find your answer, and I'm glad I did! Thanks.
Thank you so much! This information and solution was a game changer for me, after hours of trying different stuff.
5

Using headers: headers() might give you some error when deploying to vercel. I got this error ReadonlyHeadersError: Headers cannot be modified..

I solved the problem by sending Cookie with the request like this,

import { headers } from "next/headers"

const headersList = headers();
const cookie = headersList.get('cookie');

const response = await fetch("api/posts", {
  method: "GET",
  headers: {
    'Cookie': cookie
  }
})

1 Comment

Thank you! Very helpful. In my case, the error was also in invalid fetch, I need to write 'web.app/api/posts', ...
2

In my case, when NEXTAUTH_URL is 127.0.0.1 and API is requested to localhost, the session is null.

So, I solved the problem by matching the NEXTAUTH_URL with the request URL.

1 Comment

this is why AI could never replace human. thanks buddy
0

Trying adding the NEXTAUTH_SECRET environment variable and using it in your authOptions. It worked for me.

https://next-auth.js.org/deployment

Comments

0

For debugging purpose remove pages first

  pages: {
    signIn: '/',
    signOut: '/',
  },
``

Create a button which triggers signin method.

Access session like this

const session = getServerSession(authOptions) console.log({session})



I do not know about pages beacuse I could not configure it for my use so I have been using the default sign in page provided by next-auth.

But what I have mention works fine and returns session in clients and server both.

If above solution works then try sending requests. No need to pass headers or authorization.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.