Open WesleyKapow opened 9 months ago
I don't have a lot to add except to say it's not just you. Thank you for sharing code that reproduces the issue!
In case this helps anyone else, my problem was that I hadn't fully adapted the @auth0/nextjs-auth0
example to the app router. I needed to return handleLogin
, not just await it.
import { handleAuth, handleLogin } from "@auth0/nextjs-auth0"
import { NextApiRequest, NextApiResponse } from "next"
export const GET = handleAuth({
async login(req: NextApiRequest, res: NextApiResponse) {
const returnToQuery = req.query?.returnTo
const returnTo = typeof returnToQuery === "string" ? returnToQuery : "/"
return await handleLogin(req, res, {
returnTo
})
},
})
Hello Guy, I also have the same issue on my configuration that was working better on local and prod 1m ago but now it broken
Here is the error on my side : ⨯ Error: No response is returned from route handler 'D:\develop\summit-landingpage\src\app\api\auth[...nextauth]\route.ts'. Ensure you return a Response
or a NextResponse
in all branches of your handler.
My code code
import { PrismaClient } from '@prisma/client'; import { type NextApiRequest, type NextApiResponse } from 'next'; import NextAuth, { type NextAuthOptions, type Profile } from 'next-auth'; import CredentialsProvider from 'next-auth/providers/credentials'; import GoogleProvider from 'next-auth/providers/google'; interface GoogleProfile extends Profile { given_name?: string; family_name?: string; picture?: string; }
const prisma = new PrismaClient();
if (!process.env.GOOGLE_CLIENT_ID || !process.env.GOOGLE_CLIENT_SECRET) { console.error( 'Missing required environment variables: GOOGLE_CLIENT_ID or GOOGLE_CLIENT_SECRET' ); process.exit(1); }
const clientId = process.env.GOOGLE_CLIENT_ID; const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
const options: NextAuthOptions = { providers: [ GoogleProvider({ clientId, clientSecret, }), CredentialsProvider({ name: 'Email', credentials: { email: { label: 'Email', type: 'email', placeholder: 'john.doe@example.com', }, },
async authorize(credentials) {
if (!credentials?.email) {
throw new Error('Please provide the email');
}
const user = await prisma.user.findUnique({
where: { email: credentials.email },
});
if (user) {
return {
id: user.id.toString(),
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
};
}
return null;
},
}),
], callbacks: { async signIn({ user, account, profile }) { const email = user.email;
let firstName = '';
let lastName = '';
let pictureUrl = '';
if (account?.provider === 'google') {
const googleProfile = profile as GoogleProfile;
firstName = googleProfile.given_name ?? '';
lastName = googleProfile.family_name ?? '';
pictureUrl = googleProfile.picture ?? '';
}
let userId: number | null = null;
if (email) {
try {
let existingUser = await prisma.user.findUnique({
where: { email },
});
if (existingUser) {
if (account?.provider === 'google') {
await prisma.user.update({
where: { email },
data: {
firstName,
lastName,
pictureUrl,
},
});
}
userId = existingUser.id;
} else {
if (account?.provider === 'google') {
existingUser = await prisma.user.create({
data: {
email,
firstName,
lastName,
pictureUrl,
},
});
userId = existingUser.id;
}
}
if (userId !== null) {
user.id = userId.toString();
return true;
}
} catch (error) {
console.error('Error creating or updating user:', error);
return false;
}
}
return true;
},
async jwt({ token, user }) {
if (user?.id) {
token.uid = user.id;
}
return token;
},
async session({ session, token }) {
if (token.uid) {
const user = await prisma.user.findUnique({
where: { id: Number(token.uid) },
});
if (user) {
session.user = {
id: user.id.toString(),
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
};
}
}
return session;
},
}, };
const nextAuthHandler = async (req: NextApiRequest, res: NextApiResponse) => { console.log('Checking res properties:', res); console.log('Checking req properties:', req); try { await NextAuth(req, res, options); } catch (error) { console.error('NextAuth error:', error); } };
export const GET = async (req: NextApiRequest, res: NextApiResponse) => { try { await nextAuthHandler(req, res); } catch (error) { console.error('Error handling GET request:', error); res.status(500).json({ error: 'Error in GET request' }); } };
export const POST = async (req: NextApiRequest, res: NextApiResponse) => { try { await nextAuthHandler(req, res); } catch (error) { console.error('Error handling POST request:', error); res.status(500).json({ error: 'Error in POST request' }); } };
If there is someone with my solution kindly share, I need your support
@GhislainMitahi try using code snippets, when submitting code. it helps with indentation and it's easy to read
Link to the code that reproduces this issue
https://github.com/luthfib/auth0-nextjs-repro/tree/fetch-issue
To Reproduce
.env.example
to.env
and set it up for an auth0 accountpnpm install
pnpm run build
pnpm run start
Current vs. Expected behavior
I expect auth to work and to be redirected correctly back to the main page.
Instead their's a 500 and server shows:
Verify canary release
Provide environment information
Which area(s) are affected? (Select all that apply)
App Router
Additional context
Next error is from https://github.com/vercel/next.js/blob/6ed4fddf8a55f956ca6a714e081a384880d45e52/packages/next/src/server/future/route-modules/app-route/module.ts#L367
Cross-fetch overriding of
Response
object: https://github.com/lquixada/cross-fetch/blob/v4.x/src/node-polyfill.js#L8In testing, I setup some console logs and used a WeakMap/objectId trick to verify that the
Response
object is indeed getting changed due to the polyfill. This happens after Next has definedNextResponse
so the nextResponse object inherits from the original Response and not the polyfill version. This causesres instaceof Response
to fail. For more on this see https://nextjs-forum.com/post/1163946577388380171