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');
}
}
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 };
I have a function that checks the existence and validity of a token and makes a new request to get a new token if the token does not exists or is expired.
But the function always returns a promise instead of the data, and can not use it further.
const checkToken = (token) => {
if (!token || !(token.hasOwnProperty('expiry') && Object.prototype.toString.call(token.expiry) === '[object Date]') && !isExpired(token.expiry)) {
token = axios(getOptions()).then(resp => {
console.log(resp.data.expires_in);
let today = new Date();
let expiry = new Date(today.getTime() + 1000*(resp.data.expires_in));
return ({
'token': resp.data.access_token,
'expiry': expiry
});
});
return token;
}
return token;
}
checkToken is consumed like so:
const axios = require('axios');
let token;
exports.handler = (event, context, callback) => {
console.log(token);
console.log(event);
token = checkToken(token);
let options = getReqOptions(event,token);
console.log(options)
return options
};
Thanks for help!
Yes Axios return a promise but you're again returning a promise using then. You're using then value for token. That's why you're seeing token as a promise. You can simply use async/await to get same(more readable).
const checkToken = async (token) => {
if (!token || !(token.hasOwnProperty('expiry') && Object.prototype.toString.call(token.expiry) === '[object Date]') && !isExpired(token.expiry)) {
try {
const reponse = await axios(getOptions())
console.log(reponse.data.expires_in);
const expiry = new Date(today.getTime() + 1000 * (reponse.data.expires_in));
return {
token: resp.data.access_token,
expiry
}
} catch(err) {
console.log('Error while getting token ', err)
// handle error here if any
}
}
return token
}
const axios = require('axios');
let token;
exports.handler = async (event, context, callback) => {
console.log(token);
console.log(event);
try {
token = await checkToken(token);
let options = getReqOptions(event, token);
console.log(options)
return options
} catch (err) {
console.log(err)
}
};
I cannot able to validate the webhook response from the shopify by using the "shopify-node-api". and i am using the following code to validate the signature.
Below code is on app.js
app.use(bodyParser.json({
type:'application/json',
limit: '50mb',
verify: function(req, res, buf, encoding) {
if (req.url.startsWith('/webhook')){
req.rawbody = buf;
}
}
})
);
app.use("/webhook", webhookRouter);
Below on webhook.router.js
router.post('/orders/create', verifyWebhook, async (req, res) => {
console.log('🎉 We got an order')
res.sendStatus(200)
});
Below for the verification function
function verifyWebhook(req, res, next) {
let hmac;
let data;
try {
hmac = req.get("X-Shopify-Hmac-SHA256");
data = req.rawbody;
} catch (e) {
console.log(`Webhook request failed from: ${req.get("X-Shopify-Shop-Domain")}`);
res.sendStatus(200);
}
if (verifyHmac(JSON.stringify(data), hmac)) { // Problem Starting from Here
req.topic = req.get("X-Shopify-Topic");
req.shop = req.get("X-Shopify-Shop-Domain");
return next();
}
return res.sendStatus(200);
}
Verify signature function
function verifyHmac(data, hmac) {
if (!hmac) {
return false;
} else if (!data || typeof data.data !== "object") {
// I am Getting Error HERE
console.log('Error in data', data);
return false;
}
const sharedSecret = config.shopify_shared_secret;
const calculatedSignature = crypto
.createHmac("sha256", sharedSecret)
.update(Buffer.from(data), "utf8")
.digest("base64");
console.log('calculatedsecret', calculatedSignature);
return calculatedSignature === hmac;
};
and the body I am getting it as undefined. suggest me how to fix this problem in shopify webhook API
Instead of using the bodyparser.json() use bodyparser.raw to fetch the all the payload to process the shopify webhook verification.
router.use(bodyparser.raw({ type: "application/json" }));
// Webhooks
router.post("/", async (req, res) => {
console.log("Webhook heard!");
// Verify
const hmac = req.header("X-Shopify-Hmac-Sha256");
const topic = req.header("X-Shopify-Topic");
const shop = req.header("X-Shopify-Shop-Domain");
const verified = verifyWebhook(req.body, hmac);
if (!verified) {
console.log("Failed to verify the incoming request.");
res.status(401).send("Could not verify request.");
return;
}
const data = req.body.toString();
const payload = JSON.parse(data);
console.log(
`Verified webhook request. Shop: ${shop} Topic: ${topic} \n Payload: \n ${data}`
);
res.status(200).send("OK");
});
// Verify incoming webhook.
function verifyWebhook(payload, hmac) {
const message = payload.toString();
const genHash = crypto
.createHmac("sha256", process.env.API_SECRET)
.update(message)
.digest("base64");
console.log(genHash);
return genHash === hmac;
}
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.
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);
}
};