Getting NextAuth.js user session in Apollo Server context
Asked Answered
D

3

11

My web app is using:

  • NextJS
  • NextAuth.js
  • Apollo Server

I have a NextAuth set up in my app, and I am able to log in just fine.

The problem is coming from trying to get access to the user's session in the Apollo context. I want to pass my user's session into every resolver. Here's my current code:

import { ApolloServer, AuthenticationError } from "apollo-server-micro";
import schema from "./schema";
import mongoose from "mongoose";
import dataloaders from "./dataloaders";
import { getSession } from "next-auth/client";

let db;

const apolloServer = new ApolloServer({
  schema,
  context: async ({ req }) => {
    /*
    ...

    database connection setup
    
    ...
    */

    // get user's session
    const userSession = await getSession({ req });
    console.log("USER SESSION", userSession); // <-- userSession is ALWAYS null


    if (!userSession) {
      throw new AuthenticationError("User is not logged in.");
    }

    return { db, dataloaders, userSession };
  },
});

export const config = {
  api: {
    bodyParser: false,
  },
};

export default apolloServer.createHandler({ path: "/api/graphql" });

The problem is, the session (userSession) is always null, even if I am logged in (and can get a session just fine from a proper NextJS API route). My guess is that because the NextAuth function used to get the session, getSession({ req }) is being passed req--which is provided from Apollo Server Micro, and not from NextJS (which NextAuth is expecting). I've done a lot of searching and can't find anyone who's had this same problem. Any help is much appreciated!

Dressler answered 19/1, 2021 at 22:33 Comment(2)
If anyone happens upon this with using Auth0 + graphql: import { getSession } from '@auth0/nextjs-auth0' context: async args => { const session = await getSession(args.req) return { user: session.user } }Sclera
So perhaps did you try not passing req as an object, but directly? const userSession = await getSession( req )Sclera
M
8

I had exactly this issue and I found it was because of the Apollo GraphQL playground.

The playground does not send credentials without "request.credentials": "include".

My NextAuth / GraphQL API looks like this:

import { ApolloServer } from "apollo-server-micro";
import { getSession } from "next-auth/client";
import { typeDefs, resolvers } "./defined-elsewhere"

const apolloServer = new ApolloServer({
  typeDefs,
  resolvers,
  context: async ({ req }) => {
    const session = await getSession({ req });
    return { session };
  },
  playground: {
    settings: {
      "editor.theme": "light",
      "request.credentials": "include",
    },
  },
});

Hope this works for you!

Mayberry answered 21/2, 2021 at 23:29 Comment(2)
do you mind share your full code? I still not able to get req. Do you set any option when .createHandler?Edirne
I would still like to find a way to use getServerSession here instead of getSessionDihedron
B
1

I just ran into something similar. I'm not 100% sure because it's hard to know the exact details since your example code above doesn't show how you're interacting with apollo from the client before the session is coming through as null. I believe however that you're probably making an API call from inside the getStaticProps which causes static code generation and gets run at build time - ie when no such user context / session could possibly exist.

See https://github.com/nextauthjs/next-auth/issues/383

The getStaticProps method in Next.js is only for build time page generation (e.g. for generating static pages from a headless CMS) and cannot be used for user specific data such as sessions or CSRF Tokens.

Also fwiw I'm not sure why you got downvoted - seems like a legit question to ask imo even if the answer is mostly a standard rtm :). Has happened to me here before too - you win some you lose some :) Cheers

Brashear answered 29/1, 2021 at 3:23 Comment(2)
Hey, thanks! I wasn't expecting to get an answer :) I will investigate a little further with this in mind and report back.Dressler
No worries - I hope it's helpful :)Brashear
O
0

I was trying to get the session information of the currently logged in user in my ApolloServer context but was getting null as response from the getSession() function. So, I created my own function to basically get the session data from my NextAuth endpoint form the apollo server context.

src/index.ts

context: async ({ req }): Promise<GraphQLContext> => {
  const session = await getServerSession(req.headers.cookie);
  return { session: session as Session, prisma };
}

getServerSession.ts

import fetch from "node-fetch";

export const getServerSession = async (cookie: string) => {
  const res = await fetch('http://localhost/api/auth/session',{
    headers: { cookie: cookie },
  });
  const session = await res.json();
  return session;
};

I hope this helps everyone who is trying to get the session information in apollo server context while using next-auth for authentication purposes.

Offspring answered 26/4, 2023 at 16:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.