I'm setting up a web app in Angular with a restAPI in Nodejs but I can't correctly set my post request for authenticate user
I've set up my api and I can correctly test it with curl but in the client side (angular) it can't pass the condition that verify that the field required are presents
function in the API:
exports.authenticate = function(req, res) {
var new_user = new User(req.body);
if (!new_user.login || !new_user.pwd) {
res.status(400).send({
error: true,
message: 'Please provide all informations!'
});
} else {
User.authenticate(new_user, function(err, user) {
console.log('controller');
if (err) {
res.status(500).send(err);
} else {
console.log(user[0].id);
var token = jwt.sign({
id: user[0].id
}, config.secret, {
expiresIn: 3600
});
res.status(200).send({
user: user,
auth: true,
token: token
});
}
});
}
}
User.authenticate call my sql query:
sql.query("SELECT * FROM user WHERE login = ?", [user.login], function(err, res) {
if (err) {
return res.status(500).send('Error on the server ', err);
//console.log("error select: ", err);
} else {
if (!res) {
return res.status(404).send('No user found');
} else {
//sql.query("UPDATE user SET pwd = ? WHERE id = ?", [crypto.createHash('sha256').update(user.
sql.query("SELECT * FROM user WHERE pwd = ?", [crypto.createHash('sha256').update(user.pwd + r
if (err) {
console.log("error: ", err);
result(null, err);
} else {
result(null, res2);
}
});
}
}
});
Angular side (my service function):
login(loguser: User) {
return this.http.post<any>(`${environment.apiUrl}/authenticate`,
{ loguser }, { headers: new HttpHeaders().set('Content-Type', 'application/json')})
.pipe(map(user => {
// store user details and jwt token in local storage to keep user logged in between p
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
return user;
}));
}
login component:
onSubmit() {
this.submitted = true;
// stop here if form is invalid
if (this.loginForm.invalid) {
return;
}
this.loading = true;
this.user.login = this.f.username.value;
this.user.pwd = this.f.password.value;
console.log(this.user);
this.authenticationService.login(this.user)
.pipe(first())
.subscribe(
data => {
this.router.navigate([this.returnUrl]);
},
error => {
this.error = error;
this.loading = false;
});
}
console.log(this.user) output : {login: "cl", pwd: "cl"}
my post request is blocked in this part of my api:
if (!new_user.login || !new_user.pwd){
res.status(400).send({ error: true, message: 'Please provide all informations!' });
Because this is the answer I get when I submit the form.
I can get right answer when I test it like that:
curl -v -X POST --data '{"login":"cl","pwd":"cl"}' --header "Content-Type: application/json" https://#api:8443/autenticate
I want to get the good answer.
The problem is in your Angular code:
login(loguser: User) {
return this.http.post<any>(`${environment.apiUrl}/authenticate`,
{ loguser },
{
headers: new HttpHeaders().set('Content-Type', 'application/json')
})
.pipe(map(user => {
// store user details and jwt token in local storage to keep user logged in between p
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
return user;
}));
}
This piece of code:
{ loguser }
uses the "shortcut property name" syntax introduced in TypeScript and ECMAScript 2015 to create an object with a single property named loguser which has the value of the loguser variable. It is equivalent of writing:
{ loguser: loguser }
Instead, you can just pass the variable itself in your code:
login(loguser: User) {
return this.http.post<any>(`${environment.apiUrl}/authenticate`,
loguser, // Just the object itself
{
headers: new HttpHeaders().set('Content-Type', 'application/json')
})
.pipe(map(user => {
// store user details and jwt token in local storage to keep user logged in between p
localStorage.setItem('currentUser', JSON.stringify(user));
this.currentUserSubject.next(user);
return user;
}));
}
That will pass the object, with the login and pwd properties intact.
Related
const login = (req, res) => {
// console.log(req.body);
// let email = req.body.email.toLowerCase();
sequelize.models.User.findOne({
where: {
email: req.body.email,
},
})
.then(async (user) => {
if (!user) {
// console.log(" email not found is true");
return res.status(401).json({
success: false,
message: " Authentication failed, Wrong Credentials",
});
}
if (user.isActive == false) {
// console.log("user is not activated", user.isActive);
return res.status(400).json({
success: false,
message: "account is not activated",
});
}
console.log("test entry");
await user.comparePassword(req.body.password, async (err, isMatch) => {
console.log(req.body.password);
if (isMatch && !err) {
console.log("user crap");
// role_id: user.role_id,
const payload = {
user_id: user.user_id,
};
const options = {
expiresIn: "10day",
};
const token = await jwt.sign(payload, process.env.SECRET, options);
console.log("sssssss", payload);
if (user.twoFactorAuth == false) {
return res.json({
success: true,
token,
});
} else {
// let mobile = user.phone;
await twoFactorAuth(user); // we call the 2fa that will send a otp to the users cellphone
// console.log("after cb");
}
} else {
return res.json({
success: false,
msg: "Authentication failed.",
});
}
});
// console.log("user crap", user.user_id);
})
.catch((error) => {
return res.status(400).send(error);
});
};
const twoFactorAuth = async (user) => {
var data = qs.stringify({
sender: "hehe",
mobile: user.phone,
channel: "sms",
});
var config = {
method: "POST",
url: "https://blablabla",
headers: {
Authorization: "Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
},
data: data,
};
axios(config)
.then( async function (response) {
console.log(JSON.stringify(response.data));
// await verifyTwoFactorAuth (realToken)
})
.catch(function (error) {
console.log(error);
});
};
const verifyTwoFactorAuth = async(req, res) => {
//console.log("tet",req);
let otpcode = req.body.otpcode;
let mobile = req.body.mobile;
var data = qs.stringify({ mobile: mobile, code: otpcode });
var config = {
method: "POST",
url: "https://blablabla",
headers: {
Authorization: "Bearer xxxxxxxxxxxxxxxxxxxxxxxx",
},
data: data,
};
axios(config)
.then(async function (response) {
console.log(JSON.stringify(response.data));
if (response.data.code == 63 || response.data.status == 200) {
return res.json({
success: true,
token,
});
} else if (response.data.code == 21 || response.data.status == 422) {
return res.status(400).json({
success: false,
message: "wrong code, check your sms again",
});
}
})
.catch(function (error) {
console.log(error);
});
};
Hello, I am looking for a structure solution to how I should implement what I want.
Scenario: user try to login, system checks for username and passoword and generates the TOKEN, system finds that 2fa is active in users settings, system sends OTP to users cellphone.
Now my struggle begins, I am not sure what to do next, I thought about storing the token in users fields as tempToken then i look for the user via users mobile and extract the token that way, but I dont believe that this is best practice.
Any ideas of how to tackle this would be appreciated ! thank you
I've successfully set up the registration and login functionality using Express, MongoDB and Mongoose.
I would like to log when the user last visited the site once the user's credential is accepted in a lastConnection property of the user document,
I tried but "lastConnection" is null (see the line below where I add a comment)
router.post("/login", async function(req, res) {
const { errors, isValid } = validateLoginInput(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
const user = await User.findOne({ email }).then(user => {
if (!user) {
errors.email = "Email already exists";
}
console.log("user ", user); <-- returns an object with the datas of user
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = {
id: user.id,
name: user.name
};
user.lastConnection = new Date(); <-- doesn't work
jwt.sign(
payload,
keys.secretOrKey,
{
expiresIn: 7200
},
(err, token) => {
res.json({
success: true,
token: "Bearer " + token
});
}
);
} else {
errors.password = "Password is not correct";
// return res
// .status(400)
// .json({ passwordincorrect: "Password incorrect" });
}
});
});
return {
errors,
isValid: isEmpty(errors)
};
});
Any ideas? I think I have to do an update but I don't know where to put it
Try replacing user.lastConnection = new Date(); with
user.update({ lastConnection: new Date() })
.then( updatedUser => {
console.log(updatedUser)
// put jwt.sign code here
})
I am not getting any response while calling login api from nodejs.
I am handling the catch in frontend as well.
How to get Invalid Credentials message from backend API if credentials doesn't matched.
my Backend login API is -
// api to login user
router.post('/login', function (req, res) {
const valid = validator.isEmail(req.body.email)
if (valid == false) {
var message = { "Success": 0, "Message": "Please enter a valid email." };
res.send(message)
}
userObj.findOne({
email: req.body.email
}).then(user => {
if (!user) {
var message = { "Success": 0, "Message": "User does not exists." };
res.send(message)
} else {
// console.log(bcrypt.compare(req.body.password, user.password))
// var message = { "Success": 1, "User": user };
// res.send(message)
bcrypt.compare(req.body.password, user.password)
.then(isMatch => {
if (isMatch) {
const payload = {
name: user.name,
id: user._id,
email: user.email
}
jwt.sign(payload, 'secret', {
expiresIn: 3600
}, (err, token) => {
if (err) console.error('There is some error in token', err);
else {
res.json({
Success: 1,
token: `${token}`
})
}
})
}
else {
res.json({
Success: 0,
Message: 'Invalid Credentials'
})
}
})
}
})
});
my frontend login action code is -
// Login - get user token
export const loginUser = user => dispatch => {
return axios
.post("http://18.207.190.61:4000/login", {
email: user.email,
password: user.password
})
.then(res => {
// Save to localStorage
// Set token to localStorage
localStorage.setItem("usertoken", res.data.token);
// Set token to Auth header
setAuthToken(res.data.token);
// Decode token to get user data
const decoded = jwt_decode(res.data.token);
// Set current user
localStorage.setItem("username", decoded.name);
dispatch(setCurrentUser(decoded));
return res.data;
})
.catch(err => {
return err;
});
};
finally my login component code is -
this.props.loginUser(user).then((res, err) => {
if (res.Success == "0") {
this.setState({
loading: false,
message: res.Message
});
}
});
How can I get message Message: 'Invalid Credentials' from backend API in front end to print.
Please return response with status codes '200' for success and '401' for invalid credentials and try again. Axios recognises the status codes and tells if there is an error.
if(success)
res.status(200).json({
Success: 1,
token: '${token}'
})
else
res.status(401).json({
Success: 0,
Message: 'Invalid Credentials'
})
Try this once.
1.Remove the catch block in your login action code
2. change your login component code to
this.props.loginUser(user).then((res ) => {
if (res.Success == "0") {
this.setState({
loading: false,
message: res.Message
});
}
});
I was working on a simple app with login functionality , but im unable to send username and password properly to nodejs server. I have tried encoding it, putting it as Map and FormData, but nothing seems to workout. I console logged the request body and it prints "undefind"
I'm using Dio dart package for making http requests and Redux and redux thunk to dispatch actions .
//Code on My flutter app
ThunkAction<AppState> login(LoginData data) {
return (Store<AppState> store) async {
store.dispatch(IsLoading(true));
try {
Response response = await Dio().post(
"http://10.0.2.2:4000/api/user/login",
data: json.encode({"phone": data.phone, "password": data.password}));
if (response.statusCode == 200) {
print(json.decode(response.data));
store.dispatch(IsLoading(false));
}
} catch (e) {
print("Error :(");
}
};
}
// Code on My nodejs
router.post("/login", (req, res) => {
//this log prints undefined
console.log("Login route: " + req.body.phone);
var cred = {
phone: req.body.phone,
password: req.body.password
};
User.findOne({ phone: cred.phone })
.then(result => {
if (!result) {
res.status(400).json({ msg: "no user" });
} else {
bcrypt.compare(req.body.password, result.password, (err, isMatch) => {
if (isMatch) {
const payload = { id: result._id };
console.log("Logged in :" + payload);
jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 7200 },
(err, token) => {
res.status(200).json({
success: true,
token: "Bearer " + token
});
}
);
} else {
res.status(400).json({ msg: err });
}
});
}
})
.catch(err => {
res.status(400).json({ msg: err });
});
});
To access parameter in server side add this header to you request:
HttpHeaders.contentTypeHeader: 'application/x-www-form-urlencoded'
login api:
api.post('/login', function(req, res) {
User.findOne({
username: req.body.username
}).select('password').exec(function(err, user) {
if(err) throw err;
if(!user) {
res.send({ message: "User doesn't exist."});
} else if(user) {
var validPassword = user.comparePassword(req.body.password);
if(!validPassword) {
res.send({ message: "Invalid password."});
} else {
/////// token
var token = createToken(user);
res.json({
success: true,
message: "Successfully logged in.",
token: token
});
}
}
});
});
middleware:
api.use(function(req, res, next) {
console.log("somebody just came to our app.");
var token = req.body.token || req.param('token') || req.headers['x-access-token'];
// check if token exists
if(token) {
jsonwebtoken.verify(token, secretKey, function(err, decoded) {
if(err) {
res.status(403).send({ success: false, message: "failed to authenticate user."});
} else {
req.decoded = decoded;
next();
}
});
} else {
res.status(403).send({ success: false, message: "no token provided."});
}
});
authService:
authFactory.login = function(username, password) {
return $http.post('/api/login', {
username: username,
password: password
})
.success(function(data) {
AuthToken.setToken(data.token);
return data;
})
}
authFactory.isLoggedIn = function() {
if(AuthToken.getToken())
return true;
else
return false;
}
Now, if my user is logged in and he tries to access: localhost:3000/login , then he should be redirected to localhost:3000/
only after he logs out, he should be able to access the login page (similar to facebook).
How to do this?
1
In login API store user info in respond object(res).
2
app.get('/',function(req,res){
if(req.user){
res.redirect('/login');
} else {
res.render('home');
}
});
RECOMMENDED:PASSPORT and its Local-Strategy.
exports.loginPage = (req, res) => {
if(req.session.user){
res.redirect("/");
} else {
res.render("loginPage");
}
};
On your login route, add the logic inside the middleware function. You could the same on the registration page as well.
exports.registrationPage = (req, res) => {
if(req.session.user){
res.redirect("/");
} else {
res.render("registrationPage");
}
};
The key takeaway is this: if you want a user not to see a page on your site, go to the page's route, add the if/else logic.
Hope that helps, cheers!