Why do I get this error every time I use the api (POST)
SyntaxError: Unexpected token l in JSON at position 18
at JSON.parse (<anonymous>)
at parse (/Users/.../Desktop/ecommerceapi/node_modules/body-parser/lib/types/json.js:89:19)
at /Users/.../Desktop/ecommerceapi/node_modules/body-parser/lib/read.js:121:18
at invokeCallback (/Users/.../Desktop/ecommerceapi/node_modules/raw-body/index.js:224:16)
at done (/Users/.../Desktop/ecommerceapi/node_modules/raw-body/index.js:213:7)
at IncomingMessage.onEnd (/Users/.../Desktop/ecommerceapi/node_modules/raw-body/index.js:273:7)
at IncomingMessage.emit (node:events:532:35)
at endReadableNT (node:internal/streams/readable:1346:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
This is my entire code: (auth.js)
const router = require("express").Router();
const User = require("../models/User");
const CryptoJS = require("crypto-js");
const jwt = require("jsonwebtoken");
//REGISTER
router.post("/register", async (req, res) => {
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: CryptoJS.AES.encrypt(
req.body.password,
process.env.PASS_SEC
).toString(),
});
try {
const savedUser = await newUser.save();
res.status(201).json(savedUser);
} catch (err) {
res.status(500).json(err);
}
});
//LOGIN
router.post('/login', async (req, res) => {
try{
const user = await User.findOne(
{
userName: req.body.user_name
}
);
!user && res.status(401).json("Wrong User Name");
const hashedPassword = CryptoJS.AES.decrypt(
user.password,
process.env.PASS_SEC
);
const originalPassword = hashedPassword.toString(CryptoJS.enc.Utf8);
const inputPassword = req.body.password;
originalPassword != inputPassword &&
res.status(401).json("Wrong Password");
const accessToken = jwt.sign(
{
id: user._id,
isAdmin: user.isAdmin,
},
process.env.JWT_SEC,
{expiresIn:"3d"}
);
const { password, ...others } = user._doc;
res.status(200).json({...others, accessToken});
}catch(err){
res.status(500).json(err);
}
});
module.exports = router;
I'm using Postman to use the API to POST this
{ "username": sultan "password": 12345qwer }
and this is index.js:
const express = require("express");
const app = express();
mongoose = require("mongoose")
const dotenv = require("dotenv");
const userRoute = require("./routes/user");
const authRoute = require("./routes/auth");
dotenv.config();
mongoose
.connect(process.env.MONGO_URL)
.then(() => console.log("DB Connection Successfull!"))
.catch((err) => {
console.log(err);
});
app.use(express.json());
app.use("/api/auth", authRoute);
app.use("/api/users", userRoute);
app.listen(process.env.PORT || 50, () => {
console.log("Backend server is running!");
});
it should give me the users Info or "Wrong Password" but it gives the above error as a response!
double quotes and comma are missing
{
"username": "sultan",
"password": "12345 qwer"
}
Related
I have login page and signup page. when a user want register account and register is successful, I want to redirect him to signin.html page. however, nothing I've tried have worked so far. I always get the error "Cannot set headers after they are sent to the client" when I add this code "res.redirect('http://localhost:3000/signin.html')". here is my code
signup.html
const form = document.getElementById('reg-form')
form.addEventListener('submit', registerUser)
async function registerUser(event){
event.preventDefault()
const username = document.getElementById('user').value
const password = document.getElementById('password').value
const password_confirmation = document.getElementById('password_confirmation').value
const phone = document.getElementById('tel').value
const result = await fetch('/register',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password,
password_confirmation,
phone
})
}).then((res) => res.json())
if (result.status === 'ok') {
alert('success')
}else {
alert (result.error)
}
}
and here is server.js
const express = require('express')
const path = require ('path')
const mongoose = require ('mongoose')
const User = require ('./model/user')
const bodyParser = require('body-parser')
const bcrypt = require ('bcryptjs')
const jwt = require ('jsonwebtoken')
const JWT_SECRET = 'lkjlfg%nlnkllkj#R%##%#&bgkj3nskk2cnklvdfsflkjlkjf98748'
const port =3000
mongoose.connect('mongodb://localhost:27017/login-app-db', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
const app = express()
app.use('/', express.static(path.join(__dirname, '../code FE/')))
app.use(bodyParser.json())
// app.post('/api/change-password', (req, res) => {
// const { token } = req.body
// const user = jwt.verify(token, JWT_SECRET)
// console.log()
// })
app.post('/signin', async (req, res) => {
const { username, password } = req.body
const user = await User.findOne({ username }).lean()
console.log(password)
if (!user) {
return res.json({status: 'error', error: 'Invalid username/password'})
}
if (await bcrypt.compare('password', user.password)) {
// the username, password combination is successfully
const token = jwt.sign({
id: user._id,
username: user.username
},
JWT_SECRET
)
return res.json({status: 'ok', data: token})
}
return res.json({status: 'error', error: 'Invalid username/password'})
})
app.post('/register', async (req, res) => {
console.log(req.body)
const { username, password: plainTextPassword, password_confirmation: someOtherPlaintextPassword, phone} = req.body
if (!username || typeof username !== 'string') {
return res.json({ status: 'error', error: 'Invalid username'})
}
if (!plainTextPassword || typeof plainTextPassword !== 'string') {
return res.json({ status: 'error', error: 'Invalid password'})
}
const password = await bcrypt.hash('password', 10)
const password_confirmation = await bcrypt.hash('password_confirmation', 10)
try {
const response = await User.create({
username,
password,
password_confirmation,
phone
})
console.log('user created successfully: ', response)
res.redirect('http://localhost:3000/signin.html')
}catch(error){
if (error.code === 11000) {
return res.json({ status: 'error', error: 'username already in use'})
}
throw error
}
res.json({status: 'ok'})
})
app.listen(port, () => {
console.log(`Example app listening on port http://localhost:${port}`)
})
I'm facing issues while making simple POST requests from NodeJS server running on localhost. Trying, to POST JSON format data from Postman to NodeJS with express storing data to MySQL. Using the MVC method of going through the Server -> Routes (will format the data) -> Controller (validation & strong to MySQL). Error handling was applied too. but no error showing on Terminal or Postman. I've might miss something on my routes I guess. Appreciate the help. Thanks in advance!
index.js
const express = require('express');
const authRoutes = require('./routes/auth');
const errorController = require('./controllers/error');
const app = express();
const PORT = 8080;
const ports = process.env.PORT || PORT;
// MIDDLEWEAR PARSE JSON DATA
app.use(express.json());
// HEADER ACCESS CONTROL, REQUEST, ROUTES
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Methods',
'GET, POST, PUT, DELETE, OPTIONS'
);
res.setHeader(
'Access-Control-Allow-Headers',
'Content-Type, Accept, X-Custom-Header, Authorization'
);
next();
});
// AUTH
app.use('/auth', authRoutes);
// PAGE NOT FOUND
app.use(errorController.get404);
// SERVER NOT RESPONDING
app.use(errorController.get500);
app.listen(PORT, () => {
console.log(`server started at port ${ports}`);
});
Routes/auth.js
const express = require('express');
const { body } = require('express-validator');
const router = express.Router();
const User = require('../models/user');
const authController = require('../controllers/auth');
router.post(
'/signup',
[
body('email')
.isEmail()
.withMessage('Please enter a valid email.')
.custom(async (email) => {
const user = await User.find(email);
if (user[0].length > 0) {
return Promise.reject('Email address already exist!');
}
})
.normalizeEmail(),
body('password').trim().isLength({ min: 7 }),
body('admin').not().isEmpty(),
],
authController.signup
);
module.exports = router;
controllers/auth.js
const { validationResult } = require('express-validator');
const bcrypt = require('bcryptjs');
const User = require('../models/user');
exports.signup = async (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return;
const email = req.body.email;
const password = req.body.password;
const admin = req.body.admin;
try {
const hashedPassword = await bcrypt.hash(password, 12);
const userDetails = {
email: email,
password: hashedPassword,
admin: admin,
};
const results = await User.save(userDetails);
return res.status(201).json({ message: 'User registered!' });
} catch (err) {
if (!err.statusCode) {
return err.statusCode = 500;
}
next(err);
}
};
error.js
// ERROR MIDDLEWARE
exports.get404 = (req, res, next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
};
exports.get500 = (error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message,
},
});
};
Models/users.js
const db = require('../util/database');
module.exports = class User {
constructor(email, password, admin) { // TODO: , admin
this.email = email;
this.password = password;
this.admin = admin;
}
static find(email) {
return db.execute('SELECT * FROM users WHERE email = ?', [email]);
}
static save(user) {
return db.execute('INSERT INTO users (email, password) VALUES (?, ?, ?)', [
user.email,
user.password,
user.admin,
]);
}
};
Postman
POST -> http://localhost:8080/auth/signup
{
"email": "joe#gmail.com",
"password": "password",
"admin": "admin"
}
I'm creating a login and register using nodejs and mysql
when I tried it at Postman, when I registered it was successful, but when I tried to login, on the postman page it was always "sending request" and no error on code
This is the error and the code
sending request postman
enter image description here
here the code Users.js
const express = require("express")
const users = express.Router()
const cors = require('cors')
const jwt = require('jsonwebtoken')
const bcrypt = require('bcrypt')
const User = require('../models/User')
users.use(cors())
process.env.SECRET_KEY = 'secret'
users.post('/register',(req,res)=>{
const today = new Date()
const userData = {
Nama: req.body.Nama,
Nama_toko:req.body.Nama_toko,
Email: req.body.Email,
Password: req.body.Password,
create:today
}
User.findOne({
where:{
Email: req.body.Email
}
})
.then(user =>{
if(!user){
bcrypt.hash(req.body.Password,10,(err,hash)=>{
userData.Password= hash
User.create(userData)
.then(user =>{
res.json({status: user.Email + ' registered'})
})
.catch(err =>{
res.send('error: '+err)
})
})
}else{
res.json({error: "User Alredy Exits"})
}
})
.catch(err =>{
res.send('error: ' + err)
})
})
users.post('/login',(req,res)=>{
User.findOne({
where: {
Email: req.body.Email
}
})
.then(user => {
if(user){
if(bcrypt.compareSync(req.body.Password, user.Password)){
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY,{
expiresIn: 1440
})
res.send(token)
}
}else{
res.status(400).json({error: "User doesnt not exist"})
}
})
.catch(err =>{
res.status(400).json({error: "Error salah"})
})
})
module.exports = users
server.js
var express = require("express")
var cors = require("cors")
var bodyParser = require("body-parser")
var app = express()
var port = process.env.PORT || 5000
app.use(bodyParser.json())
app.use(cors())
app.use(bodyParser.urlencoded({extended: false}))
var Users = require('./routes/Users')
app.use('/Users', Users)
app.listen(port,()=>{
console.log("Server is running at : " + port)
})
If the request isn't responded, it usually means that you haven't called res.send() or res.json() on your routes.
if(bcrypt.compareSync(req.body.Password, user.Password)){
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY,{
expiresIn: 1440
})
res.send(token)
}
You don't have else block in this if, it's possible that the bcrypt.compareSync returns false and the response isn't being handled, try:
if(bcrypt.compareSync(req.body.Password, user.Password)){
let token = jwt.sign(user.dataValues, process.env.SECRET_KEY,{
expiresIn: 1440
})
res.send(token)
} else {
res.status(401).json({error: "Incorrect Password"})
}
and see if you get any response.
I am developing a nodejs express application with MySQL and for the session, authentication, and authorization I am using the passport, I dont know why but when I create the account everything goes fine. User is being created.
But when I login, it returns an error message saying "Missing credentials".
I have already seen every other Stackoverflow question regarding this problem but I haven't found a solution.
app.js
const express = require("express");
const cors = require('cors');
const accountRoute = require("./routes/account");
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.set("view engine","ejs");
app.use(express.static(__dirname + '/views'));
app.use(accountRoute.app)
app.use(accountRoute.router);
app.get("/", (req,res) => {
res.render("index.ejs");
});
app.listen(8000, () => console.log(`Listening on port 8000...`));
Login and Register
const express = require('express');
const session = require('express-session');
const flash = require('express-flash');
const bcrypt = require('bcryptjs');
const passport = require('passport');
const config = require('../config');
const initalizePassport = require('../passport');
const user = require('../models/user').User;
const router = express.Router();
const app = express();
initalizePassport(passport, async (email) => {
return await user.findOne({ where: { "email": email } }) === email;
}, async (id) => {
return await user.findOne({ where: { "id": id } }) === id;
});
app.use(session({
secret: config.sessionPassword,
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
router.get('/login', (req, res) => {
res.render('login.ejs');
});
router.post('/login', passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
}));
router.get('/register', (req, res) => {
res.render('register.ejs');
});
router.post('/register', async (req, res) => {
try {
const hashedPassword = await bcrypt.hashSync(req.body.userpass, 10);
user.create({
"email": req.body.email,
"username": req.body.username,
"userpass": hashedPassword
});
res.redirect('/login');
} catch (error) {
res.redirect('/register');
}
});
router.get('/unregister', (req, res) => {
res.render('unregister.ejs');
});
router.post('/unregister', (req, res) => {
res.send(req.body);
});
module.exports.router = router;
module.exports.app = app;
passport.js
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcryptjs')
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, userpass, done) => {
const user = getUserByEmail(email);
if (!user) {
return done(null, false, { message: 'No user with that email' })
}
try {
var correctPassword = false;
await bcrypt.compare(userpass, user.userpass, function (err, result) {
if (err) {
console.log(err);
}
else {
correctPassword = true;
console.log("passwords match!");
return;
}
});
if (correctPassword) {
return done(null, user)
} else {
return done(null, false, { message: 'Password incorrect' })
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'userpass' }, authenticateUser))
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => {
return done(null, getUserById(id))
})
}
module.exports = initialize
Login.ejs
<h1>Login</h1>
<% if(messages.error) { %>
<%= messages.error %>
<% } %>
<form action="/login" method="post">
<input name="email" type="text" placeholder="email">
<input name="userpass" type="password" placeholder="userpass">
<input type="submit" value="submit">
</form>
Now it's throwing me this:
Error: Illegal arguments: string, undefined
at _async (C:\Users\datte\Desktop\auth\node_modules\bcryptjs\dist\bcrypt.js:286:46)
at C:\Users\datte\Desktop\auth\node_modules\bcryptjs\dist\bcrypt.js:307:17
at new Promise (<anonymous>)
at Object.bcrypt.compare (C:\Users\datte\Desktop\auth\node_modules\bcryptjs\dist\bcrypt.js:306:20)
at Strategy.authenticateUser [as _verify] (C:\Users\datte\Desktop\auth\passport.js:13:24)
at Strategy.authenticate (C:\Users\datte\Desktop\auth\node_modules\passport-local\lib\strategy.js:90:12)
at attempt (C:\Users\datte\Desktop\auth\node_modules\passport\lib\middleware\authenticate.js:366:16)
at authenticate (C:\Users\datte\Desktop\auth\node_modules\passport\lib\middleware\authenticate.js:367:7)
at Layer.handle [as handle_request] (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\layer.js:95:5)
at C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:281:22
at Function.process_params (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:275:10)
at Function.handle (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:174:3)
at router (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:47:12)
at Layer.handle [as handle_request] (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:317:13)
at C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:284:7
at Function.process_params (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:335:12)
at next (C:\Users\datte\Desktop\auth\node_modules\express\lib\router\index.js:275:10)
Executing (default): SELECT `id`, `email`, `username`, `userpass`, `createdAt`, `updatedAt` FROM `Users` AS `User` WHERE `User`.`email` = 'myemail' LIMIT 1;
I am building an API with Node.js, Express, MYSQL and with the help of sequelize. I am using MVC pattern.
The problem I am encountering however is the server cannot send back any http response after request. When sending a post request for example with postman, the request keeps on loading and will terminate after around 2 minutes with COULD NOT GET ANY RESPONSE exception. While this is happening, data is correctly saved in the database.
This is my AuthController user registration method:
'use strict';
// AuthController.js
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
const Model = require('../models/index');
const User = Model.sequelize.import('../models/user');
// Register new User.
exports.register = function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
},
function (err, user) {
if (err)
{
return res.status(500).send("There was a problem registering the user. "+err)
}
else{
// create a token
var token = jwt.sign({ id: user._id }, process.env.AUTH0_CLIENT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
res.status(200).json({ auth: true, token: token });
}
});
};
// App.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const cors = require('cors');
var app = express();
var indexRoutes = require('./routes/index');
var userRoutes = require('./routes/users');
var courseRoutes = require('./routes/courses');
var authRoutes = require('./routes/auth');
// view engine setup
// Currently I am not using view-templates
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(cors()); //enable CORS
app.use(express.static(path.join(__dirname, 'public')));
//User Routes
app.use('/', indexRoutes);
app.use('/api', userRoutes);
app.use('/api', courseRoutes);
app.use('/api/auth', authRoutes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
//ROUTES
//auth.js
var express = require('express');
var router = express.Router();
//Require Controller Modules
var controller = require('../controllers/AuthController');
//Register new user
router.post('/register', controller.register);
router.get('/user', controller.me);
router.post('/login', controller.login);
router.get('/logout', controller.logout);
module.exports = router;
//User Model
'use strict';
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define('User', {
//id: DataTypes.INTEGER,
name: DataTypes.STRING,
email: {type: DataTypes.STRING, allowNull: false, unique: true, validate: { isEmail: {msg: "Invalid Email"} }},
password: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
DB Connection //in models/index.js
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(__filename);
var env = process.env.NODE_ENV || 'development';
var config = require(__dirname + '/../config/config.json')[env];
var db = {};
const Op = Sequelize.Op;
if (config.use_env_variable) {
var sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
var sequelize = new Sequelize(config.database,
config.username,
config.password,
{
host: config.host,
dialect: config.dialect,
operatorsAliases: false,
}
);
//check if connection is established
sequelize
.authenticate()
.then(() => {
console.log('Database Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
I think there is something wrong I am committing or missing out something. I am experiencing this problem when sending POST REQUESTS. Data is saved in mysql table but no response is sent back.
Please assist. Thanks.
Thank you guys for trying to assist. After working around I discovered that problem was with the controller method. The way it was structured was not sending back response after data is persisted in the database.
This is how I recoded my register method in AuthController:
//Old one
// Register new User.
exports.register = function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
},
function (err, user) {
if (err)
{
return res.status(500).send("There was a problem registering the user. "+err)
}
else{
// create a token
var token = jwt.sign({ id: user._id }, process.env.AUTH0_CLIENT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
res.status(200).json({ auth: true, token: token });
}
//Rewrite:
// Register new User.
exports.register = function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
})
.then(user=>{
// create a token
var token = jwt.sign({ id: user._id }, config.secret, {
expiresIn: 86400 // expires in 24 hours
});
return res.status(200).json({ auth: true, token: token });
}).catch(err=>{
return res.status(500).send("There was a problem registering the user. "+err)
});
};
This worked for me and the code now works as expected.