I'm using next-auth v. 4.18.8 in my login page. This is the final project of my Fullstack JS course. I'm using a newer version than the one used in the course (next-auth v. 3 is used)
When I insert the correct password, everything works as it should (it redirects me to the desired page).
Inserting the wrong password should throw me to /auth/signin?i=1 so I can handle this query. However, it redirects me to http://127.0.0.1:3000/api/auth/error?error=Request%20failed%20with%20status%20code%20401
On console, it shows "POST http://localhost:3000/api/auth/callback/credentials? 401 (Unauthorized)"
Here's my code:
Frontend: Login Page
const handleFormSubmit = async values => {
signIn('credentials', {
email: values.email,
password: values.password,
callbackUrl: 'http://127.0.0.1:3000/user/dashboard'
})
}
Frontend: [...nextauth].js
export const authOptions = {
providers: [
CredentialsProvider({
name: 'credentials',
async authorize(credentials, req) {
const res = await axios.post('http://127.0.0.1:3000/api/auth/signin', credentials)
const user = res.data
if (user) {
return user
} else {
throw '/auth/signin?i=1'
}
}
})
],
session: {
jwt: true
},
jwt: {
secret: process.env.JWT_TOKEN
},
adapter: MongooseAdapter(process.env.MONGODB_URI)
}
export default NextAuth(authOptions)
Backend: signin.js controller
const authSignin = {
post: async (req, res) => {
const {
name,
email,
password,
} = req.body
await dbConnect()
const user = await UsersModel.findOne({ email })
if (!user) {
return res.status(401).json({ success: false, message: "invalid" })
}
const passIsCorrect = await compare(password, user.password)
if (passIsCorrect) {
return res.status(200).json({
_id: user._id,
name: user.name,
email: user.email
})
}
return res.status(401).json({ success: false, message: "invalid" })
}
}
export { authSignin }
Finally: Backend: signin.js routes (using Next Connect):
import nextConnect from 'next-connect'
import { authSignin } from '../../../src/controllers/auth/signin'
const route = nextConnect()
route.post(authSignin.post)
export default route
One thing I noticed is that when inserting a wrong password, when the code reaches this line on controller:
return res.status(401).json({ success: false, message: "invalid" })
It wont continue to execute the [...nextauth].js file after axios.post, therefore not executing the code below, which should give me the 'i' query to handle on frontend (as stated in next-auth documentation):
if (user) {
return user
} else {
throw '/auth/signin?i=1'
}
The repository is on GitHub
I think if you pass redirect:false
here
const handleFormSubmit = async values => {
signIn('credentials', {
email: values.email,
password: values.password,
callbackUrl: 'http://127.0.0.1:3000/user/dashboard',
redirect: false,
})
}
Looks like when next-auth
encounters an error, it automatically redirects. By setting the redirect
option it will not automatically redirect so you could handle the error on client side like this
const handleFormSubmit = async values => {
const signInResult=signIn('credentials', {
email: values.email,
password: values.password,
callbackUrl: 'http://127.0.0.1:3000/user/dashboard',
redirect: false,
})
If (signInResult.error){
// Handle Error on client side
}
}
Also you should not make api request in authorize
. it will delay the process. you could run the signin logic inside the authorize