next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

[4.24.6] Redirect after OAuth SignUp not working

Open RicSala opened this issue 11 months ago • 3 comments

Environment

Environment System: OS: macOS 13.5 CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz Memory: 392.10 MB / 32.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 20.10.0 - ~/.nvm/versions/node/v20.10.0/bin/node npm: 10.5.0 - ~/Documents/Projects/supercopy/node_modules/.bin/npm Browsers: Brave Browser: 111.1.49.132 Chrome: 123.0.6312.59 Safari: 16.6 npmPackages: @auth/prisma-adapter: ^1.0.11 => 1.0.11 next: ^14.0.3 => 14.0.4 next-auth: ^4.24.6 => 4.24.6 react: ^18 => 18.2.0

Reproduction URL

https://github.com/RicSala/perbrand/blob/main/auth.ts

Describe the issue

When the user signs up using credentials provider, they get redirected to the callbackUrl as expected.

But when the user signsup (first time signin that creates a user in my database) with OAuth provider, they get redirected to http://localhost:3000/?callbackUrl=http%3A%2F%2Flocalhost%3A3000%2Fapp%2Fsaved instead of the callbackUrl itself.

The callbackUrl is in the url as a search param which makes me think there is an error somewhere.

My auth config:


export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
async profile(profile, tokens) {

            const newSettings = await db.settings.create({
                data: {},
            });

            return {
                id: profile.sub,
                name: profile.name,
                email: profile.email,
                image: profile.picture,
                settingsId: newSettings.id,
            };
        },
    }),

    CredentialsProvider({
        name: 'credentials',
        credentials: {
            email: { label: 'Email', type: 'text', placeholder: ' ' },
            password: { label: 'Password', type: 'password' },
        },
        async authorize(credentials) {
            if (!credentials?.email || !credentials?.password) {
                throw new Error('Missing credentials');
            }

            const user = await getUserByEmail(credentials.email);

            if (!user || !user?.hashedPassword) {
                throw new Error('Invalid credentials Custom');
            }

            const isCorrectPassword = await bcrypt.compare(
                credentials.password,
                user.hashedPassword
            );

            if (!isCorrectPassword) {
                throw new Error('Invalid credentials Custom');
            }

            return user;
        },
    }),

  
],

pages: {
    signIn: '/',
    newUser: '/',
    error: '/auth/signin',
},

debug: process.env.NODE_ENV === 'development',
jwt: {
},

session: {
    maxAge: 30 * 24 * 60 * 60,
    strategy: 'jwt',

},

callbacks: {
    async signIn({ user, account, profile, email, credentials }) {
        if (account?.provider !== 'email') return true;

        const userExists = await db.user.findUnique({
            where: { email: user.email! },
        });
        if (userExists) {
            return true;
        } else {
            return false;
        }
    },



    async jwt({ token, user, account, profile, session, trigger }) {
        console.log({ token });
        console.log({ user });
        console.log({ account });
        console.log({ profile });
        console.log({ session });
        console.log('trigger-->', { trigger });

        if (trigger === 'update' && session.brands) {
            token.brands = session.brands;
        }

        if (user) {
            const dbUser = await db.user.findUnique({
                where: { id: user.id },
            });

            const linkedinAccountLinked = !!(await db.account.findFirst({
                where: {
                    userId: dbUser!.id,
                    provider: 'linkedin',
                },
            }));

            const brandsOfUser = await db.brand.findMany({
                where: {
                    authorId: user.id,
                },
            });

            token.hasAccountLinked = linkedinAccountLinked;
            token.id = user.id;
            token.email = user.email;
            token.name = user.name;
            token.settingsId = dbUser?.settingsId;
            token.brands = brandsOfUser;
        }

        return token;
    },

    async session({ session, token, user }) {
        if (session && session.user) {
        }
        return {
            ...session,
            user: {
                ...session.user,
                id: token.id,
                role: token.role,
                settingsId: token.settingsId,
                hasAccountLinked: token.hasAccountLinked,
                brands: token.brands,
            },
        };
    },
},

events: {
    async createUser({ user }) {
        console.log('User created EVENT', user);
    },
    async linkAccount(message) {
        console.log('Account linked EVENT', message);
    },
    async signIn(message) {
        console.log('Sign in EVENT', message);
    },
},
} satisfies NextAuthOptions;

My signin button:


<Button
variant='outline'
type='button'
className='w-full'
onClick={async () => {
const res = await signIn('google', {
callbackUrl: '/app/saved',
redirect: true,
});
}}
>
Google


What I have tried so far:

Printed the baseUrl and Url using the redirect callback, and the url printed is /app/saved as expected (thus the issue sees to be with the later user creation)

Completely removed the redirect callback, to check that is not that I am interfering in the default behaviour. It didn't fix it.

Auth options are here: https://github.com/RicSala/perbrand/blob/main/auth.ts

Auth button is here: https://github.com/RicSala/perbrand/blob/main/components/auth/social.tsx

Thank you.

How to reproduce

Try to signup with any OAuth provider

Expected behavior

Redirects to the callbackUrl

RicSala avatar Mar 22 '24 12:03 RicSala

Any update on this or way to make it move forward?

RicSala avatar Apr 07 '24 16:04 RicSala

Something is wrong with your Prisma related code. The following code is not valid.

const newSettings = await client.settings.create({
     data: {},
})

JasperAlexander avatar Apr 21 '24 19:04 JasperAlexander

redirect is true by default and redirectTo is used for the url to redirect to. but it doesn't work either :(

const res = await signIn('google', {
  redirectTo: '/app/saved',
});

tonyspb avatar Jun 24 '24 21:06 tonyspb