I'm working on a "forgot password" link that runs a function that creates a new JWT, then redirects to reset-password.html and works properly.
However this page needs a <script src="updatePassword.js"></script> for the user to save the new password.
The problem is: the simple presence of the script src... on the html page makes the resetPassword function to run twice and mess up the token creation.
Console logging shows a proper token on the first run and then: token: updatePassword.js followed by jwt malformed. If I remove the script from the html page this doesnt happen. How do I fix this?
Here's the code for the forgot password link:
module.exports.resetPassword = asyncHandler(async(req, res) => {
const {id, token } = req.params
const user = await User.findById(id)
console.log('token:', token)
//check user
if(id != user._id) {
res.send('Invalid ID')
return
}
const secret = process.env.JWT_SECRET + user.password
try {
const payload = jwt.verify(token, secret)
console.log('works')
res.render('reset-password.html', {email: user.email, userName: user.userName})
} catch (error) {
console.log('doesnt work')
console.log(error.message)
res.send(error.message)
}
})
Related
I am new to this
I am writing a Vue app that connects to a Wordpress backend and I need to log in. I am using a plugin called Simple JWT-Login and I am able to send the email and password to the back end and i get the JWT back. But trying to log in and sending the jWT back to the back end gets me an error Bad Request.
Here is the function that is supposed to handle the login
async login(){
try{
const response = await axios.post('/?rest_route=/simple-jwt-login/v1/auth&email=email&password=password',
{
email: this.email,
password: this.password,
}
);
const token = response.data.data.jwt
localStorage.setItem('token', token)
console.log(token)
const login = await axios.get('/?rest_route=/simple-jwt-login/v1/autologin&JWT=token')
console.log(login)
// this.$router.push("/");
} catch(err){
console.log(err)
// if(err.response.status === 400){
// this.error = "Wrong credentials! Please make sure"
// }
} finally{
}
}
The issue was a setting in the plugin that the docs does not explain to you and unless you are an expert the only way to find out is by trial and error.
The setting under general for SESSION must be On
Looking at the docs for Login User, it seems you just need to pass the previous token value as the JWT query parameter.
I've always found it best to use the params option in Axios for query params
const login = await axios.get("/", {
params: {
rest_route: "/simple-jwt-login/v1/autologin",
JWT: token,
}
})
Your issue was that in this string...
'/?rest_route=/simple-jwt-login/v1/autologin&JWT=token'
token was not interpolated; you were literally sending "token".
You should do the same with your first request. The email and password should not be in the query string for this one.
axios.post("/", {
email: this.email,
password: this.password,
}, {
params: {
rest_route: "/simple-jwt-login/v1/auth",
}
})
I am creating a form, in react-redux to change user password. I am wondering how can I validate the user current password in order to change to new one.
in my form I have 2 fields: old password, new password.
this is my action:
const { currentUser } = auth
currentUser.updatePassword(newPassword)
.then(
success => {
dispatch({
type: CHANGE_USER_PASSWORD_SUCCESS,
payload: currentUser
})
},
error => {
dispatch({
type: CHANGE_USER_PASSWORD_FAIL,
error: error.message
})
}
)
I am wondering, how to validate the old password in firebase? Should I use signInWithEmailAndPassword()? Or, is there a function to validate the current password without calling the signIn again, since my user is already logged in?
Thanks
Well, I believe you want the user to enter the old password just to verify whether it's the actual owner of the account or not.
Firebase handles this situation very well, you just need to call the updatePassword method on the user object and pass in the new password.
const changePassword = async newPassword => {
const user = firebase.auth().currentUser;
try {
await user.updatePassword(newPassword)
console.log('Password Updated!')
} catch (err) {
console.log(err)
}
}
If it's been quite a while that the user last logged in then firebase will return back an error -
"This operation is sensitive and requires recent authentication. Log in before retrying this request."
Thus, you don't really need to check the old password as firebase does it for you.
But if you just want to do it in one go, without having the user to log in again.
There's a way for that as well.
There is a method on user object reauthenticateAndRetrieveDataWithCredential you just need to pass in a cred object(email and password) and it refreshes the auth token.
const reauthenticate = currentPassword => {
const user = firebase.auth().currentUser;
const cred = firebase.auth.EmailAuthProvider.credential(
user.email, currentPassword);
return user.reauthenticateAndRetrieveDataWithCredential(cred);
}
In your particular case, you can have something like this
const changePassword = async (oldPassword, newPassword) => {
const user = firebase.auth().currentUser
try {
// reauthenticating
await this.reauthenticate(oldPassword)
// updating password
await user.updatePassword(newPassword)
} catch(err){
console.log(err)
}
}
Learn more about firebase reauth - https://firebase.google.com/docs/auth/web/manage-users#re-authenticate_a_user
Hope it helps
I am making mock authentication in node js using passport, jwt. I have created successfully api. I am using handlebars for templating.
Suppose when user post credential to login(post), the api should verify the user and return json content. I stuck here how I redirect to another page after redirection.I don't want this in my api.
My code is this:
app.post('/login', (req, res, next) => {
if (req.body.name == '' || req.body.password == '') {
res.status(401).send('Please fill all fields')
} else {
let name = req.body.name;
// let password = req.body.password;
// usually this would be a database call:
let user = users[_.findIndex(users, {
name: name
})];
if (user === undefined) {
res.status(401).send('User not defined')
} else {
if (user.password === req.body.password) {
let payload = {
id: user.id
};
let token = jwt.sign(payload, config.jwtSecret);
res.json({message: "ok", token: token});
} else {
res.status(401).send('Password did not match')
}
}
}
});
My doubt is this from this api How can I redirect to next page if user is authenticated. I can not change code in this api as I am using this api for testing also.
I'm still kinda new to Node.js but I believe to redirect you can use
res.redirect("/pageyouwant");
Maybe in the bracket where the user gets authenticated, you can use the code I wrote above.
Btw, maybe try my code in that place
if (user.password === req.body.password) {
let payload = {
id: user.id
};
let token = jwt.sign(payload, config.jwtSecret);
res.json({message: "ok", token: token});
res.redirect("/pageyouwant"); // <-- This one right here
}
Hope I could helped you.
I have a login in my Angular 2 app, and I have been converting it from using a fake backend (which works) to connect to our mongoDB-based API instead.
This is the login function I am using in the authentication service:
login(username: string, password: string) {
const u = encodeURIComponent(username);
const p = encodeURIComponent(password);
this._url = `https://api.somesite.com/v0/staff/login/${u}/${p}?apikey=somekey`;
console.log(this._url);
return this.http.post(this._url, JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
In my login component I am subscribing like this:
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
When I try this, and log to the console "this_url", I get what I would expect. For instance, if the user typed in "billsmith" for username, and "parisnow" for password, I see this in the console for "this_url":
https://api.somesite.com/v0/staff/login/billsmith/parisnow?apikey=somekey
Furthermore, I can type that url directly into the browser address window and see data (when the username and password correctly correspond to actual records in our database). So it's accessing the correct info in that sense.
But in the console I get a "404" error for that generated url. It also doesn't "do anything". In other words, it doesn't correctly redirect to the main component as it did with the fakeBackend-enabled login. And the only thing that's different now is the url that I am calling (because I'm connecting to our actual API now, as opposed to a fake backend provider).
FYI, the url when using the fake backend looked like this:
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password}))
What am I missing here?
By the way, this is how things look on the server side re: our mongoDB:
exports.byLogin = function(req, res, next) {
let ioOnly = false, username, password;
if (_.isUndefined(req.params)){
ioOnly=true;
username = req.username;
password = req.password;
}
else {
username = req.params.username;
password = req.params.password;
}
staff.findOne({username: username, password: password}, function(err, doc) {
if (err) { if (!ioOnly) { return next(err) } else { return res(err)}}
else if(doc) ((!ioOnly) ? res.send(doc) : res(doc));
else ((!ioOnly) ? res.sendStatus(204) : res(doc));
});
};
I am working on login functionality for my Angular 2 app. I've got it working with a MockMackend and fakeBackendProvider. Now I'm in the process of connecting to our actual API. I am running into an issue with that, though.
First off, let me show what I have that IS working by using the MockBackend and fakeBackendProvider.
This is my authentication service function:
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password}))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
Again, then, in my login component, I am calling that function like this:
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
Again, all of the above IS working.
So, I assume all I should need to do is replace '/api/authenticate' in the login function, with our actual api + api string. So this is what I've been trying:
login(username: string, password: string) {
return this.http.post('https://api.somesite.com&apikey=843c-4932-ckd33', JSON.stringify({ username: username, password: password}))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
This isn't working. In the console I get a "ERR_NAME_NOT_RESOLVED" error. Any ideas here?