I have a route which posts in /verify/:token, where :token is a jwt, but in my view the form sends a post request to /verify/:token and then in my route logic I get a invalid jwt because :token is being send, how can I fix this?
<form action="/verify/:token" method="POST">
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input id="passcode" type="text" class="form-control" name="passcode" placeholder="Pass Code" required>
</div>
<button type="submit" class="btn btn-primary" style="display: inline-block;">Verify</button>
</form>
Pass token to your form page router
router.get("/", function (req, res, next) {
jwt.sign({_id: user._id}, jwtSecret, { expiresIn: '5m' }).then((token) => {
res.render("postForm", {
token: token
});
});
});
now you can use token in hidden input field assuming you are using ejs in client
<form action="/verify" method="POST">
<div class="input-group form-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input id="token" type="hidden" class="form-control" name="token" value="<%= token %> ">
<input id="passcode" type="text" class="form-control" name="passcode" placeholder="Pass Code" required>
</div>
<button type="submit" class="btn btn-primary" style="display: inline-block;">Verify</button>
</form>
Assuming you have jQuery in the client side, you have to prevent the default action of form when it is submitted. Then you have to send the ajax request by taking the value of the input field
$('form').submit(function(e){
//prevent default
e.preventDefault();
let token = $('#passcode').val();
let url = "/verify/" + token;
$.post( url, function( data ) {
// Do something once the ajax call succeeds
}).fail(function() {
alert( "error" );
});
});
Related
I am getting the CSRF forbidden error. However CSRF is working fine in the rest of the application like post route of logout, signUp, Signin deleteing anything et c..
But when I perform the post action in only one route `/addProduct" I am getting the error Note that I am generating my CSRF token before routes declaration.
I am attaching the main file code and the front end code of addProduct.
Here is my main file code where I am generating token and including it in all routes
app.use(csrfProtection);
app.use(flash());
// USed to include token and isLoggedIn information to render in every page
app.use((req, res, next) => {
res.locals.isLoggedIn = req.session.isLoggedIn;
res.locals.csrfToken = req.csrfToken();
res.locals.user= req.session.user;
next();
});
// app.use((req, res, next) => {
// // throw new Error('Sync Dummy');
// if (!req.session.user) {
// return next();
// }});
app.use(multer({ storage: fileStorage,fileFilter:fileFilter }).single('image'));
app.use(shopRoute);
app.use(authRoute);
app.use('/admin',adminRoute);
app.use(errorController.get404);
This is the front end code for ADD_Product.ejs. Here I am including hidden input as well... to get CSRF value back to check it...
<form action="<%=path%>" enctype="multipart/form-data" method="POST">
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" name="title" value="<%=product.title%>" >
</div>
<div class="form-group">
<label for="price">Price</label>
<input type="text" class="form-control" id="price" name="price" value="<%=product.price%>">
</div>
<div class="form-group">
<input type="file" class="form-control-file" id="exampleFormControlFile1" name="image" value="<%=product.imageUrl%>">
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">Description</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3" name="description" value="<%=product.description%>"></textarea>
</div>
<% if (path=="/admin/edit") { %>
<input type="hidden" name="productId" value="<%=product._id%>">
<% } %>
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit" class="btn btn-primary btn-lg center">+ </button>
</form>
i am getting the CSRF forbidden error .
However csrf is working fine in the rest of the application like post route of logout,signUp,Signin deleteing anything e.t.c/.
But when i perform the post action in only one route "/addProduct"
i got the error
Note that i am generating my CSRF token before routes declaration.
I am attaching the main file code and the front end code of addProduct.
here is my main file code where i am generating token and including it in all routes
app.use(csrfProtection);
app.use(flash());
// USed to include token and isLoggedIn information to render in every page
app.use((req, res, next) => {
res.locals.isLoggedIn = req.session.isLoggedIn;
res.locals.csrfToken = req.csrfToken();
res.locals.user= req.session.user;
next();
});
// app.use((req, res, next) => {
// // throw new Error('Sync Dummy');
// if (!req.session.user) {
// return next();
// }});
app.use(multer({ storage: fileStorage,fileFilter:fileFilter }).single('image'));
app.use(shopRoute);
app.use(authRoute);
app.use('/admin',adminRoute);
app.use(errorController.get404);
This is the front end code for ADD_Product.ejs
here i am including hidden input as well...
to get csrf value back to check it...
<form action="<%=path%>" enctype="multipart/form-data" method="POST">
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" name="title" value="<%=product.title%>" >
</div>
<div class="form-group">
<label for="price">Price</label>
<input type="text" class="form-control" id="price" name="price" value="<%=product.price%>">
</div>
<div class="form-group">
<input type="file" class="form-control-file" id="exampleFormControlFile1" name="image" value="<%=product.imageUrl%>">
</div>
<div class="form-group">
<label for="exampleFormControlTextarea1">Description</label>
<textarea class="form-control" id="exampleFormControlTextarea1" rows="3" name="description" value="<%=product.description%>"></textarea>
</div>
<% if (path=="/admin/edit") { %>
<input type="hidden" name="productId" value="<%=product._id%>">
<% } %>
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit" class="btn btn-primary btn-lg center">+ </button>
I am setting up a simple form submission, when I submit the form the url becomes undefined
This is the view: http://localhost:3000/dashboard/tours/categories
router.get('/tours/categories', function (req, res) {
res.render('agents/tourcategories', {
page_link: 'wishlist'
});
});
This is the form:
<form method="POST" action="/dashboard/tours/categories" >
<div class="box_general padding_bottom">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label>Category Name</label>
<input type="text" name="categoryname" class="form-control" placeholder="e.g Hiking">
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary pull-left" type="button" data-
dismiss="modal">Cancel</button>
<button id="" type="submit" class="btn btn-primary" >Save</a>
</div>
</form>
when I submit the form tne url changes to: `
http://localhost:3000/dashboard/tours/undefined
router.post('/tours/categories',function (req, res) {
console.log("We are here");
const category = new CategoriesDB({
categoryname: req.body.categoryname,
addedby: res.locals.useremail
});
// Save a Customer in the MongoDB
CategoriesDB.save(function (err) {
if(err){
console.log(err);
return;
}else{
res.redirect('/tours/categories');
}
})
});
I realy dont know where the undefined came from, I have checked everything seems to be okay. It keeps popping up in the url everythime i submit the form
`
From the snippets of the code you have posted, It might be because u have not used the middleware
router.all("/dashboard*");
But if u have used that and the GET request is working but not the POST then u will need to post more snippets of your code, mainly the middleware you defined to handle the routes
I am just stuck in a problem and also don't know whether the question is correct or not.
I am working on a node express js, using ejs templating engine.
I have created certain endpoints (say login(POST) endpoint) which are generic endpoints.
Now I want to create a new application which uses should use these endpoints and render the view according to the result of these endpoints.
Lets say I have a generic endpoint for login
router.post('/user/login', function (req, res) {
var userLoginId = req.body.username;
var currentPassword = req.body.password;
UserLogin.findOne({userLoginId: userLoginId, currentPassword: currentPassword}, function (err, usr) {
if (err) {
console.log('Error in User login');
console.log(err);
res.status(500).type('application/problem+json').send();
} else {
if (!usr) {
console.log('Please enter valid username and password');
res.status(404).type('application/problem+json').send();
} else {
res.type('application/json').status(200).send(usr);
}
}
});
});
And I am using this login.ejs file
<div class="container panel panel-primary">
<h2 class="h2 text-center">Login</h2>
<form class="form-horizontal" name="loginForm" method="post" action="/user/login">
<div class="form-group">
<label for="username" class="col-sm-offset-2 col-sm-2 control-label">UserName</label>
<div class="col-sm-4">
<input type="text" name="username" class="form-control" id="username" placeholder="username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-offset-2 col-sm-2 control-label">Password</label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control" id="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-4">
<button type="submit" class="btn btn-primary btn-">Sign in</button>
</div>
</div>
</form>
</div>
Now I want to use this code and want to login to the system.
If the user login is successful I want to redirect to dashboard page else same login page.
On executing this code the api returns me the JSON response and from this response how can I decide to whether to redirect on dashboard page or login page.
Please help if more input is needed please put a comment.
I would instead of doing a form request to login, do a AJAX request to login and then use something like jQuery to do the AJAX request and response. Alternatively you could do something like the following.
router.get('/login', function(req, res){
res.render('login', {});
})
router.post('/login', function (req, res) {
var userLoginId = req.body.username;
var currentPassword = req.body.password;
UserLogin.findOne({userLoginId: userLoginId, currentPassword: currentPassword}, function (err, usr) {
if (err) {
console.log('Error in User login');
console.log(err);
// res.status(500).type('application/problem+json').send();
res.status(500).render('login', { error : 'Error finding password'})
} else {
if (!usr) {
console.log('Please enter valid username and password');
// res.status(404).type('application/problem+json').send();
res.status(404).render('login', { error : 'Please enter valid username and password'})
} else {
res.redirect('/dashboard');
}
}
});
});
For the login.ejs file i would conditionally render the error.
<!DOCTYPE html>
<html>
<body>
<div class="container panel panel-primary">
<h2 class="h2 text-center">Login</h2>
<%if (locals.error) { %>
<%= error %>
<% } %>
<form class="form-horizontal" name="loginForm" method="post" action="/user/login">
<div class="form-group">
<label for="username" class="col-sm-offset-2 col-sm-2 control-label">UserName</label>
<div class="col-sm-4">
<input type="text" name="username" class="form-control" id="username" placeholder="username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-offset-2 col-sm-2 control-label">Password</label>
<div class="col-sm-4">
<input type="password" name="password" class="form-control" id="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-4">
<button type="submit" class="btn btn-primary btn-">Sign in</button>
</div>
</div>
</form>
</div>
</body>
</html>
I have a Login end point that respond me a json.
I'm using vue-router to do a POST and then Store a token in localStorage, but after the POST, the json shows on the screen:
{"success":false,"message":"Login ou senha inválidos!"}
It should return on the page login, with the message
This is the code:
var vmLogin = new Vue({
el: '#login',
data: {
email: '',
msg: '',
password: ''
},
beforeCreate: function () {
if(localStorage.getItem("timeTaskToken") !== null) {
window.location.href = '/'
}
},
methods: {
getLogin: function (e) {
this.$http.post('/login', {email: this.email, password: this.password}).then((response) => {
alert('teste!');
if(response.body.success === true) {
localStorage.setItem("timeTaskToken", response.body.token);
window.location.href = '/'
} else {
this.msg = response.body.message
}
}, (response) => {
// error callback
});
e.preventDefault();
}
}
});
login page
<form id="login" class="form-horizontal" method="post">
<h3>{{ msg }}</h3>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" v-model="email" class="form-control" name="email" placeholder="Email">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" v-model="password" class="form-control" name="password" placeholder="Password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default" #click="getLogin">Sign
in</button>
</div>
</div>
</form>
It's like nothing after .then works...
The returned JSON just appear in the screen.
I expect the problem is that the Sign In button is a submit button and you just want it to be a button button.
Change
<button type="submit" class="btn btn-default" #click="getLogin">Sign in</button>
To
<button type="button" class="btn btn-default" #click="getLogin">Sign in</button>
Note the type="button".
If you leave it as type submit then the form is is actually posted and code execution will stop. This also explains why you see a page that has just the JSON result; that is just the response from posting that form.
Alternatively, move e.preventDefault() to the top of the method.
You could also use #click.prevent="getLogin".
Just add a console.error in you error callback
}, (response) => {
console.error(response);
});
This is the first step because maybe you just enter here ..