How to create a unprotected api in Json server jwt auth - json

I am using json server with jwt auth to create a fake api.After successful registration or login i am receiving one token and using this token I can access the database.json.Without registation or login i can't access database.json file,but I want to access one api with out verifying my self to show all product to guest user.how it is possible.
I want a api like localhost:8000/products so I can access it without authorization,how to archive this in this js file.
I am using this code from git.
https://github.com/techiediaries/fake-api-jwt-json-server/blob/master/server.js
const fs = require('fs')
const bodyParser = require('body-parser')
const jsonServer = require('json-server')
const jwt = require('jsonwebtoken')
const server = jsonServer.create()
const router = jsonServer.router('./database.json')
const userdb = JSON.parse(fs.readFileSync('./users.json', 'UTF-8'))
server.use(bodyParser.urlencoded({extended: true}))
server.use(bodyParser.json())
server.use(jsonServer.defaults());
const SECRET_KEY = '123456789'
const expiresIn = '1h'
// Create a token from a payload
function createToken(payload){
return jwt.sign(payload, SECRET_KEY, {expiresIn})
}
// Verify the token
function verifyToken(token){
return jwt.verify(token, SECRET_KEY, (err, decode) => decode !== undefined ? decode : err)
}
// Check if the user exists in database
function isAuthenticated({email, password}){
return userdb.users.findIndex(user => user.email === email && user.password === password) !== -1
}
// Register New User
server.post('/auth/register', (req, res) => {
console.log("register endpoint called; request body:");
console.log(req.body);
const {email, password} = req.body;
if(isAuthenticated({email, password}) === true) {
const status = 401;
const message = 'Email and Password already exist';
res.status(status).json({status, message});
return
}
fs.readFile("./users.json", (err, data) => {
if (err) {
const status = 401
const message = err
res.status(status).json({status, message})
return
};
// Get current users data
var data = JSON.parse(data.toString());
// Get the id of last user
var last_item_id = data.users[data.users.length-1].id;
//Add new user
data.users.push({id: last_item_id + 1, email: email, password: password}); //add some data
var writeData = fs.writeFile("./users.json", JSON.stringify(data), (err, result) => { // WRITE
if (err) {
const status = 401
const message = err
res.status(status).json({status, message})
return
}
});
});
// Create token for new user
const access_token = createToken({email, password})
console.log("Access Token:" + access_token);
res.status(200).json({access_token})
})
// Login to one of the users from ./users.json
server.post('/auth/login', (req, res) => {
console.log("login endpoint called; request body:");
console.log(req.body);
const {email, password} = req.body;
if (isAuthenticated({email, password}) === false) {
const status = 401
const message = 'Incorrect email or password'
res.status(status).json({status, message})
return
}
const access_token = createToken({email, password})
console.log("Access Token:" + access_token);
res.status(200).json({access_token})
})
server.use(/^(?!\/auth).*$/, (req, res, next) => {
if (req.headers.authorization === undefined || req.headers.authorization.split(' ')[0] !== 'Bearer') {
const status = 401
const message = 'Error in authorization format'
res.status(status).json({status, message})
return
}
try {
let verifyTokenResult;
verifyTokenResult = verifyToken(req.headers.authorization.split(' ')[1]);
if (verifyTokenResult instanceof Error) {
const status = 401
const message = 'Access token not provided'
res.status(status).json({status, message})
return
}
next()
} catch (err) {
const status = 401
const message = 'Error access_token is revoked'
res.status(status).json({status, message})
}
})
server.use(router)
server.listen(8000, () => {
console.log('Run Auth API Server')
})

Related

My Express MySQL server get crash when user input wrong data for login

When the user try to login with wrong email or password my app throw error user not found if the email is not in dB a other error then password is wrong but after few second the server get crashed with the error
"SERVER CONNECTION LOST"
I was Thing the problem come in my error handling but after many try and search i'm now block
export const getUser = (req, res) => {
const token = req.cookies.accessToken;
if (!token) return res.status(401).json("Please logging first !");
jwt.verify(token, "secretkey", (err, data) =\> {
if (err) {
return res.status(403).json("Please login first !!");
}
const q = "SELECT * FROM `Users` WHERE ID= ?";
db.query(q, [req.params.userId], (err, data) => {
if (err) return res.status(500).json("Something when wrong !!");
const { user_PassCode, ...info } = data[0];
if(data) return res.json(info);
});
});
};
//...........LOGIN START HERE...............
export const logIn = (req, res) => {
const q = "SELECT * FROM Users WHERE user_Email = ? "
db.query(q, [req.body.user_Email], (err, data) => {
if (err) res.status(500).json(err)
if(data.length === 0) res.status(404).json('user not found!')
// chech if password match to userPasscode
const checkPassword = bcrypt.compareSync(
req.body.user_PassCode,
data[0].user_PassCode
)
if(!checkPassword) return res.status(400).json('wrong password or username try again!')
const token = jwt.sign({ id: data[0].ID }, "secretkey")
const {user_PassCode, ...others} = data[0]
// if not error
res.cookie("accessToken", token, {
httpOnly: true
}).status(200).json(others)
})
}

Here i m trying to get complete data of authorized user to profile after login. tell me how to get user data in middleware

Middleware
my database is MYSQL and i m using sequelize. i tried findByPK() but that was not working
import jwt from "jsonwebtoken";
export const verifyToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if(token == null) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET_KEY, (err, decoded) => {
if(err) return res.sendStatus(403);
req.email = decoded.email;
next();
})
}
contollerenter code here
export const loggedUser = async (req, res) => {
res.send({ "user": req.user })
}
just call the middleware like this :
router.get('/getUser', verifyToken, loggedUser);
So frst parameter is the end-point's name, second is your middleware, third is your controller function

Cannot set headers after they are sent to the client error when add code to redirect another page

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}`)
})

Could not get response when making POST request from Postman to Node.js (express), MySQL

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"
}

using bcrypt for login in nodejs

I'm having a hard time with integrating bcrypt to try to make my login system safe.
I basically get the username, password the user inputs and try to compare it from the hashed password in my db. here's what I have.
const inputUsername = req.body.inputUsername;
const inputPassword = req.body.inputPassword;
var userLogin = "select * from login where USERNAME = ?"
ibmdb.open(ibmdbconnMaster, function(err, conn) {
if (err) return console.log(err);
conn.query(userLogin, [inputUsername], function(err, rows) {
if (err) {
console.log(err)
}
if (rows.length > 0) {
var pass = ""
for (var i = 0; i < rows.length; i++) {
pass = rows[i]['PASSWORD'];
console.log(pass)
bcrypt.compare(inputPassword, hash, function(err, result) {
if (pass == result) {
console.log("this works")
userAuth = true;
res.redirect('/index')
}
})
}
console.log("does not work")
} else {
userAuth = "false";
res.render('login.ejs')
alert('Incorrect username or password. Please try again')
}
conn.close(function() {
console.log('closed the function /login');
});
})
})
what happens right now is I get the error ReferenceError: hash is not defined
not sure how to fix this. thanks in advance
Where have you defined hash? I don't see it in your code.
Here's an example of auth routes that I've used with bcrypt/node/express:
const Users = require("../users/users-model.js");
router.post("/register", (req, res) => {
// Pull the user's credentials from the body of the request.
const user = req.body;
// Hash the user's password, and set the hashed password as the
// user's password in the request.
const hash = bcrypt.hashSync(user.password, 10);
user.password = hash;
Users.add(user)
.then((newUser) => {
const token = generateToken(newUser);
res
.status(201)
.json({ created_user: newUser, token: token, user_id: newUser.id });
})
.catch((err) => {
res.status(500).json({
message: "There was an error adding a user to the database",
err,
});
});
});
router.post("/login", (req, res) => {
const { username, password } = req.body;
Users.findBy({ username })
.first()
.then((user) => {
if (user && bcrypt.compareSync(password, user.password)) {
const token = generateToken(user);
res
.status(200)
.json({
username: user.username,
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
token: token,
user_id: user.id,
});
} else {
res.status(401).json({ message: "Invalid Credentials" });
}
})
.catch((err) => {
res.status(500).json(err);
});
});
function generateToken(user) {
const payload = {
userid: user.id,
username: user.username,
};
const options = {
expiresIn: "1h",
};
const token = jwt.sign(payload, secrets.jwtSecret, options);
return token;
}
module.exports = router;