Refresh window when username and password mismatch - node.js

I am building an application using node.js. I made a login form and it is working fine, but if the user enters the wrong username and password then he has to refresh the window and then type the right username and password in order to continue with the next screen.
What should I do to let the user enter after the login window without a refresh?
Explaining the above problem step-by-step:
User enters username and password (if both are correct).
User is logged in.
But:
User enters username and password (if either of them is wrong).
Refresh window.
User enters correct username and password.
User is logged in.
How can I avoid the "refresh window" step? I can explain more if this is not clear.

I have edited the answer, you can do it like this.
socket.on('login_check', function(email, pwd) {
connection.query("SELECT id,user_type FROM user WHERE email = '"+email+"' AND password = '"+pwd+"'ORDER BY name ",
function (error, results, fields) {
if (error) {
console.log(error);
}
if (results[0]) {
// some code
} else {
response.writeHead(200, {
'Location': '/login-path'
// add other headers here...
// you may also show the email in the text box
// again by passing the variable email to the template
// engine you are using or how ever you are doing it
});
response.end();
}
});
});

Related

nodejs with ldapjs authentication possible without password

I gonna write a API which get a Username and password from the Front-End. This username and password get passed into my LDAP bind and should get checked if these informations are correct. Now I got the problem when the use types a wrong password I get the correct error code 49 for invalid credentials. But when the user just enter his username and nothing into password, then LDAP is automatically accepting it and passes through the authentication.
Can maybe someone help me or give me an advice whats wrong?
const ldap = require('ldapjs');
var client = ldap.createClient({
url: `ldap://${process.env.LDAP_HOST}:${process.env.LDAP_PORT}`
});
function ldapauth(dn, password, callback) {
var serverStatus;
//dn = entry.object.dn from another ldap query
client.bind(dn, password, function(err, res) {
if(err) {
console.log(['Error:',err.code, err.dn, err.message]);
serverStatus = err.code;
client.unbind();
return callback (serverStatus);
} else {
console.log('Auth Status: ' + res.status);
if(res.status == 0) {
serverStatus = res.status;
} else {
serverStatus = 500;
}
client.unbind();
return callback(serverStatus);
};
});
}
This is my output which I get when the password is empty
The activedirectory package solves this by returning an error if no password is supplied:
if ((! username) || (! password)) {
var err = {
'code': 0x31,
'errno': 'LDAP_INVALID_CREDENTIALS',
'description': 'The supplied credential is invalid'
};
return(callback(err, false));
}
Here is the code: https://github.com/gheeres/node-activedirectory/blob/master/lib/activedirectory.js#L1803
More info about the bind command: https://ldap.com/the-ldap-bind-operation/
This sounds like is the cause of your issue:
An anonymous simple bind can be performed by providing empty strings as the bind DN and password (technically, the LDAPv3 specification states that only the password must be empty, but this has been responsible for many security problems with LDAP clients in the past, and many servers require that if an empty password is provided then an empty DN must also be given).

How to update already existing data using token only?

I have been trying to complete a login/Sign Up API using Node Js and MongoDB, and everything works fine except Forgot Password. I send an email to the user with a link to add new password.
The issue I am having is, How will I extract that specific user when he/she presses the reset button and only update that user's data in the database.
Classic rest password should have this flow:
user select the reset password
user enter its mail
a mail is sent from the system
mail contains a link (with expiration time for security) something like this:
https://acme.com/security/password/reset?code=8df024dfd526
code=8df024dfd526 in the link is related to the mail, so when is clicked, a final UI form will be prompted to the user. You could use this code to identify the email, sending it to your backend
You cannot ask the email again because anyone could change anyone's password.
Some times this code is known as one-time password (OTP).
As its name says: You must ensure that this code works just one time. I mean if user click again, you should show an error.
More details here.
implementation
You just need to persist somewhere (database) the following information:
the generated alphanumeric code with the requested email.
an expiration time for any code
usage count of code
Your email link to the user should be unique and can identify the user.
I do this:
// Generate hashed reset password token
User.resetPasswordToken = (user) => {
const resetToken = crypto.randomBytes(20).toString('hex')
// Update user with hashed token and expire time
user.resetPasswordToken = crypto.createHash('sha256').update(resetToken).digest('hex')
user.resetPasswordExpire = Date.now() + 10 * 60 * 1000
// Return unhashed token for use in email url
return resetToken
}
Here I do two things: 1) update the User in the DB with a resetPasswordToken and an expiration time/date for the resetPassword. Both saved in the database. 2) return an unhashed resetPassword for use in the email link to be sent (see below).
const resetToken = User.resetPasswordToken(user)
await user.save()
const resetUrl = `this link`
// Send email
const message = `<p>Please follow ${resetUrl} in order to create a new password. The link is valid for 10 minutes.</p>`
User now clicks the link and the endpoint extracts the reset token, hashes it and checks if it corresponds with the token saved on this particular user in the database from req.params.resettoken:
const resetPasswordToken = crypto.createHash('sha256').update(req.params.resettoken).digest('hex')
const timeNow = Date.now()
let user = await User.findOne({
where: {
resetPasswordToken,
deletedAt: null,
},
})
Then I perform some checks before I save the new password (encrypted) the user has typed in. I reset the reset token and expiration password in the database to null.
user.password = await encrypt(req.body.password)
user.resetPasswordToken = null
user.resetPasswordExpire = null
try {
await user.save()
} catch (error) {
return next(new ErrorResponse(`The new password could not be saved, please try again later`, 500))
}

How to check currentPassword to allow user to change Password

im trying to implement function for "user change password".
i want to do:
1.user choose new password.
2.user needs to enter his current password to varificate.
3.if the user currentPassword correct -> change the password.
the problem: i dont know how to get his current password to check if its correct
in my client side i save his hashPassword ("lfds7fdhas784n23489h42")
so i cant do something like:
if state.user.password===currentPassword because i dont have its state password
i need to somhow get his passwsord from the server and check it, or maybe i need to send the
currentPassword to the back end and check it there ,but i dont know how to implement it...
code:
the Form to update password (in shortcut for better understanding):
<TextInput
placeholder"NewPassword"
onChangeText={setNewPass}/>
<TextInput
placeholder"currentPassword"
onChangeText={setCurrentPass}/>
updateUserPssword(state.userId, token, param, value);
the Function for update the password:
const updateUserPssword = dispatch => async (userId, token, newPass, currentPass) => {
try {
const res = await indexApi.put(
`/user/${userId}`,
{
password: newPass,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
}
For summary, the flow of reset password operation is like:
Step 1: User fills in currentPassword, newPassword and confirmedNewPassword in your React App. What you can validate here is only the similatiry of newPassword and confirmNewPassword.
Step 2: When the newPassword and comfirmedNewPassword are similar you send a request to server with data like this : { current: currentPassword, new: newPassword }
Your main concern is how to do that with axios. Below is an example:
axios.post('/reset-password', {
current: currentPassword,
new: newPassword
})
.then(function (response) {
// success case handle here
})
.catch(function (error) {
// error case handle here
});
When your server gets this request, basically, the following steps should be done
Step 1: Use hash function to hash the currentPassword
Step 2: Compare with hashed password of this user in DB
Step 2.1: If the 2 hashed passwords match, hash the newPassword and save the hashed value to DB
Step 2.2: If the 2 hashed passwords do not match, response error to your React App. (something like: passwords do not match)
You should manipulate all your actions on passwords on the server-side. That's the right flow
User types new password (Don't hash)
User types same password for confirmation (you can compare only this on client-side, if fieldA.value == fieldB.value)
User types old password
You send new password and old password as plain, to the server without hash.
Server hashes your old password with the same SALT and compares if generated hash is equal to the hash is stored in the database. That's the KEY MOMENT, you don't need to decode a stored password and compare the plain.
P.S Every time hashing something with the same salt gives you the
same result.
// Pseudo code
decodeHash(passwordInDatabase) == oldPassword // incorrect + impossible
hash(oldPassword) == passwordInDatabase // correct
If it's equal, back-end hash your new password and update in the database.
Return success or error message from back-end.

handleResetPassword in custom email action handlers

function handleResetPassword(auth, actionCode, continueUrl, lang) {
// Localize the UI to the selected language as determined by the lang
// parameter.
var accountEmail;
// Verify the password reset code is valid.
auth.verifyPasswordResetCode(actionCode).then(function(email) {
var accountEmail = email;
// TODO: Show the reset screen with the user's email and ask the user for
// the new password.
// Save the new password.
auth.confirmPasswordReset(actionCode, newPassword).then(function(resp) {
// Password reset has been confirmed and new password updated.
// TODO: Display a link back to the app, or sign-in the user directly
// if the page belongs to the same domain as the app:
// auth.signInWithEmailAndPassword(accountEmail, newPassword);
// TODO: If a continue URL is available, display a button which on
// click redirects the user back to the app via continueUrl with
// additional state determined from that URL's parameters.
}).catch(function(error) {
// Error occurred during confirmation. The code might have expired or the
// password is too weak.
});
}).catch(function(error) {
// Invalid or expired action code. Ask user to try to reset the password
// again.
});
}
Using above handleResetPassword function I can get the email with auth.verifyPasswordResetCode and how to continue toauth.confirmPasswordReset with new password? Do I need html form? then what will be the action of that form? I'm confusing to continue to auth.confirmPasswordReset.
You need a form with an input and a button but you never need to submit the form. You ask the user to enter the new password in an input field. On button click, you get the new password and call confirmPasswordReset with the actionCode and new password while cancelling the submit action.

Sign out different user

I would like to be able to sign out some user that is logged in. By this I do not mean current user but some other user.
I, as an administrator, can deactivate or ban a user. At this point I would like to get this user and sign him out so when he makes his next request he gets redirected to log in page. After login attempt he would get a message why he cannot log in.
I am aware I can do it by writing my own authorization filter and go and fetch user from database each time but I would, if possible, like to avoid that.
Setting up authentication as follows hits mz OnValidatePrincipal each time a request is made but I do not know how to update exactly this user.
services.AddAuthentication("CookieAuthentication")
.AddCookie("CookieAuthentication", options => {
options.LoginPath = "/Login";
options.Events = new CookieAuthenticationEvents()
{
OnValidatePrincipal = new Func<CookieValidatePrincipalContext, Task>(async (a) =>
{
var expired = a.Principal.FindFirst(System.Security.Claims.ClaimTypes.Expired);
if(expired != null && bool.Parse(expired.Value))
{
a.RejectPrincipal();
return;
}
await Task.CompletedTask;
})
};
});
I am also aware that I could write my own middleware and keep some kind of list of all the users that have logged in. That list could than be easily updated by an administrator and checked by the previous event.
What I would like to know is, can I get an instance of other logged user and can I than alter its claims?

Resources