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

How do you use this properly with Next Auth? #44

Closed
jnovak-SM2Dev opened this issue Jun 26, 2023 · 7 comments
Closed

How do you use this properly with Next Auth? #44

jnovak-SM2Dev opened this issue Jun 26, 2023 · 7 comments

Comments

@jnovak-SM2Dev
Copy link

I'm trying to figure out how to use this properly with Next Auth. I put what I have below, it does work, but I don't think it's correct and the client side has to keep calling to get the token on each call, which seems wrong. Any suggestions or samples would be incredibly helpful.

layout.tsx

import { ApolloWrapper } from "../lib/apolloProvider";
import "./globals.css";
import { Inter } from "next/font/google";
import { NextAuthProvider } from "./providers";
import { getSession } from "next-auth/react";
import { NextSessionProvider } from "./nextsessionprovider";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <NextAuthProvider>
          <NextSessionProvider>
            <header>
              My Website
              <nav></nav>
            </header>
            <main>{children}</main>
          </NextSessionProvider>
        </NextAuthProvider>
      </body>
    </html>
  );
}

NextAuthProvider

"use client";

import { SessionProvider } from "next-auth/react";

type Props = {
  children?: React.ReactNode;
};

export const NextAuthProvider = ({ children }: Props) => {
  return <SessionProvider>{children}</SessionProvider>;
};

NextSessionProvider

import { SessionProvider, getSession } from "next-auth/react";
import { ApolloWrapper } from "../lib/apolloProvider";
import { getServerSession } from "next-auth";

type Props = {
  children?: React.ReactNode;
};

export const NextSessionProvider = async ({ children }: Props) => {
  return <ApolloWrapper>{children}</ApolloWrapper>;
};

ApolloWrapper

"use client";

import {
  ApolloClient,
  ApolloLink,
  HttpLink,
  SuspenseCache,
} from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
import {
  ApolloNextAppProvider,
  NextSSRApolloClient,
  NextSSRInMemoryCache,
  SSRMultipartLink,
} from "@apollo/experimental-nextjs-app-support/ssr";
import { getSession } from "next-auth/react";
import { PropsWithChildren, useCallback } from "react";

const authLink = setContext(async (_, { headers }) => {
  const session = await getSession();
  const modifiedHeader = {
    headers: {
      ...headers,
      authorization: session?.jwt
        ? `Bearer ${session.jwt}`
        : `Bearer ${process.env.NEXT_PUBLIC_API_TOKEN}`,
    },
  };
  return modifiedHeader;
});

function makeClient() {
  const httpLink = new HttpLink({
    uri: process.env.NEXT_PUBLIC_API_URL,
    fetchOptions: { cache: "no-store" },
  });

  return new NextSSRApolloClient({
    cache: new NextSSRInMemoryCache(),
    link:
      typeof window === "undefined"
        ? ApolloLink.from([
            new SSRMultipartLink({
              stripDefer: true,
            }),
            authLink,
            httpLink,
          ])
        : ApolloLink.from([authLink, httpLink]),
  });
}

function makeSuspenseCache() {
  return new SuspenseCache();
}

export function ApolloWrapper({ children }: PropsWithChildren) {
  return (
    <ApolloNextAppProvider
      makeClient={makeClient}
      makeSuspenseCache={makeSuspenseCache}
    >
      {children}
    </ApolloNextAppProvider>
  );
}

client.ts

import {
  ApolloClient,
  HttpLink,
  InMemoryCache,
  createHttpLink,
  from,
} from "@apollo/client";
import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rsc";
import { getSession } from "next-auth/react";
import { setContext } from "@apollo/client/link/context";
import { getServerSession } from "next-auth";
import { authOptions } from "../app/authOptions";

const httpLink = createHttpLink({
  uri: process.env.NEXT_PUBLIC_API_URL,
  fetchOptions: { cache: "no-store" },
});

const authLink = setContext(async (_, { headers }) => {
  const session = await getServerSession(authOptions);
  const modifiedHeader = {
    headers: {
      ...headers,
      authorization: session?.jwt
        ? `Bearer ${session.jwt}`
        : `Bearer ${process.env.NEXT_PUBLIC_API_TOKEN}`,
    },
  };
  return modifiedHeader;
});

export const { getClient } = registerApolloClient(() => {
  return new ApolloClient({
    cache: new InMemoryCache(),
    link: from([authLink, httpLink]),
  });
});
@phryneas
Copy link
Member

You might have encountered a regression that we had in 0.3.0 - could you please try it with 0.3.1 that I just released?

@jnovak-SM2Dev
Copy link
Author

@phryneas Sorry, had to switch away from the app folder since there are a lot of issues with plugins. I have a test app i'll test this with later day.

@jnovak-SM2Dev
Copy link
Author

jnovak-SM2Dev commented Jul 11, 2023

@phryneas From what I can tell both getSession() and getServerSession(authOptions) still call the session endpoint on each call.

@Tanish2002
Copy link

@phryneas An example with next-auth would be useful.
My config is identical to @SM2DevLLC.
I'm not sure if this is even related to next-auth but I've been trying to use useSuspenseQuery but I've been getting a weird error:

 ⨯ node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@apollo/client/errors/errors.cjs (33:0) @ new ApolloError
 ⨯ ApolloError: Cannot read properties of null (reading 'user')
    at new Promise (<anonymous>)
    at Array.forEach (<anonymous>)

I'm not able to trace back why it was created.
It works fine if I simply do a useQuery.

@phryneas
Copy link
Member

phryneas commented Sep 25, 2023

@Tanish2002 two different things ^^

  • if you provide a runnable repository using next-auth, I can take a look and see if I can point things out, but I haven't used that one myself yet.
  • I think this is a separate issue. Generally, please make sure to import useSuspenseQuery from this package, not from @apollo/client. If the problem persists, please open a separate issue and provide some kind of reproduction.

@phryneas
Copy link
Member

I'm doing some housekeeping so I'm closing some older issues that haven't seen activity in a while.
If this is still relevant, please feel free to reopen the issue.

Copy link
Contributor

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants