Reputation: 91
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"
}
Upvotes: 9
Views: 7538
Reputation: 1916
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.
Upvotes: 0
Reputation: 1
Trying adding the NEXTAUTH_SECRET
environment variable and using it in your authOptions. It worked for me.
https://next-auth.js.org/deployment
Upvotes: 0
Reputation: 92
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
}
})
Upvotes: 4
Reputation: 530
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.
Upvotes: 13
Reputation: 11
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.
Upvotes: 1