I'm currently making simple user-authentication app.
now I'm done with backend process with node js and passport.
what I've done was returning json response if authentication goes well or not.
router.post('/register', (req, res) => {
if(!utils.emailChecker(req.body.username)) {
return res.status(403).json({
error: "Invalid Username",
code: 403
});
}
if(!utils.passwordChecker(req.body.password)) {
return res.status(403).json({
error: "Invalid Password",
code: 403
});
}
//mysql query : variables must be inside "" or '';
let sql = `SELECT * FROM users WHERE username="${req.body.username}"`;
connection.query(sql, (err, result) => {
if(err) throw err;
if(utils.duplicateChecker(result)) {
return res.status(409).json({
error: "Username Exist",
code: 409
});
} else {
hasher({password: req.body.password}, (err, pass, salt, hash) => {
let user = {
authId: 'local: '+req.body.username,
username: req.body.username,
password: hash,
salt: salt,
displayName: req.body.displayName
};
let sql = 'INSERT INTO users SET ?';
connection.query(sql, user, (err, rows) => {
if(err) {
throw new Error("register error!");
} else {
req.login(user, (err) => {
req.session.save(() => {
return res.json({ success: true });
});
});
}
});
});
}
});
});
As you can see above, every time request makes error or goes perfect, json that contains error & code or success property is returned.
What I want to do is that getting these jsons via http service of angular2.
#Injectable()
export class UserAuthenticationService {
private loginUrl = "http://localhost:4200/auth/login";
private registerSuccessUrl = "http://localhost:4200/auth/register";
headers = new Headers({
'Content-Type': 'application/json'
});
constructor(private http: Http) { }
/*
body: {
username,
password,
}
*/
logIn(user: Object) {
return this.http
.post(this.registerSuccessUrl, JSON.stringify(user),
{ headers: this.headers });
}
What I've tried is this way. Make http post request using backend url.
and implement function on AuthComponent.
export class AuthComponent {
username: string = '';
password: string = '';
remembered: boolean = false;
submitted = false;
constructor(private userAuthenticationService: UserAuthenticationService) {}
onsubmit() {
this.userAuthenticationService.logIn({ username: this.username, password: this.password });
this.submitted = true;
}
}
But result is I just get json object on screen. { success: true }!
How can I get this json object thru http call and make use of 'success' property?
You are not using the server's response.
onsubmit() {
this.userAuthenticationService
.logIn({ username: this.username, password: this.password })
.subscribe(result => {
//here check result.success
}, error => console.error(error));
this.submitted = true;
}
The Http calls are asynchronous. Hence, using something like :
const data =this.userAuthenticationService.logIn({ username: this.username, password: this.password }); would not work. Rather subcribe to the response like this :
this.userAuthenticationService.logIn({ username: this.username, password: this.password }).subscribe(
data => {
this.submitted = data.success;
});
Here data is the response object from the server.
Related
Created a login method but it spits out the token regardless of what is entered in the Userfields
This uses swagger API and I'm trying to develop the frontend and backend
I'm relatively new to nodejs/javascript
Any Help would be appreciated!
login.js
var form = document.getElementById('login')
form.addEventListener('submit', login)
async function login(event) {
event.preventDefault()
const username = document.getElementById('username').value
const password = document.getElementById('password').value
const result = await fetch('/v1/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password
})
}).then((res) => res.json())
if (result.status === 'ok') {
// everythign went fine
console.log('Got the token: ', result.data)
localStorage.setItem('token', result.data)
alert('Login Successful')
return false;
} else {
alert(result.error)
}
}
userController.JS
login: async (req,res)=> {
const { userName, password } = req.body
const existUsername = await userModel.findOne({ userName: req.body.userName, password: req.body.password}).then((existUsername) =>{
if (existUsername){
res.status(400).json({status: 'Failed', message: `User was Not found`, data: null})
return;
}
try{
async() => {
await bcrypt.compare(password, req.body.password) }
// the username, password combination is successful
const token = jwt.sign(
{
id: userModel._id,
userName: userModel.userName
},
JWT_SECRET
)
res.json({ status: 'ok', data: token })
}
catch (e) {
res.status(400).json({status: 'Failed', message: `${e.message}`, data: null})
}
});
},
I have created a Authentication service in Angular with function SignUp that sends the API Request to Firebase, As Firebase returns the User ID, I am saving the userid into my personal MongoDB Database with its Role. Now the problem here is i am sending two request which i want to further Subscribed in Register.component.ts, I am not able to understand how to achieve this. Below are the sample code that i have tried.
auth.service.ts
signUp(email: string, password: string) {
return this.http.post<AuthResponse>(`https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${config.API_KEY}`, {
email: email,
password: password,
returnSecureToken: true
}).pipe(
switchMap(data => {
return this.http.post<any>(`${config.BASE_URL}/api/ezusers/`,{useruid: data.idToken, 'isRegistered':false}); // or this.userId
})
).map(response => {
this.authenticatedUser(response.email, response.localId, response.idToken, +response.expiresIn);
// this.userOrders = response;
return
});
}
Register.component.ts
onSubmit() {
this.loading = true;
if (this.registerForm.valid) {
this._authService.signUp(this.registerForm.value.email, this.registerForm.value.password).subscribe(
res => {
console.log(res);
this.loading = false;
this.registerForm.reset();
this.success = true;
this.error = false;
},
err => {
console.log(err);
this.loading = false;
this.success = false;
this.error = this.errMsgs[err.error.error.message];
})
}
else {
}
}
Any help would be really Appreciated.
Thanks in Advance!
I'm not totally understand what you want to achieve in register component, but what's I've noticed there always response will be falsy, as you return undefined in service. Not sure what method authenticatedUser returns, but try it.
signUp(email: string, password: string) {
return this.http.post<AuthResponse>(`https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${config.API_KEY}`, {
email: email,
password: password,
returnSecureToken: true
}).pipe(
switchMap(data => {
return this.http.post<any>(`${config.BASE_URL}/api/ezusers/`,{useruid: data.idToken, 'isRegistered':false}); // or this.userId
})
).map(response =>
this.authenticatedUser(response.email, response.localId, response.idToken, +response.expiresIn)
);
exports.addUser = async(req, res) => {
const {
username,
email,
password
} = req.body;
//hash password
const password_hash = await hashPassword(password);
//check whitelist
this.checkWhitelist(email).then(function(response) {
if (response) {
console.log("RESOLVED TRUE")
//POST user to Airtable
new Promise(function(resolve, reject) {
return usersTable.create({
email,
username,
password_hash,
"email_verified": "false"
},
function(err) {
if (err) {
resolve(false);
console.error(err);
res.send({
"Success": false,
"responseCode": 502,
})
}
resolve(true);
res.send({
"Success": true,
"responseCode": 200,
});
}
).then(function(response) {
if (response) {
const EMAIL_SECRET = "xxxxxxxxxxx";
jwt.sign({
'username': username,
},
EMAIL_SECRET, {
expiresIn: '1d',
},
(err, emailToken) => {
const url = `http://localhost:3000/confirmation/${emailToken}`;
transporter.sendMail({
to: args.email,
subject: 'Confirm Email',
html: `Please click this email to confirm your email: ${url}`,
});
}
)
}
})
})
} else {
console.log('RESOLVED FALSE')
res.send({
"Success": false,
"responseCode": 403
})
}
})
}
For some reason, the promise I created at usersTable.create is not resolving correctly. When I call .then() after, I get the error: UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'then' of undefined.
For context, this is the user registration flow for a webapp. First, the pass is hashed, then the email is check against a whitelist (so far this logic is working). Now I just need to verify the email, but can't get the .then() to call correctly.
What's going on?
In your first then where you return createTable you'll need to return new Promise so it can be chained to the next then.
If createTable returns a promise, you can simply write return createTable and get rid of the new Promise that wraps it.
Since you are using async-await earlier in the code, I'd recommend you moving to that completely as it makes the code much easier to read.
I took a stab at that,
exports.addUser = async(req, res) => {
const {
username,
email,
password
} = req.body;
//hash password
const password_hash = await hashPassword(password);
//check whitelist
try {
const whitelist = await this.checkWhiteList(email)
if (whitelist) {
await usersTable.create() // shortened for readability sake.
const EMAIL_SECRET = 'xxxxxxxxxxx';
jwt.sign(
{
'username': username,
},
EMAIL_SECRET,
{
expiresIn: '1d',
},
(err, emailToken) => {
const url = `http://localhost:3000/confirmation/${emailToken}`;
transporter.sendMail({
to: args.email,
subject: 'Confirm Email',
html: `Please click this email to confirm your email: ${url}`,
});
}
);
}
res.send({
'Success': true,
'responseCode': 200,
});
} catch (error) {
res.send({
'Success': false,
'responseCode': 403,
});
}
}
I have a login form that sends data to an Express.js backend using fetch. On the client side, when I want to display the results of the fetch call when it completes nothing is displayed (and it never reaches the data callback). I don't seem to be getting any errors, but I know that the data is successfully being sent to the backend.
Here's the Express.js server code:
const express = require('express');
const User = express.Router();
const bcrypt = require('bcrypt');
const user = require('../Models/user');
this is edited
function loginRouteHandler(req, res) {
user.findOne(
{
where: {
userName: req.body.userName,
},
},
)
.then((data) => {
if (bcrypt.compareSync(req.body.password, data.password)) {
req.session.userName = req.body.userName;
req.session.password = req.body.password;
console.log(req.session);
res.status(200).send('Success!');
} else {
res.status(400).send('some text');
}
});
}
User.route('/').get(getRouteHandler);
User.route('/register').post(postRouteHandler);
User.route('/login').post(loginRouteHandler);
module.exports = User;
And here's the fetch call:
fetch('http://localhost:4000/login',{
method: 'POST',
headers: {
'Accept': 'application/json,text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({
userName: this.state.userName,
password: this.state.password,
}),
}).then((response)=>{
if(response.ok){
console.log(response)
}
else {
console.log("a problem")
}
}).then((data)=>{
console.log(data)
});
In your loginRouteHandler, if the bcrypt compare succeeds nothing is returned in the response. So in the first branch of the if statement, put res.send('Success!') or something similar.
Here's an example:
function loginRouteHandler(req, res) {
user.findOne(
{
where: {
userName: req.body.userName,
},
},
)
.then((data) => {
if (bcrypt.compareSync(req.body.password, data.password)) {
req.session.userName = req.body.userName;
req.session.password = req.body.password;
console.log(req.session);
res.status(200).send('Success!');
} else {
res.status(400).send('some text');
}
});
}
UPDATE: you're also not getting the output of the fetch response with .text() or .json(). You have to update the fetch call to the following:
fetch(/* stuff */).then((response)=>{
if(response.ok){
console.log(response)
}
else {
console.log("a problem")
}
return response.text()
}).then((data)=>{
console.log(data)
});
Remove ok from response.ok
Remove .then((data)=>{ console.log(data) });
And check console log.
}).then((response)=>{
if(response){
console.log(response)
}
else {
console.log("a problem")
}
}).then((data)=>{
console.log(data)
});
i'm trying to create a user from server side using meteor js, when testing the code it show me this error in navigator console Error invoking Method 'addNewUser': Internal server error [500].
this is my code:
/imports/api/users/methods.js :
Meteor.methods({
addNewUser(user) {
console.log(user);
const email = user.emails[0].adresse;
const newUser = {
username: user.username,
email: email,
password: user.password
};
Accounts.createUser(newUser, (err) => {
if (err) {
toastr.error(err.reason,'faild');
// this.done(new Error("Submission failed"));
} else {
toastr.success('Registred with success !', 'welcome');
FlowRouter.go('home');
}
});
}
});
/imports/ui/pages/create-account.js:
AutoForm.hooks({
formCreateAccount: {
onSubmit(user) {
Meteor.call('addNewUser', user);
return false;
}
}
});