I am using mern stack to make one website. I am using jwt and trying to store them in cookies. I invoked the res.cookie function with parameters(you can find the code below). But somehow I cannot find the cookie in the browser.
no cookie found(top portion) whereas name of cookie(=jwt) found in network tab in inspect. Please look at this screenshot
But when I check the network tab in the inspect, there is a cookie present in Set-cookie.
Assuming that the cookie has been stored, I try to access the jwt token, but in vain.
I am providing the code below.
This is my file where all the routes are written.
const express = require ("express")
const Resident = require("../models/residentModels");
const bcrypt = require("bcrypt");
// const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const router = express.Router();
router.post("/register", async (req, res) =\> {
try {
const resident = new Resident(req.body);
console.log(req.body);
// password hash
// middleware
const token = await resident.generateAuthToken();
console.log("token: " + token);
res.cookie("jwt", token, {
httpOnly: true,
expires: new Date (Date.now() + 12342)
})
// console.log(cookie);
const newResident = await resident.save();
console.log("hehe" + newResident);
// console.log(newResident._id);
// console.log(newResident._id.toString());
res.status(200).send("Record Added Successfully");
} catch (error) {
console.log(error);
res.status(200).send("Record Creation Unsuccessfull");
}
})
router.post("/login", async (req, res) =\> {
try {
let blockNumber = req.body.blockNumber;
let flatNumber = req.body.flatNumber;
let password = req.body.password;
console.log(blockNumber)
console.log(flatNumber)
console.log(password)
const response = await Resident.findOne({blockNumber: blockNumber, flatNumber:flatNumber});
console.log(response);
const isMatch = await bcrypt.compare(password, response.password);
console.log("isMatch: " + isMatch);
const token = await response.generateAuthToken();
console.log("token part: " + token);
let cookie = res.cookie("jwt", token, {
httpOnly: true,
expires: new Date (Date.now() + 10000)
})
// console.log(cookie)
// console.log(`this is the cookie awesome !! + ${req.cookies.jwt}`);
let jwtToken = req.cookies;
console.log("req.cookies.jwt: " + jwtToken);
if(isMatch){
res.status(200).send("Successful Login");
}
else{
res.status(200).send("Invalid Login Details");
}
} catch (error) {
res.status(200).send("Invalid Login Details");
}
});
module.exports = router;
This is my index.js file :
const express = require("express");
require('./db/conn');
const Resident = require("./routes/residentRoutes");
var cors = require("cors");
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cors());
app.use(express.json());
app.use(Resident);
app.use(cookieParser());
const port = process.env.PORT || 8000;
const bcrypt = require("bcrypt");
const securePassword = async (password) =\> {
const passwordHash = await bcrypt.hash(password, 10);
console.log(passwordHash);
const passwordMatch = await bcrypt.compare(password, passwordHash)
console.log(passwordMatch);
}
securePassword("thapa#123");
const createToken = async () =\> {
const token = await jwt.sign({\_id: "63e677a57d45b06c8557441a"}, "thisisnotformyresumebutmyideology!!!",{
expiresIn: "20 seconds"
})
console.log(token);
const userVerify = await jwt.verify(token, "thisisnotformyresumebutmyideology!!!");
console.log(userVerify); // returns an object
}
createToken();
app.listen(port, () =\> {
console.log(`connection successful at port ${port}`);
})
In the file where all the routes are written, the variable jwtToken returns "undefined".
As a result, it is evident that the cookie was not stored.
So now the question arises how do I store the cookies and where am I doing wrong?
P.S.: I am using React.js in the frontend.
My Login.jsx file looks like this:
import axios from 'axios';
import React from 'react'
import { NavLink, useNavigate } from 'react-router-dom'
const Login = () => {
let navigate = useNavigate();
const loginButton = async (event) => {
event.preventDefault();
// console.log(event.target[0].value); // block number
let blockNumber = event.target[0].value;
let flatNumber = event.target[1].value;
let password = event.target[2].value;
const response = await axios.post('http://localhost:8000/login', {
blockNumber: blockNumber,
flatNumber: flatNumber,
password: password
})
// console.log("response :" + response.data);
console.log(response);
if(response.status === 200){
navigate("/dashboard");
}
else{
alert("Invalid Login Details");
}
}
return (
<>
<h1> Login </h1>
<form onSubmit={loginButton}>
<input type="number" placeholder='Block Number *' />
<input type="number" placeholder='Flat Number *' />
<input type="password" placeholder='Password *' />
<button type="submit">Login</button>
<NavLink to='/register'>or Click to Register</NavLink>
</form>
</>
)
}
export default Login
In your index.js file
Swap these two from:
app.use(Resident);
app.use(cookieParser());
to:
app.use(cookieParser());
app.use(Resident);
You need to parse the request first before accessing the routes
The sequence matter how you place your code
can you see the cookies in the application tab of browser developer tools?
If you can, are you using axios? If so, it might be because of that, you need to add withCredentials: true in the axios constructor.
axios("http://someurl", {
method: "post",
data: someJsonData,
withCredentials: true
})
Related
I'm very new to backend development and I'm trying to figure out how to send my form data from front to backend. I watched a youtube tutorial on how and this is my code for server.js:
const express = require("express");
const app = express();
const port = 2009;
app.use(express.static("public"));
app.use(express.json());
app.get("/", (req, res) => {
res.status(200).json({info: "something"});
});
app.post("/", (req, res) => {
const { parcel } = req.body;
if (!parcel) {
return res.status(400).send({status: "failed"});
}
res.status(200).send({status: "recieved"});
});
app.listen(port, () => console.log(`server.js running on port: ${port}`));
And here is the code for script.js for my form:
const submit = document.getElementById("submit");
const userName = document.getElementById("user");
const password = document.getElementById("pass");
const email = document.getElementById("mail");
const baseUrl = "http://localhost:2009/"
async function post(e) {
e.preventDefault();
const res = await fetch(baseUrl + "website?key=hello", {
method: "POST"
})
}
Like I said I basically have no clue what I am doing could someone help me?
I haven't tested it yet because I'm afraid it won't work if would be very helpful if someone could show me some code or point me to some documentation so that I can work in the right direction.
you seem to be on the right track just a few changes and additions.
const registerForm = document.getElementById('register_form');
async function post(e) {
const form = document.forms.register_form;
const email = form.email.value;
const password = form.password.value;
const username = form.username.value;
try {
const res = await fetch(baseUrl + "website?key=hello", {
method: "POST",
body: JSON.stringify({
email,
username,
password,
}),
headers: { "Content-Type": "application/json" },
});
// handle the response here
} catch (error) {
// handle error here
}
}
registerForm.addEventListener('submit', post, false);
on the backend, you will need a route to handle this request
app.post("/", (req, res) => {
const { username, email, password } = req.body;
// validate the data from the request
if (!username || !email || !password) {
return res.status(400).send({
status: "failed",
message: "fields are required"
});
}
res.status(201).send({status: "recieved"});
});
StatusCode 201 indicates a new resource has been created
References:Using Fetch Api statusCode
I hope this helps.
I am new to coding. I am trying CRUD operation with express.js and MongoDB atlas for database on my project but when I am fetch for loading data for my client site server its error:
var _this = _super.call(this, message) || this;
BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
I am trying a lot but no result.
this is my code:
//this is client site code:
import React from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
import { Link, useParams } from 'react-router-dom';
const MeetingDetail = () => {
const {meetingId} = useParams()
const [meeting, setMeeting] = useState({})
console.log(meeting)
useEffect(() => {
const url = `http://localhost:5000/meeting/${meetingId}`;
console.log(url)
fetch(url)
.then(res => res.json())
.then(data => setMeeting(data))
},[])
return (
<div className='mx-auto w-75'>
<h1>meetingID : {meeting.age}</h1>
<Link to='/checkout'><button className='btn btn-primary mx-auto'>
Process Checkout</button></Link>
</div>
);
};
export default MeetingDetail;
//this is server site code:
const express = require("express");
const cors = require("cors");
require("dotenv").config();
const port = process.env.PORT || 5000;
const { MongoClient, ServerApiVersion, ObjectId } = require("mongodb");
const app = express();
// middleware
app.use(cors());
app.use(express.json());
// from Mongodb
const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}#cluster0.9nfwrgy.mongodb.net/?retryWrites=true&w=majority`;
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
serverApi: ServerApiVersion.v1,
});
console.log("mongo connected");
async function run() {
try {
await client.connect();
const meetingCollection = client.db("hotelRoom").collection("meeting");
// create main link for component data
app.get("/meeting", async (req, res) => {
const query = {};
const cursor = meetingCollection.find(query);
const meetings = await cursor.toArray();
res.send(meetings);
});
// create main link id for component data
app.get("/meeting/:id", async (req, res) => {
const id = req.params.id;
const query = {_id: ObjectId(id) };
const meeting = await meetingCollection.findOne(query);
res.send(meeting);
});
}
finally {
}
}
run().catch(console.dir);
app.get("/", (req, res) => {
res.send("starting server");
});
app.listen(port, () => {
console.log("CURD running", port);
});
Hi i am newbie about this stuff please help me whenever I try to authenticate i am getting this error
https://i.stack.imgur.com/VqQRY.png
my code is here :
index
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
const dotenv = require('dotenv')
const authRoute = require('./routes/Auth')
const userRoute = require('./routes/User')
const examRoute = require('./routes/Exam')
const examQuestionsRoute = require('./routes/ExamQuestions')
const userExamsRoute = require('./routes/UserExams')
dotenv.config();
const app = express()
app.use(cors())
app.use(express.json())
mongoose.connect(process.env.DATABASE_ACCESS, () => console.log("db connected
succes"))
app.use("/app/auth", authRoute);
app.use("/app/exam", examRoute);
app.use("/app/examquestions", examQuestionsRoute);
app.use("/app/userexams", userExamsRoute);
app.listen(5000, () => {
console.log('Server started on 5000')
})
Auth router
const router = require("express").Router();
const User = require("../models/User");
const CryptoJS = require("crypto-js");
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
if (!user) {
errors.email = "Wrong credentials!";
res.status(404).json({ errors });
return;
}
const hashedPassword = CryptoJS.AES.decrypt(
user.password,
process.env.PASS_SEC
);
const OriginalPassword = hashedPassword.toString(CryptoJS.enc.Utf8);
OriginalPassword !== req.body.password &&
res.status(401).json("Wrong credentials!");
const { password, ...others } = user._doc;
res.status(200).json({...others});
} catch (err) {
res.status(500).json(err);
}
});
module.exports = router;
I do not know if it is necessary since code 500 is server side issue but the "client" code is:
import {useState } from 'react'
import { useNavigate } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { login } from "../redux/apiCalls";
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const dispatch = useDispatch();
const navigate = useNavigate()
const handleLogin = (e) => {
e.preventDefault();
login(dispatch, { email, password });
};
return ()}
redux api calls
import { publicRequest } from "../requestMethods";
export const login = async (dispatch, user) => {
dispatch(loginStart());
try {
const res = await publicRequest.post("/auth/login", user);
dispatch(loginSuccess(res.data));
} catch (err) {
dispatch(loginFailure());
}
};
requestmethod.js is
export const publicRequest = axios.create({baseURL: http://localhost:5000/app/,});
i am waiting for good news guys thanks for the attention!
my terminals :
https://i.stack.imgur.com/SnJFG.png
i guess i found the error :
my error log
i have been working on this error for 3 days, i am open to any advice
I think your issue is due to the fact that you're sending the request two times in your code :
OriginalPassword !== req.body.password &&
res.status(401).json("Wrong credentials!");
const { password, ...others } = user._doc;
res.status(200).json({...others});
Here you have res.status(401).json(...) and res.status(200).json(...) which might be executed one after the other. When that happens you're trying to rewrite on a response that has already been sent with the json() method, which eventually throws the error you're having
I'm trying to implement JWT authentication, and I can't figure out why in Postman protected-route is available, while in my browser protected-route is Unauthorized.
I'm a beginner and its first time implementing jwt authentication in my project following this tutorial https://www.youtube.com/playlist?list=PLYQSCk-qyTW2ewJ05f_GKHtTIzjynDgjK
Problem
/login and /register work fine and I can see from the log they issue a JWT token in the req.headers
like 'Authorization':'Bearer <token>', however when I try to access GET /protected-route in my browser, it returns Unauthorized, and I can see no logging from JWTStrategy.
I think req.headers.Authorization is not set to all HTTP requests in the app, but only to POST /login, /register routes So my questions are:
Is this req.headers["Authorization"] = 'Bearer <toekn>'; correct way to set req headers to all GET and POST request in the app?
Does the jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken() checks for Authorization property in req.headers or res.headers?
I have provided the relevant code snippets please have a look!
Code:
app.js
//...
require('./config/database'); // require the db
// ...
const passport = require('passport');
const strategy = require('./config/passport').strategy;
// ...
app.use(passport.initialize());
passport.use(strategy);
// ...
module.exports = app
router/index.js
const router = express.Router();
//...
const User = require('../config/database').User;
const passport = require('passport');
const utils = require('../lib/utils');
// register route
router.post('/register', function(req, res, next){
const saltHash = utils.genPassword(req.body.password);
console.log("req.body.password is: " + req.body.password)
const salt = saltHash.salt;
const hash = saltHash.hash;
const newUser = new User({
username: req.body.username,
hash: hash,
salt: salt
})
newUser.save()
.then((user) => {
const jwt = utils.issueJWT(user);
if (jwt){
req.headers["Authorization"] = jwt.token;
}
res.redirect('/login')
})
.catch(err => next(err))
});
// login route
router.post('/login', function(req, res, next){
User.findOne({username: req.body.username})
.then((user) => {
if(!user) {
res.status(401).json({success: false, msg: "Could not find user "})
}
// validate the user
const isValid = utils.validPassword(req.body.password, user.hash, user.salt)
if(isValid) {
// issue a JWT
const jwt = utils.issueJWT(user);
if (jwt){
req.headers["Authorization"] = jwt.token;
}
res.redirect("/")
} else {
res.status(401).json({success: false, msg: "you entered the wrong password"})
}
})
.catch(err => next(err))
});
// GET protected route
router.get("/protectd-route", passport.authenticate('jwt', {session: false}), async (req, res, next) => {
res.render("user/getuser.pug")
next()
})
passport.js
const User = require('../config/database').User;
// ...
const Strategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
/// PUB_KEY
const pathToKey = path.join(__dirname, '..', 'id_rsa_pub.pem');
const PUB_KEY = fs.readFileSync(pathToKey, 'utf8');
// options
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: PUB_KEY,
algorithms: ['RS256']
};
// strategy
const strategy = new Strategy(options, (payload, done) => {
User.findOne({_id: payload.sub})
.then((user) => {
if(user) {
return done(null, user)
} else {
return done(null, false)
}
})
.catch((err) => done(err, null))
});
module.exports.strategy = strategy;
utils.js
genPassword() - Creating a salt and hash out of it to store in db
validPassword() - re-hashing user salt and hash to verify
issueJWT() - signing user with jsonwebtoken
const crypto = require('crypto');
const jsonwebtoken = require('jsonwebtoken');
const User = require('../config/database').User;
//...
const pathToKey = path.join(__dirname, '..', 'id_rsa_priv.pem');
const PRIV_KEY = fs.readFileSync(pathToKey, 'utf8');
// validate in /login
function validPassword(password, hash, salt) {
var hashVerify = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex');
return hash === hashVerify;
}
// generate in /register
function genPassword(password) {
var salt = crypto.randomBytes(32).toString('hex');
var genHash = crypto.pbkdf2Sync(password, salt, 10000, 64, 'sha512').toString('hex');
return {
salt: salt,
hash: genHash
};
}
// sign
function issueJWT(user) {
const _id = user._id;
const expiresIn = '86400';
const payload = {
sub: _id,
iat: Date.now()
};
const signedToken = jsonwebtoken.sign(payload, PRIV_KEY, { expiresIn: expiresIn, algorithm: 'RS256' });
return {
token: "Bearer " + signedToken,
expires: expiresIn
}
}
module.exports.validPassword = validPassword;
module.exports.genPassword = genPassword;
module.exports.issueJWT = issueJWT;
Postman
In Postman, the protected route is showing successfully, with Headers set as above.
The browser network is showing this, there is no Authorization property both in response and request headers
Clearly, I'm missing something, but I can't figure it out. Any help is appreciated
here is also my db
database.js
const uri = process.env.MONGO_URI
const connection = mongoose.connection;
mongoose.connect(uri, {
useUnifiedTopology: true,
serverSelectionTimeoutMS: 5000
})
connection.on('error', console.error.bind(console, "connection error"))
connection.once('open', () => {
console.log('MongoDB database connection has been established successfully')
})
const userSchema = new mongoose.Schema({
username: String,
hash: String,
salt: String
});
const User = mongoose.model('User', userSchema )
module.exports.User = User;
I'm building login system for my ChatApp and got stuck on JWT malformed when trying to create a new chatroom. When I login I get token and I try to send request from Postman to create chatroom, I put Token as bearer and in body I set name as my chatroom which is ok to put. Code:
auth.js:
const jwt = require('jwt-then')
module.exports = async (req, res, next) => {
try {
if (!req.headers.authorization) throw 'Forbidden!'
const token = req.headers.authorization.split('')[1]
const payload = await jwt.verify(token, process.env.SECRET)
req.payload = payload
next()
} catch (err){
res.status(401).json({
message: err.message
})
}
}
routes/chatroom.js:
const { catchErrors } = require('../handlers/errorHandlers.js')
const chatroomController = require('../controllers/userControllers.js')
const auth = require('../middlewares/auth')
router.post('/', auth, catchErrors(chatroomController.createChatroom))
module.exports = router
chatroomController:
const Chatroom = mongoose.model('Chatroom')
exports.createChatroom = async (req, res) => {
const {name} = req.body
const nameRegex = /^[A-Za-z\s]+$/
if (!nameRegex.test(name)) throw 'Chatroom name can only contain alphabets.'
const chatroomExists = await Chatroom.findOne({name})
if (chatroomExists) throw 'Chatroom already exists.'
const chatroom = new Chatroom({
name,
})
await chatroom.save()
res.json({
message: 'Chatroom created!',
})
}
Please help me