I had a problem in double posting the form with csrf enabled.
In my setup: mobile autocomplete was posting the form automatically, but before redirecting if I click submit as all fields are filled it was giving error... But I was already logged in with error. I don't know how to stop user clicking submit button if autofill is already posted the form and waiting for page loading.
First form submits in success and if somehow you are sending same form second time csrf is became void then error message is sent. But user logged-in in the back.
<form action="/login/password" method="post">
<section>
<label for="username">User Name :</label>
<input id="username" name="username" type="text" autocomplete="username" required autofocus>
</section>
<section>
<label for="current-password">Password :</label>
<input id="current-password" name="password" type="password" autocomplete="current-password" required>
</section>
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button class="btnSign" type="submit">Sign In</button>
</form>
router.use(function (req, res, next) {
res.header("Cache-Control", "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0");
next();
});
passport.use(
new LocalStrategy(function verify(username, password, cb) {
conn.query("SELECT * FROM users WHERE username = ?", [username], function (err, row) {
if (err) {
return cb(err);
}
if (!row.length) {
return cb(null, false, {
message: "Incorrect username or password.",
});
}
//sanitize password input length. (in congfig.js)
if (locals.maxPasswordLength < password.length) {
password = password.substring(0, Math.min(password.length, locals.maxPasswordLength));
}
crypto.pbkdf2(password, row[0].salt, 310000, 64, "sha512", function (err, hashedPassword) {
if (err) {
return cb(err);
}
if (!crypto.timingSafeEqual(row[0].hashed_password, hashedPassword)) {
return cb(null, false, {
message: "Incorrect username or password.",
});
}
return cb(null, row[0]);
});
});
})
);
router.post(
"/login/password",
passport.authenticate("local", {
successReturnToOrRedirect: "/dothisonsuccess",
failureRedirect: "/login",
keepSessionInfo: false,
failureMessage: true,
})
);
router.get("/dothisonsuccess", function (req, res, next) {
if (req.cookies.getSessionReturn) {
res.clearCookie("getSessionReturn");
return res.redirect(req.cookies.getSessionReturn);
}
return res.redirect("/");
});
This doesnt happen on desktop. When i autofill the fields using chrome password manager all fields are filled and browser waiting for me to click submit. But in android samsung phone i click inputfield, pop up appears and i select user for this site. then as soon as i click username to fill the form it starts submitting. I did not notice it was submitting the form and i quickly click submit after selecting user. Then error happens.
I am using these and many others. But i think its on autofill posting without triggering anything in chrome....
"csurf": "^1.11.0",
"express": "^4.18.2",
"express-ejs-layouts": "^2.5.1",
"express-mysql-session": "^3.0.0",
"express-session": "^1.17.2",
"passport": "^0.6.0",
"passport-google-oidc": "^0.1.0",
"passport-local": "^1.0.0",
Possible duplicate: Why am I getting a 403 Forbidden error when trying to access authenticated routes in React frontend, even though login is successful?
There is <form autocomplete="off"> and <input type="hidden" autocomplete="false"> suggestions but they disable autocomplete alltogether. I need to disable the autosubmitting the form. Or catching the submit event and disable the submit button somehow. Is there a way to catch mobile autosubmit event ?
There really was an event called onsubmit.
This solved double clicking signin button and clicking signin after autocomplete submits the form. But still auto-complete autosubmit is annoying.