Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getSession() returns null because request body is sent to next-auth url #7167

Closed
clueleaf opened this issue Apr 6, 2023 · 5 comments
Closed
Labels
triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@clueleaf
Copy link

clueleaf commented Apr 6, 2023

Environment

System:
OS: macOS 13.3
CPU: (10) arm64 Apple M1 Pro
Memory: 1.49 GB / 32.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 18.14.1 - /usr/local/bin/node
Yarn: 1.22.18 - /opt/homebrew/bin/yarn
npm: 9.3.1 - /usr/local/bin/npm
Browsers:
Chrome: 111.0.5563.146
Firefox: 111.0.1
Safari: 16.4

Reproduction URL

none

Describe the issue

After updated to v4.21.1, await getSession({ req }) started to return null for POST API requests, with following logs.

[next-auth][error][CLIENT_FETCH_ERROR] 
https://next-auth.js.org/errors#client_fetch_error undefined {
  error: {},
  url: 'http://localhost:3000/api/auth/session',
  message: undefined
}

It appeared that this change is causing the issue when body is added to the request to next-auth api route. (When I manually removed these lines, the problem got solved.)

if (req?.body) {
options.body = JSON.stringify(req.body)
options.method = "POST"
}

How to reproduce

Here's my [...nextauth].ts (only essential parts):

const adapter = DynamoDBAdapter(client, {
  tableName: //...
});

export default NextAuth({
  providers: [
    OktaProvider({
      // ...
    }),
  ],
  adapter: adapter,
  session: {
    strategy: "database",
  },
  callbacks: {
    async session({ session }) {
      return {
        ...session,
        user: {
          name: session.user?.name ?? "",
          email: session.user?.email ?? "",
        },
      };
    },
  },
});

Expected behavior

getSession returns session instead of null;

@clueleaf clueleaf added the triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. label Apr 6, 2023
@clueleaf
Copy link
Author

clueleaf commented Apr 6, 2023

Using getServerSession instead solves the problem. Closing for now.

@clueleaf clueleaf closed this as completed Apr 6, 2023
@therecluse26
Copy link

therecluse26 commented Apr 7, 2023

@clueleaf I don't think getServerSession is adequate. I tried that in an API endpoint and it returns the following error. Further, this solution will require everyone to refactor their existing codebases to replace getSession. I think this is a real bug that should be fixed.

230640180-714a9cbb-390d-4bf9-837a-a0efda750b60

Please reopen, thanks!

therecluse26 added a commit to therecluse26/takeitaway that referenced this issue Apr 7, 2023
@clueleaf
Copy link
Author

clueleaf commented Apr 8, 2023

@therecluse26 Are you passing req, res and authOptions to getServerSession?
I'm doing something like this and it is working fine.

In pages:

// /pages/path/index.tsx
import { GetServerSideProps } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../api/auth/[...nextauth]";

export const getServerSideProps: GetServerSideProps = async (context) => {
  const session = await getServerSession(context.req, context.res, authOptions);
  // ...
}

In API route:

// /pages/api/path/index.ts
import { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]";

export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise<void> {
  const session = await getServerSession(req, res, authOptions);
  // ...
}

Also see: https://next-auth.js.org/tutorials/securing-pages-and-api-routes#server-side

@ZilatAIOBC
Copy link

If you are not able to get session use gettoken instead
In authOption file

 secret: process.env.NEXTAUTH_SECRET as string,
  callbacks: {
                   async signIn(user:any) {
                              if (user) {
                                const data = await axios.post(`${process.env.NEXTAUTH_URL}/api/sign_in_create_account`, user);
                                if (data) {
                                  return user;
                                }
                            } else {
                              // Return false if login failed
                              console.log("Login failed");
                              return "/auth/signup";
                            }
                  },
                  async jwt({ token, account, profile,user }) {
                    // Persist the OAuth access_token and or the user id to the token right after signin
                    if (account) {
                      token.accessToken = account.access_token
                       token.id = user.id
                    }
                  return token;
    },

Keys and URL

generate your NEXTAUTH_SECRET key from
# Only for production – generate one here: https://generate-secret.vercel.app/32
and Url for local
NEXTAUTH_URL=http://localhost:3000

this is api route for calling token

import { getToken } from "next-auth/jwt"
export const GET = async (req) => {
  
  const session = await getToken({ req, secret:process.env.NEXTAUTH_SECRET })

  return NextResponse.json(
      { message: "GET Property Error", session },
      { status: 200 }
    );
  }

and the in your layout/page

const MainLayout = ({ children }) => {
  // Data Calling
  const [session, setSession] = useState(false);

  useEffect(() => {
    const fetch = async () => {
      if (!session) {
        const response = await axios.get("/api/auth/token");
        if (response.data.session) {
          setSession(true);
        }
      }
    };
    fetch();
  });
return (
    <>
      {session ? (
     // write code when session exist
) : (
     // write code when session is not there
      )}
    </>
  );
};

export default MainLayout;

@jvmhonorato
Copy link

create file: ' .eslintrc.json ' in the root of the application with the following contents:

{
  "env":{"browser": true, "node":true, "es6":true},
  "extends": ["eslint:recommended","next/core-web-vitals"]
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

4 participants