next-auth
next-auth copied to clipboard
Session not received as authenticated during a GET request
Provider type
Credentials
Environment
System: OS: Windows 10 10.0.19044 CPU: (4) x64 Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz Memory: 5.06 GB / 15.87 GB Binaries: Node: 14.17.5 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.17 - ~\AppData\Roaming\npm\yarn.CMD npm: 8.1.3 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Spartan (44.19041.1266.0), Chromium (99.0.1150.46) Internet Explorer: 11.0.19041.1566 npmPackages: next: ^12.0.10 => 12.0.10 next-auth: ^4.2.1 => 4.2.1 react: 17.0.2 => 17.0.2
Reproduction URL
https://github.com/ParidV/Dua-n-pu
Describe the issue
getSession returning null in Get requests, in POST request the session is okay.
Component
`export async function getServerSideProps(context) {
const res = await axios.get(`${process.env.API_URL}/company/jobs`);
return {
props: {
jobs: res.data.jobs,
},
};
}`
API Request api/company/jobs/index.js
import { getSession } from "next-auth/react";
export default async (req, res) => {
const { method } = req;
switch (method) {
case "GET":
try {
const session = await getSession({ req });
console.log(session + " SESSION "); //RETURN NULL
console.log(JSON.stringify(session));
const jobs = await prisma.jobs.findMany({
where:{
userId: session.id
}
});
return res.status(200).json({ success: true, jobs });
} catch (error) {
return res.status(404).json({
success: false,
message: error.message,
});
}
How to reproduce
In POST request, the session is okay, but when I make a get request to get the ID from the server to pass in the axios request come as NULL.
Expected behavior
It should return the session
I've setup a quick reproduction based on your API route code provided above and it seems to work for me. It will return null
if you're unauthenticated. However, if you copy a request "as curl" out of your browsers network dev tools (when authenticated) which includes the token/cookie and modify the URL to the api route, I got a response and the dev server terminal logged the session successfully.
Can you double check the GET
requests you're making are actually also authenticated (i.e. including the cookie or authorization header?
I can confirm that with the GET
request, authenticated does not receive the session.
I tried with POST
on This request and it works perfectly.
I created a job from the POST
request and I received this by console.log(session)
{
user: { name: 'Company', email: '[email protected]' },
expires: '2022-04-22T19:23:39.673Z',
id: 2,
name: 'Company',
surname: 'Surname',
email: '[email protected]',
role: 2
}
I tried a POST
request from postman and it says that I am not logged in, which is okay, but when I am authenticated from my project, the session is retrieved successfully.
So this problem happens only with GET
This is the request from cuRL from the get request:
curl "http://localhost:3000/company/jobs" ^
-H "Connection: keep-alive" ^
-H "sec-ch-ua: ^\^" Not A;Brand^\^";v=^\^"99^\^", ^\^"Chromium^\^";v=^\^"99^\^", ^\^"Google Chrome^\^";v=^\^"99^\^"" ^
-H "sec-ch-ua-mobile: ?0" ^
-H "sec-ch-ua-platform: ^\^"Windows^\^"" ^
-H "DNT: 1" ^
-H "Upgrade-Insecure-Requests: 1" ^
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36" ^
-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" ^
-H "Sec-Fetch-Site: none" ^
-H "Sec-Fetch-Mode: navigate" ^
-H "Sec-Fetch-User: ?1" ^
-H "Sec-Fetch-Dest: document" ^
-H "Accept-Language: en-US,en;q=0.9,de-DE;q=0.8,de;q=0.7,sq;q=0.6" ^
-H "Cookie: _ga=GA1.1.622907214.1643984174; next-auth.csrf-token=c2db1395200a91b1915039666fe73b4d36a5fd49a430dffac15d0d704b6613dc^%^7C07336a24d0a4cc0a2dd92548d698de66d84e5f3daf1e28b5592e3a2cb9ee871f; next-auth.callback-url=http^%^3A^%^2F^%^2Flocalhost^%^3A3000^%^2F; next-auth.session-token=eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..k5rKQz-UT6gGL2O8.381fW_sK8GZ-zo8PA3gS1V7xmwBvpYMc_EkgNx9wcbxKh9KsHGVe1adOrIUfexJeoxpP_WpBc1rpp3BIUdlPcLPCbmgor_WjHLbRhmOLQd7mW2bZN8C7DyZm3JlUdBCX6iIpOicYeNJSI6dtooVQkC136X1izbyaP3E92z56CiKbEhLVLd0o-SZZItreAvWXD04RjlqAhAmqovvwrcB-A1POYDxfsw2rR3Vf.UQuUbRZhvGPXwDV8nJB7Zg" ^
--compressed
Okay, alternatively you can give our experimental getServerSession
a try. Something like this:
import { getServerSession } from "next-auth/next";
import { authOptions } from './auth/[...nextauth]'
export default async (req, res) => {
const { method } = req;
switch (method) {
case "GET":
try {
const session = await getServerSession({req, res}, authOptions)
console.log("SESSION", session)
res.status(200).json({
message: "Success",
session
})
} catch (error) {
console.error(error);
res.status(500).json({ error: error.message });
}
}
}
I was also able to get this ^^ to successfully work.
We've released it as a preview in the latest release, and there are two open PRs which provide more documentation for it which you can take a look at:
- https://github.com/nextauthjs/next-auth/pull/4116
- https://github.com/nextauthjs/next-auth/pull/3982
Thank you for your reply, but what is authOptions because referring to my [...nextauth.js] and I do not have a authOptions, in this way can you double check the procedure if the authentication is done correctly (for security issues or any other problem such as GET request, even though I think has nothing to do with [..nextauth].js )
import NextAuth from "next-auth";
import CredentialProvider from "next-auth/providers/credentials";
import axios from "axios";
export default NextAuth({
providers: [
CredentialProvider({
name: "credentials",
async authorize(credentials) {
try {
const user = await axios.post(
`${process.env.API_URL}/auth/authentication/login`,
{
email: credentials.email,
password: credentials.password,
}
);
if (!user.data.user) {
return null;
}
if (user.data.user) {
return {
id: user.data.user.id,
name: user.data.user.name,
surname: user.data.user.surname,
email: user.data.user.email,
role: user.data.user.role,
};
}
} catch (error) {
console.error(error);
}
},
}),
],
callbacks: {
jwt: ({ token, user }) => {
if (user) {
token.id = user.id;
token.name = user.name;
token.surname = user.surname;
token.email = user.email;
token.role = user.role;
}
// Here, check the token validity date
if (token.tokenExpiration < Date.now()) {
// Call the endpoint where you handle the token refresh for a user
const user = axios.post(
`${process.env.API_URL}/auth/authentication/refresh`,
{
refreshToken: token.refreshToken,
}
);
// Check for the result and update the data accordingly
return { ...token, ...user };
}
return token;
},
session: ({ session, token }) => {
if (token) {
session.id = token.id;
session.name = token.name;
session.surname = token.surname;
session.email = token.email;
session.role = token.role;
}
return session;
},
},
secret: process.env.SECRET_KEY,
jwt: {
secret: process.env.SECRET_KEY,
encryption: true,
maxAge: 5 * 60 * 1000,
},
pages: {
signIn: "/auth/login",
},
});
I also gave a try with getServerSession, but still no success.
API request
const session = await getServerSession({ req, res }, authOptions);
console.log(session);
console.log("SESSION", session);
if (!session) {
return res.status(401).json({
message: "You are not logged in",
});
}
[..nextauth].js
import NextAuth from "next-auth";
import CredentialProvider from "next-auth/providers/credentials";
import axios from "axios";
export const authOptions = {
providers: [
CredentialProvider({
name: "credentials",
async authorize(credentials) {
try {
const user = await axios.post(
`${process.env.API_URL}/auth/authentication/login`,
{
email: credentials.email,
password: credentials.password,
}
);
if (!user.data.user) {
return null;
}
if (user.data.user) {
return {
id: user.data.user.id,
name: user.data.user.name,
surname: user.data.user.surname,
email: user.data.user.email,
role: user.data.user.role,
};
}
} catch (error) {
console.error(error);
}
},
}),
],
callbacks: {
jwt: ({ token, user }) => {
if (user) {
token.id = user.id;
token.name = user.name;
token.surname = user.surname;
token.email = user.email;
token.role = user.role;
}
// Here, check the token validity date
if (token.tokenExpiration < Date.now()) {
// Call the endpoint where you handle the token refresh for a user
const user = axios.post(
`${process.env.API_URL}/auth/authentication/refresh`,
{
refreshToken: token.refreshToken,
}
);
// Check for the result and update the data accordingly
return { ...token, ...user };
}
return token;
},
session: ({ session, token }) => {
if (token) {
session.id = token.id;
session.name = token.name;
session.surname = token.surname;
session.email = token.email;
session.role = token.role;
}
return session;
},
},
secret: process.env.SECRET_KEY,
jwt: {
secret: process.env.SECRET_KEY,
encryption: true,
maxAge: 5 * 60 * 1000,
},
pages: {
signIn: "/auth/login",
},
};
export default NextAuth(authOptions);
I have created a new project to test that and it is still with the same problem,
- First I have authenticated
- Visited http://localhost:3000/api/hello
- Still the session was null
@formerskulk4 getSession()
or getServerSession()
will return you null
if the user is not authenticated. Have you verified that the user is logged in when calling the function?
I am positive that the user is authenticated, it is weird because when POST
request is used there is no null returned.
Hey im having this problem as well the user is authenticated
i'm seeing a next-auth.session-token on cookies as well but when i try to request GET on getServerSideProps it will return me null on getSession on Handler(/api)
but if i use client side fetching it works perfectly
my code
/api/tasks/index.js
const handler = async (req, res) => {
if (req.method === "GET") {
const session = await getSession({ req });
if (!session) {
res.status(401).json({ message: "Not Authenticated" });
return;
}
const userId = session.user.id;
const client = await connectDb();
const db = client.db();
const tasks = await db
.collection("tasks")
.find({ user_id: userId })
.toArray();
res.status(200).json(tasks);
}
};
index.js
export const getServerSideProps = async (context) => {
const res = await fetch(`http://localhost:3000/api/tasks`);
const data = await res.json();
return {
props: { data },
};
};
where i fetch here now i get a message: "Not Authenticated" (i'm logged in 100% sure)
useEffect works perfectly fine(client fetching)
useEffect(() => {
const fetchData = async () => {
const res = await fetch(`http://localhost:3000/api/tasks`);
const data = await res.json();
console.log(data);
};
fetchData();
}, []);
@markmendozadev
When you use the POST
request does it work? Because I am having the same issue, I am positive that the user is authenticated however here returns null on the server side.
use this code in your _app.js :
function MyApp({Component, pageProps}) { return ( <SessionProvider session={pageProps.session}> <Component {...pageProps} /> </SessionProvider> ); }
@jaminecode I have already that.
export default function App({ Component, pageProps }) { return ( <SessionProvider session={pageProps.session}> <Component {...pageProps} /> </SessionProvider> ); }
Hi @ParidV Yes i think i found my answers already but not 100% sure. It works on client-side because getSession works on client-side requests.
if you do a request on your api through client side (not using any next data fetching just pure react it will 100% work) i mean the authentication.
now i did a little digging and here's what i found (https://github.com/nextauthjs/next-auth/pull/4116)
@jaminecode my _app.js already like that
import "../styles/globals.css";
import { SessionProvider } from "next-auth/react";
import Layout from "../components/layout/Layout";
function MyApp({ Component, pageProps: { session, ...pageProps } }) {
return (
<SessionProvider session={session}>
<Layout>
<Component {...pageProps} />
</Layout>
</SessionProvider>
);
}
export default MyApp;
@markmendozadev maybe this is a late response, but I faced the same issue with POST method, I could access the session, but not with POST, after doing some research, I found this is because NextJS does not send the cookies in the header for GET method, so I fixed the issue like this:
`let res = await fetch("http://localhost:3000/api/posts", { method: "GET", headers: {
"Content-Type": "application/json",
// I have to add cookie in the GET
Cookie: context.req.headers.cookie,
},
});`