Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting NextAuth.js user session in Apollo Server context

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!

like image 734
Nolan P Avatar asked Jan 19 '21 22:01

Nolan P


2 Answers

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!

like image 113
Mike Avatar answered Nov 10 '22 22:11

Mike


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

like image 29
J.Wolfe Avatar answered Nov 10 '22 21:11

J.Wolfe