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

Unexpected Modification of User Object in Next.js Authentication Callback #10593

Open
loki4514 opened this issue Apr 15, 2024 · 1 comment
Open
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@loki4514
Copy link

loki4514 commented Apr 15, 2024

Environment

I'm facing an issue with user authentication in a Next.js application using NextAuth. I have implemented a custom signIn callback for Google OAuth authentication, where I check if the user exists in the database and return it if found. However, I'm encountering unexpected behavior where the user object seems to be modified or overwritten.

Example in Database i have already have record name : ijk email : abc@gmail.com

when i use google login, name : abc email : abc@gmail.com

since the email already exists it should return {name: ikj, email: abc@gmail.com} instead it returns {name : abc, email : abc@gmail.com}, which is an unexpected behaviour. {name : abc, email : abc@gmail.com} this getting stored in authprovider and in backend returns the status code of 401

async signIn is the main fucntion of google outh

Reproduction URL

https://github.com/loki4514/Blog-App

Describe the issue

export const authOptions: NextAuthOptions = {
    providers: [
        CredentialsProvider({
            name: "crendentials",
            credentials: {},
            async authorize(credentials, req): Promise<any> {
                const { email, password } = credentials as {
                    email: string;
                    password: string;
                };
                try {
                    const user = await User.findOne({ email })
                    if (!user) {
                        // Assuming you have access to the response object 'res'
                        return null
                    }

                    const comparedpassword: boolean = await bcryptjs.compare(password, user.password)
                    if (!comparedpassword) {
                        return null
                    }
                    return user;
                    
                } catch (error: any) {
                    console.log("Error:", error)
                    return null
                }
            }

        }),
        GoogleProvider({
            clientId: GOOGLE_CLIENT_ID! as string,
            clientSecret: GOOGLE_CLIENT_SECRET! as string
        })
    ],

    session: {
        strategy: 'jwt'
    },

    callbacks: {

        async signIn({ user, account }: { user: any; account: any }) {
            if (account.provider === "google" && user) {
                try {
                    
                    const { name, email }: { name: string; email: string } = user;
                    const existingUser = await User.findOne({ email });
                    if (existingUser) {
                        return existingUser; // Return existing user
                    }
        
                    const newUser = new User({
                        name: name,
                        email: email,
                        isVerified: true 
                    });

                    const savedUser = await newUser.save();
        
                    return savedUser; // Return the newly created user
                } catch (error) {
                    console.error("Error in Google OAuth signIn callback:", error);
                    return null; 
                }
            }
        else {
        // not hiting the else block
            console.log("why is i'm getting called here")
            return user;

        }
        
        },
  
        async jwt({ token, user }) {
            if (user) {
                console.log(user,"this failed in every aspect of my life 0001")
                // i should existingUser object but i'm not getting it
                token.email = user.email
                token.name = user.name
                token.id = user.id
              
            }
            if (!user) 
                token.error = "Invalid Credentials"
                token.errorStatus = 401; // Set error status code
            }
            return token
        },
        async session({ session, token }: { session: any, token: any }) {
            if (session.user) {
                session.user.email = token.email;
                session.user.name = token.name;
                session.user.id = token.id;
                
            }
            return session

        }
    },
    secret: process.env.NEXTAUTH_SECRET!,
    pages: {
        signIn: '/login'
    }

}

const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }`

How to reproduce

Currently i working in local repository

Expected behavior

Despite returning the existing user if found, the user object appears to be modified, causing inconsistencies in authentication. I've ensured that there are no explicit variable reassignments within the callback function.

I've tried debugging the issue, but I'm unable to identify the root cause. Could someone please help me understand why the user object is being modified unexpectedly and suggest how to resolve this issue?

Any insights or suggestions would be greatly appreciated. Thanks in advance!

here is stackoverflow question
Link

@loki4514 loki4514 added bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Apr 15, 2024
@JasperAlexander
Copy link
Contributor

You should retrieve the user in the jwt callback with token.email. Then you can use it to set the token entries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

2 participants