next-auth
next-auth copied to clipboard
[4.24.6] Redirect after OAuth SignUp not working
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
Any update on this or way to make it move forward?
Something is wrong with your Prisma related code. The following code is not valid.
const newSettings = await client.settings.create({
data: {},
})
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',
});