Luca Federzoni
Luca Federzoni

Reputation: 75

Profile and account undefined inside jwt callback function for next-auth

I'm having an issue defining my jwt callback. I have this auth.ts file

import NextAuth, { Profile, User, Account, Session } from "next-auth";
import { JWT } from "next-auth/jwt"
import GitHubProvider from "next-auth/providers/github";
import { client } from "./sanity/lib/client";
import { AUTHOR_BY_GITHUB_ID_QUERY } from "./sanity/lib/queries";
import { writeClient } from "./sanity/lib/write-client";

export const authOptions = {
    providers: [
        GitHubProvider({
            clientId: process.env.GITHUB_ID,
            clientSecret: process.env.GITHUB_SECRET
        })
    ],
    callbacks: {
        async signIn({ user, profile }: { user: User; profile?: Profile }): Promise<boolean> {
            const { id, login, bio } = profile ?? {};
            const { name, email, image } = user;

            // Check if user exists based on GitHub ID
            const existingUser = await client.fetch(AUTHOR_BY_GITHUB_ID_QUERY, { id });

            // If user doesn't exist, create them in the database
            if (!existingUser) {
                await writeClient.create({
                    _type: 'author',
                    id,
                    name,
                    username: login,
                    email,
                    image,
                    bio: bio || ''
                });
            }

            // Returning the `id` inside the JWT during the first sign-in
            // Return true to allow sign-in, this will trigger `jwt` callback to add `id` to token
            return true;
        },
        async jwt({ token, account, profile }: {
            token: JWT,
            account: Account | null,
            profile?: Profile,
        }): Promise<any> {

            // Log account and profile to check if they are populated here
            console.log('JWT Callback - Account:', account);
            console.log('JWT Callback - Profile:', profile);
            console.log('JWT Callback - Token:', token);
            
            if (account && profile) {
                const user = await client.withConfig({ useCdn: false }).fetch(AUTHOR_BY_GITHUB_ID_QUERY, { id: profile.id });
                token.id = user?._id;
            }

            return token;
        },
        async session({ session, token}: { session: Session, token: JWT }): Promise<any> {
            session.id = token.id as string;
            return session;
        }
    }
};

export const { handlers, signIn, signOut, auth } = NextAuth(authOptions);

but my logs are always giving me that profile and account are undefined. I don't really understand what's the matter with that.

I need those to be defined in order to set the id of the token with a type augmentation equal to the id of the user in my database in sanity in order to set it also in the session that I then retrieve with

const session = await auth();

please I'm trying to follow a guide on the internet on how to implement this stuff so I'm still learning but I can't figure out what's missing since my code is the same as the github repository. I tried to reach out to the content creator of the guide but while I'm waiting I want to also ask the community.

Thanks everyone.

Upvotes: 0

Views: 25

Answers (1)

Luca Federzoni
Luca Federzoni

Reputation: 75

It looks like the jwt function is called on every request. When I sign in it is called with the value defined and in the subsequent calls I get undefined values. The fix for this is to set the token id in the first call and the carry it over on the subsequent ones:

async jwt({ token, user, account, profile }: { token: JWT; user?: User; account?: Account; profile?: Profile }): Promise<JWT> {
            // On the initial sign-in, account/profile (or user) are available
            if ((account || profile || user) && !token.id) {
                // You can choose to use user.id if it exists, or profile.id
                token.id = profile?.id || token.id;
                console.log("JWT Callback (initial) - Set token.id:", token.id);
            } else {
                // On subsequent calls, account/profile will be undefined, and token.id will already be set
                console.log("JWT Callback (subsequent) - token.id remains:", token.id);
            }
            return token;
        },

hope it might be usefull to someone else

Upvotes: 1

Related Questions