Node.js - How to send sessionID to GET method in Express via request package? [duplicate] - javascript

I'm trying to use NodeJS to scrape a website that requires a login by POST.
Then once I'm logged in I can access a separate webpage by GET.
The first problem right now is logging in. I've tried to use request to POST the login information, but the response I get does not appear to be logged in.
exports.getstats = function (req, res) {
request.post({url : requesturl, form: lform}, function(err, response, body) {
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(body);
res.end();
});
};
Here I'm just forwarding the page I get back, but the page I get back still shows the login form, and if I try to access another page it says I'm not logged in.
I think I need to maintain the client side session and cookie data, but I can find no resources to help me understand how to do that.
As a followup I ended up using zombiejs to get the functionality I needed

You need to make a cookie jar and use the same jar for all related requests.
var cookieJar = request.jar();
request.post({url : requesturl, jar: cookieJar, form: lform}, ...
That should in theory allow you to scrape pages with GET as a logged-in user, but only once you get the actual login code working. Based on your description of the response to your login POST, that may not be actually working correctly yet, so the cookie jar won't help until you fix the problems in your login code first.

The request.jar(); didn't work for me. So I am using the headers response to make another request like this:
request.post({
url: 'https://exampleurl.com/login',
form: {"login":"xxxx", "password":"xxxx"}
}, function(error, response, body){
request.get({
url:"https://exampleurl.com/logged",
header: response.headers
},function(error, response, body){
// The full html of the authenticated page
console.log(body);
});
});
Actualy this way is working fine. =D

Related

How to redirect user to a page that requires an access token without exposing token in a URL query

I am trying to implement a way of only allowing authorized admins to access pages with sensitive information within my Web App/API. I am currently using Node.JS with Express to handle routing. Views are generated with Jade/Pug View Engine. CORS requests are handled using the request framework on github. (https://github.com/request/request)
Currently, clients are stored within a MongoDB collection. When they enter their login information, their passwords are compared to a Hash stored in the DB. If everything checks out, a JWT is generated for the user and saved in the client DB and also stored within the browser in localStorage.token.
The user is then redirected to a splash page which has an authentication function as middleware. The authentication function accepts the token in three forms:
var token = req.body.token || req.query.token || req.headers['x-access-token'];
I feel like the way redirection is handled is a bit hacky. I am using window.location = route?token=[token]
Token is handed over to the authentication function within req.query.token, but this is exposed in URL. Here is my login function:
function submitLogIn() {
var credentials = {
email: logInForm.userEmail.value,
password: logInForm.pwField.value
}
fetch('/login', {
headers:{
'Content-Type': 'application/json'
},
method: 'POST',
body: JSON.stringify(credentials)
}).then(function(res){
if(!res.ok) alert("Error!")
else return res.json().then(function(result){
localStorage.token = result.token;
//This is how I'm doing redirecting:
window.location = '/selection?token=' + result.token;
}).catch(function(err){
console.log(err);
throw err;
});
});
Just for reference, this is the front-end route that it's going to at port 3001 which swings it over to 3000 as a reverse-proxy request:
router.post('/login', function(req, res, next) {
request.post({
url: 'http://localhost:3000/authorize',
form: req.body
}).pipe(res)
});
My main question is this: How can I handle redirection at the front-end within fetch calls?
My splash screen is basically a menu of buttons which will take the user to different pages. The pages will contain information that only admins should see. Let's say I want to click on this navigation button. It goes to a /GET route that requires the token to be sent for an OK status. if no token, it returns a 403.
router.get('/main', authorize.adminRequired, function(req, res, next) {
request.get({
url: 'http://localhost:3000/menus'
}, function(response, sensitiveItems) {
return res.render('index', {menu: JSON.parse(sensitiveItems)});
});
});
That authorize.adminRequired function needs a token in the form of a query, x-access-token, or req.body. Can't send a body in a GET request. Don't want to expose in URL, so:
Here's what I tried. I have this redirect fetch call as an onclick function.
function redirectToSensitivePage() {
fetch('/main', {
headers: {
'x-access-token': localStorage.token
},
method: 'GET'
});
};
This gives me a 200, OK. But I don't load the page. The res.render(index) in the route does not fire. The response does contain all of the data, but I am not redirected to the visual representation.
I could do the same hacky redirect using window.location=/main?token=[token], but I don't want to expose the URL token. I could load everything I need into the webpage upon login instead of having separate pages, have those divs hidden out of sight until keypress to make that div the main visible div, but I would rather figure out how to do it via redirect.
I'm still getting my bearings with using Node, so please let me know if I have made any stupid glaring oversights.
Edit: Should I simply try
var token = localStorage.token || req.body.token || req.query.token || req.headers['x-access-token'];
Is there any disadvantage to simply scraping from the localStorage automatically with each request?

Get headers on page load from node-express app? [closed]

I am building an app with node and express and set it up such that when the page loads, some headers are sent to the client. How do I extract that information on the client side? I am using JS/jQuery on the client side. Here's the code in question-
app.get('/', (req, res) => {
models.game_session.build({
sid: req.sessionID
}).save().then((data) => {
let options = {
"root": __dirname,
headers: {
"x-sid": data.id
}
}
res.sendFile('/index.html', options, (err) => {
if (err) {
res.send(err)
}
});
}).catch((e) => {
res.send(`There was an error`);
});
});
I am saving the session ID in the database then sending the index file to the client. As you see in the options object, I want to include the session ID in the header to be sent with the index file. How can I retrieve that info on the client side? I'm not sure if I am going about this in the right way- appreciate any help!
EDIT: sorry, didn't read closely enough. It's not actually possible, and here's why:
https://stackoverflow.com/a/220233/4045156
What you are doing is fine, but you could also (once the page loads on the client side) make another request to the server and then respond with a simple JSON object. It's totally up to you though. This of course means another request, but it doesn't seem possible to avoid another request anyways.
Unfortunately there isn't an API to get the headers from you current page, you need to generate another request from you JS/Jquery to get the headers:
How to do that:
How to get read data from response header in jquery/javascript
Accessing the web page's HTTP Headers in JavaScript

No authorization token was found when res.redirect

I have two applications, both on Nodejs. One front-end and other back-end.
My back-end app is protected with token access using express-jwt and jsonwebtoken middlewares.
My problem is: I am making a request from front-end to back-end passing the token on header, back-end accepts the request and respond properly. Then in the front-end I redirect the response to an specific page (res.redirect('/')), in that moment I get the error UnauthorizedError: No authorization token was found
My front-end request:
/* Authentication */
router.post('/', function(req, res, next) {
// request login service
request({
uri: env.getUrl() + "/user",
method: 'POST',
timeout: 10000,
headers: {
'Authorization': 'Bearer '.concat(global.token)
},
form: { login : req.body.login, pwd : req.body.pwd }
}, function(error, response, body){
if(error) {
logger.error(error);
res.render("error", {message: "Error getting user" });
}
else {
if(body){
req.session.usuario = JSON.parse(body);
res.redirect("/");
} else {
res.render("login", {message: "Login Failed" });
}
}
});
});
I don't know why this happen. Could you help me?
Thanks in advance.
A redirect (via res.redirect) issues a new HTTP request. This means that the Authorization header is empty. This results in the UnauthorizedError error.
To fix this, you have two options:
1. Pass the token in the URI
You can issue the redirect with the token passed in the URL in this way:
res.redirect("/?access_token=" + global.token);
2. Set the header before the redirect
You can set the 'Authorization' header before making the redirect request:
req.session.access_token = global.token;
Problem found.
Anytime the my front-end app makes a request to the back-end side (api) the user logged in front-end is validated against back-end and so the fron-end's session is updated as well. Which means that every request is actually two requests:
One as the real request the app is doing.
The request validating the user logged on front-end in order to be sure that user exists.
This update (second point) was made without providing a token.

Node.js Post Request - Keep Session Alive

Hi guys (Happy new year btw :) )!
I'm giving a try to Node.js and Express.js, and, i'm facing some difficulties with the processing of several requests.
Here's the problem : I need to retrieve data from an external website. To do so, I have to be logged in and I have a fake/zombie account available. What I am trying to do is to first send a POST request with my username and password, and then, sending a GET request to access a specific content. The problem is that, even if the POST request is successfully executed, when I'm doing the GET request, I am no longer logged in.
I was doing the same thing with the Gem Mechanize in Ruby but, it should probably do some implicit stuff that made the whole process work.
To make requests, I am using the request module (https://github.com/request/request). And, here is the code :
var zombie = require('request').defaults({
headers: { connection: "keep-alive" },
pool: {maxSockets: 1},
});
var connect = function(req, res, next){
zombie.post({
url: "target.com",
form: {
user: "zombie",
pass: "password"}
}, function(err, response, body){
req.connected = true;
next();
});
}
var information = function(req, res, next){
if(req.connected){
zombie.get({
url: "target.com",
qs: {
page: "targetPage",
search: req.params.search}
}, function(err, response, body){
res.send(body);
})
}
}
And, from a controller, I'm trying to connect, then to access information.
var router = require('express').Router();
var zombie = require('./../middleware/Zombie');
router.get('/search/:search', zombie.connect, zombie.information);
Most likely the server is sending back a Set-Cookie and it's getting ignored (the default behavior for the request module). To fix that, you need to npm install tough-cookie and then set up the jar config option. There are some examples that show various cookie jar usage scenarios.

How to maintain a request session in NodeJS

I'm trying to use NodeJS to scrape a website that requires a login by POST.
Then once I'm logged in I can access a separate webpage by GET.
The first problem right now is logging in. I've tried to use request to POST the login information, but the response I get does not appear to be logged in.
exports.getstats = function (req, res) {
request.post({url : requesturl, form: lform}, function(err, response, body) {
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(body);
res.end();
});
};
Here I'm just forwarding the page I get back, but the page I get back still shows the login form, and if I try to access another page it says I'm not logged in.
I think I need to maintain the client side session and cookie data, but I can find no resources to help me understand how to do that.
As a followup I ended up using zombiejs to get the functionality I needed
You need to make a cookie jar and use the same jar for all related requests.
var cookieJar = request.jar();
request.post({url : requesturl, jar: cookieJar, form: lform}, ...
That should in theory allow you to scrape pages with GET as a logged-in user, but only once you get the actual login code working. Based on your description of the response to your login POST, that may not be actually working correctly yet, so the cookie jar won't help until you fix the problems in your login code first.
The request.jar(); didn't work for me. So I am using the headers response to make another request like this:
request.post({
url: 'https://exampleurl.com/login',
form: {"login":"xxxx", "password":"xxxx"}
}, function(error, response, body){
request.get({
url:"https://exampleurl.com/logged",
header: response.headers
},function(error, response, body){
// The full html of the authenticated page
console.log(body);
});
});
Actualy this way is working fine. =D

Resources