i have been facing this error of 401 unauthorized error when i tried to mount my isLoggedinMiddlware.js, and even when i can manage to print the token stored, it stil says its
authorised. Any advice or help would be appreciated! Have a nice day.
this is my isLoggedinMiddleware.js
const jwt = require("jsonwebtoken");
const JWT_SECRET = process.env.JWT_SECRET;
module.exports = (req, res, next) => {
const authHeader = req.headers.authorization;
if (authHeader === null || authHeader === undefined || !authHeader.startsWith("Bearer ")) {
res.status(401).send();
return;
}
const token = authHeader.replace("Bearer ", "");
jwt.verify(token, JWT_SECRET, { algorithms: ["HS256"] }, (error, decodedToken) => {
if (error) {
res.status(401).send();
return;
}
req.decodedToken = decodedToken;
next();
});
};
this is my post api
app.post("/listings/",isLoggedInMiddleware,(req,res)=>{
listings.insert(req.body,(error,result)=>{
if(error){
console.log(error)
console.log(req.body)
console.log(isLoggedInMiddleware)
res.status(500).send('Internal Server Error')
return;
}
console.log(result)
res.status(201).send({"Listing Id":result.insertId})
})
})
This is my front end
const baseUrl = "http://localhost:3000";
const loggedInUserID = parseInt(localStorage.getItem("loggedInUserID"));
const token = localStorage.getItem("token")
console.log(token)
if(token === null || isNaN(loggedInUserID)){
window.location.href = "/login/"
}else{
$('#logoff').click(function(){
event.preventDefault();
localStorage.removeItem('token')
localStorage.removeItem('loggedInUserID')
window.alert('Logging out now')
window.location.href = "/login/"
})
$(document).ready(function () {
$('#submitbtn').click((event) => {
const loggedInUserID = parseInt(localStorage.getItem("loggedInUserID"));
// middleware = {headers:{'Authorization':'Bearer '+token},data:{id: loggedInUserID}}
event.preventDefault();
const itemName = $("#itemName").val();
const itemDescription = $("#itemDescription").val();
const price = $('#price').val();
const image = $('#image').val();
const requestBody = {
itemName: itemName,
itemDescription: itemDescription,
price: price,
fk_poster_id: loggedInUserID,
imageUrl: image
}
console.log(requestBody);
axios.post(`${baseUrl}/listings/`,{headers:{'Authorization':'Bearer '+token},data:{id: loggedInUserID}}, requestBody)
.then((response) => {
window.alert("successfully Created")
})
.catch((error) => {
window.alert("Error")
console.log(requestBody)
})
})
})
}
i can managed to get the token i stored when i log in, however, it stills say 401 unauthorised.
Related
Good day developers, recently as been working in this node js app, and when implementing jwt library i got an error related to tghe verify() method in this jwt repo.
Kind of :
return secretCallback(null, secretOrPublicKey);
^
TokenExpiredError: jwt expired
The repo is structured in several folders:
controllers
middlewares
helpers
socket controllers
On my middleware folder, sepecifically in a file related to jwt validation i settled this:
file middleware jwt-validation
export {};
const { request, response } = require("express");
const User = require("../models/user-model");
const jwt = require("jsonwebtoken");
const jwtValidator = async (req = request, res = response, next) => {
const token_response = req.header("token-response");
if (!token_response) {
return res.status(401).json({
message: "Not valid token .You don't have authorization",
});
}
try {
const payload = await jwt.verify(token_response, process.env.SECRETKEYJWT)
const userAuth = await User.findById(payload.id);
if (userAuth.userState != true) {
return res.status(401).json({
message: "User inhabilitated",
});
}
if (!userAuth) {
return res.status(404).json({
message: "User not found",
});
}
req.user = userAuth;
next();
} catch (error) {
return res.status(500).json({
message: "Not valid token.Error 500",
});
}
};
module.exports = { jwtValidator };
file middleware jwt-validation-sockets
import { UserSchema } from "../interfaces";
const jwt = require("jsonwebtoken");
const User = require("../models/user-model");
const jwtValidatorRenew = async (
token: string = ""
): Promise<UserSchema | null> => {
if (token == "" || token.length < 10 || token == undefined) {
return null;
}
const payloadToken = await jwt.verify(token, process.env.SECRETKEYJWT)
const userTokenDecoded: UserSchema = User.findById(payloadToken.id);
if (userTokenDecoded?.userState) {
return userTokenDecoded;
} else {
return null;
}
};
module.exports = { jwtValidatorRenew };
file helper jwt-generator
const { request, response } = require("express");
const jwt = require("jsonwebtoken");
const createJWT = async (id = "", nickname = "") =>
return new Promise((resolve, reject) => {
const payloadInJWT = { id, nickname };
jwt.sign(
payloadInJWT,
process.env.SECRETKEYJWT,
{
expiresIn: 3600,
},
//calback
(error:any, token:string) => {
if (error) {
alert(error)
reject("Error creating token ");
} else {
resolve(token);
}
}
);
});
};
module.exports = { createJWT };
file socket-controller
const { jwtValidatorRenew } = require("../middlewares/jwt-validation-socket");
const { userData } = require("../helpers/helper-user-schema-data");
const { Socket } = require("socket.io");
const User = require("../models/user-model");
const {
ChatMessage,
Message,
MessagePrivate,
GroupChat,
} = require("../models/chat-model");
const chatMessage = new ChatMessage()
const socketController = async (socket = new Socket(), io) => {
const user = await jwtValidatorRenew(
socket.handshake.headers["token-response"]
);
try {
...some sockets flags
} catch (error) {
socket.disconnect();
}
};
module.exports = { socketController };
Basically, I get an error saying "Cannot set headers after they are sent to the client". i tried redoing everything.
this is the form code:
const loader = document.querySelector('.loader');
// selecionar inputs
const submitBtn = document.querySelector('.submit-btn');
const name = document.querySelector('#name');
const email = document.querySelector('#email');
const password = document.querySelector('#password');
const number = document.querySelector('#number');
const tac = document.querySelector('#terms-and-cond');
const notification = document.querySelector('#notifications');
submitBtn.addEventListener('click', () => {
if(name.value.length < 3){
showAlert('name must be 3 letters long');
} else if (!email.value.length){
showAlert('enter your email');
} else if (password.value.length < 8){
showAlert('password should be 8 letters long');
} else if (!number.value.length){
showAlert('enter your phone number');
} else if (!Number(number.value) || number.value.length < 10){
showAlert('invalid number, please enter valid one');
} else if (!tac.checked){
showAlert('You must agree to our terms and conditions');
} else{
// para dar submit
loader.style.display = 'block';
sendData('signup', {
name: name.value,
email: email.value,
password: password.value,
number: number.value,
tac: tac.checked,
notification: notification.checked,
seller: false
})
}
})
// mandar a função dos dados
const sendData = (path, data) => {
fetch(path, {
method: 'post',
headers: new Headers({'Content-Type': 'application/json'}),
body: JSON.stringify(data)
}).then((res) => res.json())
.then(response => {
processData(response);
})
}
const processData = (data) => {
loader.style.display = null;
if(data.alert){
showAlert(data.alert);
}
}
const showAlert = (msg) => {
let alertBox = document.querySelector('.alert-box');
let alertMsg = document.querySelector('.alert-msg');
alertMsg.innerHTML = msg;
alertBox.classList.add('show');
setTimeout(() => {
alertBox.classList.remove('show');
}, 3000);
}
again, and I still get the same error...
and this is the server code:
// importar os packages
const express = require('express')
const admin = require('firebase-admin');
const bcrypt = require('bcrypt');
const path = require('path');
// setup da firebase - admin
let serviceAccount = require("./haza---pap-firebase-adminsdk-lrx0l-0da425a226.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});
let db = admin.firestore();
// declarar um caminho estatico
let staticPath = path.join(__dirname, "public");
// inicializar o express.js
const app = express();
//middlewares
app.use(express.static(staticPath));
app.use(express.json());
// routes
// home route
app.get("/", (req, res) => {
res.sendFile(path.join(staticPath, "index.html"));
})
//route do signup
app.get('/signup', (req, res) =>{
res.sendFile(path.join(staticPath, "signup.html"));
})
app.post('/signup', (req, res) => {
let {name, email, password, number, tac, notification } = req.body;
// validações do form
if (name.length < 3){
return res.json({'alert': 'name must be 3 letters long'});
} else if (!email.length){
return res.json({'alert': 'enter your email'});
} else if (password.length < 8){
return res.json({'alert' :'password should be 8 letters long'});
} else if (!number.length){
return res.json({'alert' : 'enter your phone number'});
} else if (!Number(number) || number.length < 10){
return res.json({'alert' :'invalid number, please enter valid one'});
} else if (!tac){
return res.json({'alert' : 'You must agree to our terms and conditions'});
} else {
// guardar utilizadores na base de dados
db.collection('users').doc(email).get()
.then(user => {
if(user.exists){
return res.json({'alert': 'email already exists'});
} else{
// encriptar a password antes de guarda-la.
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(password, salt, (err, hash) => {
req.body.password = hash;
db.collection('users').doc(email).set(req.body)
.then(data => {
res.json({
name: req.body.name,
email: req.body.email,
seller: req.body.seller,
})
})
})
})
}
})
}
res.json('data recieved');
})
//route do 404
app.get('/404', (req, res) => {
res.sendFile(path.join(staticPath, "404.html"));
})
app.use((req, res) => {
res.redirect('/404');
})
app.listen(3000, () => {
console.log('listening on port 3000.......');
})
You are setting some data in response obj after send is being processed by node js.
Try using: res.end() after your all res.send.. events
Ref: https://www.geeksforgeeks.org/express-js-res-end-function/#:~:text=end()%20Function,-Last%20Updated%20%3A%2005&text=The%20res.,Node%20core%2C%20specifically%20the%20response.
You are sending response twice in /signup route.
Remove res.json('data recieved'); and it should work fine
That Error happens when you res. and then res. again to the client. Responding to the client several times is erroneous in node.
Check your route req,res cycles. Remember middleware .use() execute sequentially, and routes execute usually in between so...good luck
I am working on express js api with jwtr,when i run the api it gives me error:
UnhandledPromiseRejectionWarning: Error: Can't set headers after they
are sent.
can anyone please help me why i am getting this error, here i have added my code, can anyone please look in it, and help me to resolve this issue,
const requireAuthentication = async(req, res, next) => {
try {
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxUWpuTDBhd2lTIiwiaWF0IjoxNTY5OTQwMjgyfQ.1xwX2OULW4RjKW4Ok13mwlJE8k95u-d0o7T6k5U9tjs'; //req.headers['vrc-access-token'];
if (!token) return res.status(401).send('Failed to authenticate token.');
let verify_token_data = await jwtr.verify(token, secret);
if(typeof verify_token_data.jti != 'undefined') {
req.body.username = verify_token_data.username;
req.body.organization = verify_token_data.organization;
req.body.userId = verify_token_data.id;
req.body.organizationId = verify_token_data.organizationId;
console.log("sdsd234");
// create a new token
const newToken = await jwtr.sign({
username: verify_token_data.username,
organization: verify_token_data.organization,
id: verify_token_data.id,
organizationId: verify_token_data.organizationId
}, config['token-secret']);
console.log(newToken);
req.refreshToken = newToken;
console.log('sdfdf');
return await next();
} else {
return res.status(401).send('Failed to authenticate token.');
}
} catch (error) {
return res.status(401).send(error.message);
}
};
i have had this issue before and it happens because you have already send the response back to the server and it reaches a code which sends a response again.
i think that the issue is when you do
return await next()
what you should do is:
next()
const requireAuthentication = async(req, res, next) => {
try {
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxUWpuTDBhd2lTIiwiaWF0IjoxNTY5OTQwMjgyfQ.1xwX2OULW4RjKW4Ok13mwlJE8k95u-d0o7T6k5U9tjs'; //req.headers['vrc-access-token'];
if (!token) return res.status(401).send('Failed to authenticate token.');
let verify_token_data = await jwtr.verify(token, secret);
if(typeof verify_token_data.jti != 'undefined') {
req.body.username = verify_token_data.username;
req.body.organization = verify_token_data.organization;
req.body.userId = verify_token_data.id;
req.body.organizationId = verify_token_data.organizationId;
// create a new token
const newToken = await jwtr.sign({
username: verify_token_data.username,
organization: verify_token_data.organization,
id: verify_token_data.id,
organizationId: verify_token_data.organizationId
}, config['token-secret']);
console.log(newToken);
req.refreshToken = newToken;
next();
} else {
return res.status(401).send('Failed to authenticate token.');
}
} catch (error) {
return res.status(401).send(error.message);
}
};
I am currently getting a "ReferenceError: logger is not defined" error when I am running some tests. These errors did not occur while my endpoints were in my app.js. They only started occurring when I moved my endpoints into my router file.
My endpoints all work in postman and can retrieve the data but for some reason all my tests are failing. Is there something I am missing in my router file?
const express = require("express");
const uuid = require("uuid/v4");
const logger = require("../logger");
const { bookmarks } = require("../store");
const BookmarksService = require("../bookmarks-service");
const bookmarkRouter = express.Router();
const bodyParser = express.json();
bookmarkRouter
.route("/bookmarks")
.get((req, res, next) => {
const knexInstance = req.app.get("db");
BookmarksService.getAllBookmarks(knexInstance)
.then(bookmarks => {
res.json(bookmarks);
})
.catch(next);
})
.post(bodyParser, (req, res) => {
//implementation
for (const field of ["title", "url", "rating"]) {
if (!req.body[field]) {
logger.error(`${field} is required`);
return res.status(400).send(`${field} is required`);
}
}
const { title, url, rating, desc } = req.body;
if (!title) {
logger.error("Title is required");
return res.status(400).send("Invalid data");
}
if (!url) {
logger.error("Url is required");
return res.status(400).send("Invalid data");
}
if (!desc) {
logger.error("Desc is required");
return res.status(400).send("Invalid data");
}
const id = uuid();
const bookmark = {
id,
title,
url,
rating,
desc
};
bookmarks.push(bookmark);
logger.info(`Bookmark with bookmark ${id} created`);
res
.status(201)
.location(`http://localhost.8000/bookmark/${id}`)
.json(bookmark);
});
bookmarkRouter
.route("/bookmarks/:id")
.get((req, res, next) => {
//implementation
const { id } = req.params;
const bookmark = bookmarks.find(b => b.id == id);
const knexInstance = req.app.get("db");
BookmarksService.getById(knexInstance, id)
.then(bookmark => {
if (!bookmark) {
logger.error(`Bookmark with id ${id} not found`);
return res.status(404).send({
error: { message: `Bookmark doesn't exist` }
});
}
res.json(bookmark);
})
.catch(next);
})
.delete((req, res) => {
//implementation
const { id } = req.params;
const bookmarkIndex = bookmarks.findIndex(li => li.id == id);
if (bookmarkIndex === -1) {
logger.error(`Bookmark with id ${id} not found.`);
return res.status(400).send("Not found");
}
bookmarks.splice(bookmarkIndex, 1);
logger.info(`Bookmark with id ${id} deleted`);
res.status(204).end();
});
module.exports = bookmarkRouter;
I tried to implement jwt token generation in node js.I got jwt token but how to validate token using node js crud operation.but I got token jwt verfiy code using callback function.without call back function used to implement async/awit function implement.
index.js
router.post('/', async (req, res) => {
(async function() {
try {
await client.connect();
console.log("Connected correctly to server");
const db = client.db('olc_prod_db');
//Validation
const { error } = validate.validate(req.body);
if (error)
{
return res.status(400).send(error.details[0].message);
}
else
{
const check_login = req.body
const r = await db.collection('UserRegistration').find().toArray();
r.forEach(element => {
if(element['username'] == check_login['username'])
{
const token = get_token.validate(req.body)
res.send({"token ":token})
}
else
{
return res.send(401,"Un Authorized");
}
});
}
client.close();
} catch(err) {
console.log(err.stack);
}
})();
});
authtoken.js
var jwt = require('jsonwebtoken')
function get_token(userdata)
{
var accessToken = jwt.sign(userdata, 'secretkey', {
//Set the expiration
expiresIn: 3600 //we are setting the expiration time of 1 hr.
});
//send the response to the caller with the accesstoken and data
console.log('Authentication is done successfully.....');
return accessToken
}
exports.validate = get_token;
const jwt = require('jsonwebtoken')
const config = require('../../config/default')
function verifyjwt(req,res,next){
const token = req.headers['authorization']
if(!token) return res.status(401).json('Unauthorize user')
try{
const decoded = jwt.verify(token,config.secret);
req.user = decoded
next()
}catch(e){
res.status(400).json('Token not valid')
}
}
module.exports = verifyjwt
const CONST = require('../../config')
exports.validJWTNeeded = (req, res, next) => {
if (req.headers['authorization']) {
try {
let authorization = req.headers['authorization'].split(' ');
if (authorization[0] !== 'Bearer') {
return res.status(401).send('invalid request'); //invalid request
} else {
req.jwt = jwt.verify(authorization[1], CONST.SECRET);
return next();
}
} catch (err) {
return res.status(403).send(); //invalid token
}
} else {
return res.status(401).send('invalid request');
}
}