I'm wondering on how to pass the next-auth session as context to my nexus queries. The reson behind is that I want the sessions email to retrieve data from my database with nexus. I'm also using Apollo Server and next-connect here.
Here's what I tried:
The Apollo Server
import { ApolloServer } from "apollo-server-micro";
import { MicroRequest } from 'apollo-server-micro/dist/types';
import { ServerResponse } from 'http';
import { getRequestOrigin } from './../../server/get-request-origin';
import handler from "../../server/api-route";
import prisma from "../../server/db/prisma";
import { schema } from "../../server/graphql/schema";
export const config = {
api: {
bodyParser: false,
},
};
export interface GraphQLContext {
session?: {
user: {
name: string
email: string
image: string
},
expires: Date // This is the expiry of the session, not any of the tokens within the session
};
prisma: typeof prisma;
origin: string;
}
const apolloServer = new ApolloServer({
schema,
context: ({ req }): GraphQLContext => ({
session: req.user,
origin: getRequestOrigin(req),
prisma,
}),
})
const startServer = apolloServer.start();
export default handler().use((req: MicroRequest, res: ServerResponse) => {
startServer.then(() => {
apolloServer.createHandler({
path: "/api",
})(req, res);
});
});
My middleware to pass the session:
import { NextApiRequest, NextApiResponse } from "next";
import { Session } from 'next-auth';
import cookieSession from "cookie-session";
import { error } from "next/dist/build/output/log";
import { getSession } from 'next-auth/react';
import nc from "next-connect";
import { trustProxyMiddleware } from "./trust-proxy-middleware";
export interface Request extends NextApiRequest {
user?: Session | null;
}
const COOKIE_SECRET = process.env.COOKIE_SECRET;
/**
* Create an API route handler with next-connect and all the necessary middlewares
*
* @example
* ```ts
* export default handler().get((req, res) => { ... })
* ```
*/
function handler() {
if (!COOKIE_SECRET)
throw new Error(`Please add COOKIE_SECRET to your .env.local file!`);
return (
nc<Request, NextApiResponse>({
onError: (err, _, res) => {
error(err);
res.status(500).end(err.toString());
},
})
// In order for authentication to work on Vercel, req.protocol needs to be set correctly.
// However, Vercel's and Netlify's reverse proxy setup breaks req.protocol, which the custom
// trustProxyMiddleware fixes again.
.use(trustProxyMiddleware)
.use(
cookieSession({
name: "session",
keys: [COOKIE_SECRET],
maxAge: 24 * 60 * 60 * 1000 * 30,
// Do not change the lines below, they make cy.auth() work in e2e tests
secure:
process.env.NODE_ENV !== "development" &&
!process.env.INSECURE_AUTH,
signed:
process.env.NODE_ENV !== "development" &&
!process.env.INSECURE_AUTH,
})
)
.use(async (req: Request, res: NextApiResponse) => {
const session = await getSession({ req })
if (session) {
// Signed in
console.log("Session", JSON.stringify(session, null, 2))
} else {
// Not Signed in
res.status(401)
}
res.end()
})
);
}
export default handler;
And the nexus query
const queries = extendType({
type: "Query",
definition: (t) => {
t.field("currentUser", {
type: "User",
resolve: (_, __, ctx) => {
console.log(ctx);
if (!ctx.session?.user.email) return null;
return prisma.user.findUnique({
where: {
email: ctx.session?.user.email,
},
});
},
});
},
});