Passportsjs logout - document says to use app.post but fails saying "Cannot GET /logout" - passport.js

The documentation for passport js https://www.passportjs.org/concepts/authentication/logout/ says..."It is a good idea to use POST or DELETE requests instead of GET requests for the logout endpoints, in order to prevent accidental or malicious logouts."
My code looks like this...
app.post('/logout', function(req, res){
req.logout(function(err) {
if (err) { return next(err); }
res.redirect('/');
});
});
The error I get when logging out is "Cannot GET /logout"
when I change the app.post to app.get it works no problem but that goes against what the documentation is suggesting. How do I get app.post to work?

You have to move that "logout button or link" inside your .ejs and put it inside a form, so you would be able to post that logout request.
Something like this:
<form class="" action="/logout" method="post">
<button class="" type="submit" name="button">Logout</button>
</form>
Share the code where you put the option for the user to logout and i will help with that too.

Related

Cannot delete an article in crud app (mongo, express, Nodejs)

Hi I am trying to make a crud app using Node Express and mongodb. But when I am trying to delete an article from my app it says it cannot delete. I checked all the code but cant find errors. Can anyone help please?
Delete route in my code is
router.delete('/:id', async (req, res)=>{
await Article.findByIdAndDelete(req.params.id)
res.redirect('/')
})
Link to delete an article is
<form action="/articles/<%=article.id%>?_method=DELETE" method="POST" class="d-inline">
<button type="submit" class="btn btn-danger">DELETE</button>
</form>
This is my server.js file
Write your app.use(methodOverride("_method")); middleware before routing app.use('/articles', articleRouter)

How to get dynamic parameter from html form in ajax

I have system for liking/unliking posts and I don't want page refresh to occur when user likes post. I want to use ajax to prevent that but don't know how to fetch
<form action="/posts/like/{{post.id}}" method="POST" id="like-form">
<button type="submit" id="like-button">Like</button>
</form>
How to fetch this {{post.id}} in ajax, I've tried using form.action but that returns whole url i just want id of certain post
You're not clear what are you using for the back-end like API built with Node or you're using templating engine with Node, but you can try this on front-end to achieve it.
document.querySelector('#like-form').addEventListener('submit', function(e) {
e.preventDefault(); // this prevents page refresh
fetch(`/posts/like/${post.id}`, { method: 'POST' });
});

How to "catch" a form's post request status?

I am using Node.js(with express) to make a website and I'm pretty new at it. I am currently stuck on how to "catch"(not sure the proper term) a POST request response on the client side. I have a page that has a form that the user fills out. Once the user hit the submit button the server-side gets the information and process it. Then once done it sends a status code. What I want to do on the client side is "catch" that status code, depending on the code, if its good then redirect to the next page else pop up an alert to the user that something is wrong with their input(or something along those lines). If someone can show me the most simplest way of doing it, as I am still learning, I would appreciate it.
When I hit submit it changes my browser window blank with a text: 'OK'
index.html
<!DOCTYPE html>
<html>
<head><title>Index</title></head>
<body>
<form action="/create" method="POST">
<input type="text" name="input1" value="Message"></br>
<input type="number" name="input2" value="0"></br>
<input type="submit" value="Submit">
</form>
<script src="app.js"></script>
</body>
</html>
app.js
//where I want to "catch" my post request response
index.js
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(express.static(__dirname+'/views'))
app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.post('/create', function(req, res){
//abstract data and send to db
if(okay)
res.sendStatus(200)
else
res.sendStatus(400)
})
When I hit submit it changes my browser window blank with a text: 'OK'...why can't I use a HTML form submission?
That's because if it is a plain HTML form submission, the browser will send the HTTP request, get response from server, and display that response content as a new web page (and replace the old one).
Why I have to use an Ajax request?
To get resonse from server without refresh the page, you need to send an Ajax request. That is, send the HTTP request via JavaScript, rather than via HTML element. In this way, the response can be processed by JavaScript code ("if its good then redirect to the next page else pop up an alert").
Example Ajax code is listed as below (using jQuery):
$.post('/create', {
input1: 'Message',
input2: 0
}).done(function(){
// redirect to the next page.
}).fail(function(){
// pop up an alert
});

User logout: Redirect GET to POST (Node/Express)

I am using Stormpath for Expressjs (without Passport at the moment) to handle my user registration. I am very concerned about what is the proper way to logout an user.
Before, I always did it through the GET method, however Stormpath explicitly requires a POST call to the /logout page.
I display a user menu only when the user is logged in through Stormpath, this is the super-simple middleware that I have in my router.js in Express:
router.use(stormpath.getUser, function (req, res, next) {
if (req.user) {
req.session.useremail = req.user.email;
}
next();
});
Now, of course in this menu there is the Logout entry. I want my user to click this link to Logout, however I know that when anchor links like Logout are used, a GET request is sent, not a POST.
I have been looking for countless number of ways to redirect a GET request to a POST, but I feel that this is absolutely the wrong way. Also I feel it would make no sense to use a form inside a menu like:
<ul>
<li>User Profile</li>
<li>User Settings</li>
<form action="/logout" method="/post">
<input type="submit">
</form>
</ul>
So the question is: what is the best way to simply logout an user via POST?
I don't think there is anything particularity bad about having the form in the menu but if you really want to have a get request you would probably need to do something like so:
var request = require('request')
app.get('/logout', function(req, res) {
// Send logout POST request to stormpath REST api
request.post({
url: 'https://stormpath/logout/url',
form: {
key: 'value'
}
},
function(err, httpResponse, body) {
// Check if there was an error logging the user-out
if (err) return res.send('Error logging out')
// If no error, user is logged out so redirect them or something
res.redirect('/')
})
})
So your express app accepts the GET request and then makes the POST request to Stormpath on the user's behalf to log the user out.
If you do move on to using the Stormpath passport stratergy I think you can simply call req.logout().

Express JS redirect to default page instead of "Cannot GET"

I am using express JS and I have a set of routes that I have defined as follows
require('./moduleA/routes')(app);
require('./moduleB/routes')(app);
and so on. If I try to access any of the routes that I have not defined in the above routes, say
http://localhost:3001/test
it says
Cannot GET /test/
But instead of this I want to redirect to my app's index page. I want this redirection to happen to all of the undefined routes. How can I achieve this?
Try to add the following route as the last route:
app.use(function(req, res) {
res.redirect('/');
});
Edit:
After a little researching I concluded that it's better to use app.get instead of app.use:
app.get('*', function(req, res) {
res.redirect('/');
});
because app.use handles all HTTP methods (GET, POST, etc.), and you probably don't want to make undefined POST requests redirect to index page.
JUst try to put one get handler with * after all your get handlers like bellow.
app.get('/', routes.getHomePage);//When `/` get the home page
app.get('/login',routes.getLoginPage); //When `/login` get the login page
app.get('*',routes.getHomePage); // when any other of these both then also homepage.
But make sure * should be after all, otherwise those will not work which are after * handler.
HTML file would be :
<form class="" action="/fail" method="post">
<button type="submit" name="button">Redirect to Homepage!</button>
</form>
Your Node.js code would be:
app.post("/fail", (req, res)=>{
res.redirect("/");
});

Resources