Your question
Cannot POST /api/auth/callback/credentials
What are you trying to do
Whenever I try to log in, I get the post error.
Feedback
Documentation refers to searching through online documentation, code comments and issue history. The example project refers to next-auth-example.
<form method='post' action='/api/auth/callback/credentials' className="account-form">
For example, when I try to get the csrf token, it works fine.
NextAuth config:
const options = {
site: 'http://localhost:3000/api/auth',
providers: [
Providers.Credentials({
name: 'Credentials',
credentials: {
username: { label: "Username", type: "text", placeholder: "" },
password: { label: "Password", type: "password" }
},
authorize: async (credentials) => {
const user = { id: 1, name: 'J Smith', email: '[email protected]' }
if (user) {
return Promise.resolve(user)
} else {
return Promise.resolve(null)
}
}
})
],
callbacks: {
signIn: async (user, account, profile) => {
return Promise.resolve(true)
},
session: async (session, user) => {
session.foo = 'bar' // Add property to session
return Promise.resolve(session)
},
credentials: async( user,acount,profile) => {
return Promise.resolve(true)
},
redirect: async (url, baseUrl) => {
return url.startsWith(baseUrl)
? Promise.resolve(url)
: Promise.resolve(baseUrl)
}
},
session: {
jwt: true,
},
jwt: {
secret: "secret",
encryption: true
},
database: {
type: 'mysql',
host: process.env.DB_HOST,
port: 3306,
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_TABLE
},
debug: true,
}
I tried everything, and also the documentation doesn't help since I can't find what I'm looking for particularly.
You can find a couple of examples of ways you can create a custom credentials sign in page:
https://next-auth.js.org/configuration/pages#credentials-sign-in
You can find a couple of examples of ways you can create a custom credentials sign in page:
https://next-auth.js.org/configuration/pages#credentials-sign-in
In my nextauth config I have
pages: {
signIn: '/login',
}
and I have that page located in pages/login.js, is that correct?
The form looks like this:
<form method='post' action='/api/auth/callback/credentials' className="account-form">
<input name='csrfToken' type='hidden' defaultValue={csrfToken}/>
<div className="form-group">
<label htmlFor="sign-up">Email lub Nazwa Użytkownika</label>
<input type="text" placeholder="Email lub Login" name="username"/>
</div>
<div className="form-group">
<label htmlFor="pass">Hasło</label>
<input type="password" placeholder="Hasło" name="password"/>
<span className="sign-in-recovery">
<a href="reset-password.html">Zapomniałeś hasła?</a>
</span>
</div>
<div className="form-group text-center">
<button type="submit" className="mt-2 mb-2">Zaloguj</button>
</div>
</form>
That looks like broadly the right approach - we'd need the full source and the specific error to be able to help if you are getting an error. Have you tried copying and pasting the example page, and seeing if that works for you?
I was having the same issue, but I found a solution today. Here are the general steps I took:
id property to the Credential providersignIn in my form instead of action and methodExample pages/api/[...nextAuth].js
const options = {
// Configure one or more authentication providers
providers: [
Providers.Credentials({
id: "username-login", // <- add this line
name: "Login",
authorize: async (credentials) => {
const user = {};
return Promise.resolve(user);
},
credentials: {
username: { label: "Username", type: "text ", placeholder: "username" },
password: {
label: "Password",
type: "password",
placeholder: "a-really-long-password",
},
},
}),
],
pages: {
signIn: "/login",
},
};
Then in pages/login.js:
import { useState } from "react";
import Layout from "@components/layout";
import { signIn, getSession } from "next-auth/client";
export default function Login() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
// "username-login" matches the id for the credential
signIn("username-login", { username, password });
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">Username</label>
<input
id="username"
name="username"
type="text"
placeholder="Username"
onChange={(e) => setUsername(e.target.value)}
value={username}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
id="password"
name="password"
type="password"
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
value={password}
/>
</div>
<button type="submit">
Login
</button>
</form>
);
}
That looks like broadly the right approach - we'd need the full source and the specific error to be able to help if you are getting an error. Have you tried copying and pasting the example page, and seeing if that works for you?
I will try now as the solution @kyrelldixon has provided hasn't worked for me.
Edit: Yup, the example from the website doesn't work as well.
It keeps showing the POST error(Cannot POST /api/auth/callback/credentials)
Could the issue be that my website is on a custom express server? But I'm still getting the providers and the csrf token so I don't know if I'm right here.
I'm using a custom express server with next-auth.
It works now.
// server.js
:
const nextApp = next({ dev });
const handle = nextApp.getRequestHandler();
:
app.get('*', (req, res) => {
return handle(req, res);
});
// ↓↓↓ add route for post method
app.post('*', (req, res) => {
return handle(req, res);
});
// ↑↑↑ add route for post method
:
// /pages/api/auth/[...nextauth].js
:
session: {
// ↓↓↓ add
jwt: true,
// ↑↑↑ add
},
:
// /pages/api/auth/[...nextauth].js
:
// ↓↓↓ add config export
export const config = {
api: {
bodyParser: false,
},
}
// ↑↑↑ add config export
export default (req, res) => NextAuth(req, res, options)
because I already use bodyParser on express.
// server.js
:
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
:
@kobuchin1 potentially work scenario for me, however, I have concerns on the POST method to accept any type of URL. for example some people have an API installed in the system, like me, is it not going to give a treat to the system to post anything that you want?
@gyto Oh..you are right.
I tried to narrow down the tolerances to just next-auth api.
app.post('/api/auth/*', (req, res) => {
return handle(req, res);
});
But I don't have security knowledge much.
Can someone please correct me?