Search code examples
next.jsnext-auth

NextAuth Credential provider with apollo client?


Using NextAuth for GraphQL authentication with Apollo client in Next.js encounter the error

Hooks can only be called inside of the body of a function.

import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';
import { useMutation, useApolloClient } from '@apollo/client';
import { LOGIN_MUTATION } from '../../../graphql/mutations';
import { getErrorMessage } from '../../../lib';

export default (req, res) =>
    NextAuth(req, res, {
        providers: [
            Providers.Credentials({
                name: 'Credentials',
                credentials: {
                    identifier: { label: "Email", type: "text" },
                    password: { label: "Password", type: "password" }
                },
                authorize: async (credentials) => {
                    const client = useApolloClient();
                    const [errorMsg, setErrorMsg] = useState();
                    const [login] = useMutation(LOGIN_MUTATION);

                    try {
                        await client.resetStore();
                        const { data: { login: { user, jwt } } } = await login({
                            variables: {
                                identifier: credentials.identifier,
                                password: credentials.password
                            }
                        });            
            
                        if (user) {
                            return user;
                        }
            
                    } catch (error) {
                        setErrorMsg(getErrorMessage(error));
                    }
                }
            })
        ],
        site: process.env.NEXTAUTH_URL || "http://localhost:3000",
        session: {
            jwt: true,
            maxAge: 1 * 3 * 60 * 60,
            updateAge: 24 * 60 * 60,
        },
        callbacks: {},
        pages: {
            signIn: '/auth/signin'
        },
        debug: process.env.NODE_ENV === "development",
        secret: process.env.NEXT_PUBLIC_AUTH_SECRET,
        jwt: {
            secret: process.env.NEXT_PUBLIC_JWT_SECRET,
        }
    });

I am wondering is there anyway to make this work with apollo? Thank you for the helps.


Solution

  • As in the comments rightfully pointed out, you can't use hooks in server-side code. You would have to create a new ApolloClient like this:

    const client = new ApolloClient()
    

    Then you can do queries like this for example:

    const { data } = await client.query({
      query: "Your query",
      variables: { someVariable: true }
    });
    

    Best would be the to move the creation of the client to a separate external file as a function and import it in your server-side code whenever needed. Like done here for example.

    Edit:

    As @rob-art correctly remarks in the comments, for a [mutation][2], the code should look more like this:
    const { data } = await client.mutate({
      mutation: "Your query",
      variables: { someVariable: true }
    });