How do you handle cookies with request-promise? - javascript

I'm having trouble scraping a website that needs authentication, and is using session cookies. The session requires a request with POST, and the authentication then approves. But when I want to GET the webpage that need authentication, it returns "Unauthorized". I guess I need a way to bring the session cookie with the GET-request, but I don't know how! My dependencies is request-promise(https://www.npmjs.com/package/request-promise).
The code looks like this:
var rp = require("request-promise");
var options = {
method: "POST",
uri: "http://website.com/login",
form: {
username: "user",
password: "pass",
},
headers: {},
simple: false
};
rp(options).then(function(response) {
console.log(response); // --> "Redirecting to login/AuthPage"
request("http://website.com/login/AuthPage", function(err, res, body) {
console.log(body); // --> "Unauthorized"
})
}).catch(function(e) {
console.log(e)
})
I'm guessing you have to put the request in a "Jar" (https://github.com/request/request#requestjar), to be able to reach the next request-URL, but how can I set the request-promise to create a cookie-jar?

Your problem is how to keep the session after authentication.
That means, after logging in by using username and password, the server will return a cookie with an identifier. Then you need to attach that cookie to all your feature requests.
It's simple with request-promise. Just keep tracking session by enabling jar option then use the same request object for all requests.
Let take a look
var request = require("request-promise").defaults({ jar: true });
var options = {
method: "POST",
uri: "http://website.com/login",
form: {
username: "user",
password: "pass",
},
headers: {},
simple: false
};
request(options).then(function(response) {
request("http://website.com/login/AuthPage", function(err, res, body) {
console.log(body);
})
}).catch(function(e) {
console.log(e)
})

Use the following object while making rest calls.
var request = require("request-promise").defaults({jar: true});
To add your own cookies
var tough = require('tough-cookie');
// Easy creation of the cookie - see tough-cookie docs for details
let cookie = new tough.Cookie({
key: "some_key",
value: "some_value",
domain: 'api.mydomain.com',
httpOnly: true,
maxAge: 31536000
});
// Put cookie in an jar which can be used across multiple requests
var cookiejar = rp.jar();
cookiejar.setCookie(cookie, 'https://api.mydomain.com');
// ...all requests to https://api.mydomain.com will include the cookie
var options = {
uri: 'https://api.mydomain.com/...',
jar: cookiejar // Tells rp to include cookies in jar that match uri
};
and then make the call. More details about request-promise:
https://www.npmjs.com/package/request-promise

Related

Using ably.io JWT with Angular

I'm trying to use ably.io with Angular and Azure Functions using the JWT way of authenticating since it's secure, but I'm having issues with configuring the angular side of it. The use case is for a live auction site to update bids in realtime. There isn't a specific angular tutorial for this so I'm trying to piece it together. Also this code
realtime.connection.once('connected', function () {
console.log('Client connected to Ably using JWT')
alert("Client successfully connected Ably using JWT auth")
});
never throws the alert so I don't think it's working right. I used to have it working where I wasn't using ably JWT, but had the API key on the client-side in a component like this
let api = "<api key>";
let options: Ably.Types.ClientOptions = { key: api };
let client = new Ably.Realtime(options); /* inferred type Ably.Realtime */
let channel = client.channels.get(
"auctions"
);
and I could subscribe to that channel and update auctions accordingly by their id inside ngOnInit()
channel.subscribe(message => {
const auction = this.posts.find(action => {
return action.id === message.data.auctionId;
});
if (auction) {
auction.currentBid = message.data.lastBid;
}
});
but I need to switch this logic for JWT and somehow feed that JWT token into different components as well.
Ably.io JWT tutorial reference
I put the following in my angular login service
login(email: string, password: string) {
const authData: AuthDataLogin = { email: email, password: password };
return this.http
.post<{
token: string;
expiresIn: number;
userId: string;
}>(environment.azure_function_url + "/POST-Login", authData)
.pipe(takeUntil(this.destroy)).subscribe(response => {
//JWT login token. Not Ably JWT Token
const token = response.token;
this.token = token;
if (token) {
console.log('Fetching JWT token from auth server')
var realtime = new Ably.Realtime({
authUrl: "http://localhost:7071/api/AblyAuth"
});
realtime.connection.once('connected', function () {
console.log('Client connected to Ably using JWT')
alert("Client successfully connected Ably using JWT auth")
});
...
}
With my azure function already configured, When I login, the browser console outputs
GET wss://realtime.ably.io/?access_token=<token was here>&format=json&heartbeats=true&v=1.1&lib=js-web-1.1.22
SO it returns my token, but
the alert never happens
I'm not sure how to grab that JWT token that's returned to the browser. I was thinking I could store it in localStorage to share between components and clear out localStorage when user logs out, but I need to be able to subscribe to response and assign the token to a variable, but I didn't see in ably javascript tutorial how to get variable assigned to JWT Token response since it's being called with this syntax.
I appreciate any help with this!
var realtime = new Ably.Realtime({
authUrl: "http://localhost:7071/api/AblyAuth"
});
My azure function looks like
const checkAuth = require('../middleware/check-auth');
var jwt = require("jsonwebtoken")
var appId = '<APP ID>'
var keyId = '<key ID>'
var keySecret = '<key secret>'
var ttlSeconds = 60
var jwtPayload =
{
'x-ably-capability': JSON.stringify({ '*': ['publish', 'subscribe'] })
}
var jwtOptions =
{
expiresIn: ttlSeconds,
keyid: `${appId}.${keyId}`
}
console.log("JwtPayload");
console.log(jwtPayload);
console.log("jwtOptions");
console.log(jwtOptions);
module.exports = function (context, req) {
console.log("INSIDE ABLY AUTH")
// checkAuth(context, req);
console.log('Sucessfully connected to the server auth endpoint')
jwt.sign(jwtPayload, keySecret, jwtOptions, function (err, tokenId) {
if (err) {
console.log("ERR")
console.log(err)
console.trace()
return
}
context.res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate')
context.res.setHeader('Content-Type', 'application/json')
console.log('Sending signed JWT token back to client')
console.log(tokenId)
context.res = {
status: 200,
body: JSON.stringify(tokenId),
headers: {
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Set-Cookie",
"Access-Control-Max-Age": "86400",
"Vary": "Accept-Encoding, Origin",
"Content-Type": "application/json"
}
};
context.done();
})
}
I'd recommend if you're wanting to intercept the JWT prior to passing it to Ably (so as to verify the contents, and also use the JWT for other components), you make use of authCallback instead of authUrl. You can use a function instead of a direct URL, within which you can call the endpoint, and do anything you like with the response, prior to passing the JWT back to the Ably constructor. I've made a JavaScript example of using the authCallback for normal Token Authentication, but the same principle applies.
As to why you're not seeing the alert, it looks like you're sending an invalid JWT for what Ably is expecting, and thus you're not successfully connecting to Ably. For example, you're specifying 'expiresIn' rather than 'exp'. For a token to be considered valid, it expected certain elements in a very specific structure, see the documentation. I'd recommend for this sort of situation where you're not certain what's breaking that you make use of verbose logging, which you can enable in the connection constructor as "log": 4.

Cannot read property 'session' of undefined - Manage Session Cookie Firebase Auth generated cookie

The problem that I am facing is that after setting a Firebase session cookie, I go to another endpoint that needs to be secure, but req cannot find the cookie.
I am following a Firebase tutorial called Manage Session Cookies that describes how to generate a cookie after a user has logged in using the Firebase signInWithEmailAndPassword function. The user idToken is then passed over to a POST request:
First, I am generating a token and sending it to an endpoint:
function signIn() {
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
document.getElementById('quickstart-sign-in').disabled = false;
}).then(user => {
// Get the user's ID token as it is needed to exchange for a session cookie.
return user.getIdToken().then(idToken => {
if (firebase.auth().currentUser) {
$.ajax({
method: 'POST',
url: '/login',
data: {'email':firebase.auth().currentUser.email,idToken},
success: function(data) {
//do other things...
}
});
}
});
})
}
The URL endpoint, which is getting the idToken from the prior POST request, creating a session cookie with createSessionCookie, then setting the cookie using res.cookie('session', sessionCookie, options):
exports.postLogin = (req, res, next) => {
// Get the ID token passed
const idToken = req.body.idToken.toString();
// Set session expiration to 14 days.
const expiresIn = 60 * 60 * 24 * 14 * 1000;
var exampleDB = admin.database().ref('exampleDB');
exampleDB.once('value', function(snapshot) {
//unrelated things happening...
//generate randomData...
}).then(function() {
admin.auth().createSessionCookie(idToken, {expiresIn})
.then((sessionCookie) => {
// Set cookie policy for session cookie.
const options = {maxAge: expiresIn, httpOnly: true, secure: true};
res.cookie('session', sessionCookie, options);
res.status(200).send(randomData).end();
}, error => {
res.status(401).send('UNAUTHORIZED REQUEST!');
});
});
};
The problem that I am facing starts here, when I go to another endpoint, /dashboard. The cookie that I had supposedly set cannot be found, and instead I get an error message stating TypeError: Cannot read property 'session' of undefined for my session cookie:
exports.dashboard = (req, res, next) => {
const sessionCookie = req.cookies.session || '';
// a bunch of other code around the session cookie that doesn't even get triggered because of the break in req.cookies.session
}
Am I retrieving the cookie incorrectly? Or have I not set the cookie properly? Or is the cookie somehow not being carried over to this new endpoint, /dashboard, from the page on which the POST to /login happens?
After logging the req to /dashboard I see that I have the following in there, but I don't know if it's from another session for something. If it is from Firebase, I don't know how to access it correctly:
sessionID: 'ublahxARQVljyGRblahPQrei',
session:
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
returnTo: '/dashboard',
flash: {},
_csrfSecret: 'r46blahE+kOzblah5==' },
I believe that you need to use the __session cookie.
When using Firebase Hosting together with Cloud Functions or Cloud
Run, cookies are generally stripped from incoming requests.
source
This has been encountered before in a different form: Firebase Functions : How to store simple cookies to remember an authenticated user

How to include credentials in node request?

im trying to get array edges from this url
`https://www.instagram.com/graphql/query/?query_id=17851374694183129&variables={"id":"500818047","first":10}
In the frontend, I can get this array with fetch and credentials: 'include'.
But I can't work with him because of CORS. So, I try to do this in app.js using node, but array is still hidden.
That's what I get:
{
edge_followed_by:
{
count: 18213,
page_info: { has_next_page: false, end_cursor: null },
edges: []
}
}
How to enable the parameter credentials in node request? Or, if I do something wrong, how to get this array?
var cors = require('cors');
app.use(cors());
var request = require("request");
const url = 'https://www.instagram.com/graphql/query/?query_id=17851374694183129&variables={"id":"500818047","first":10}';
request({
url: url,
json: true,
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body['data']['user'])
}
});
This is because when you hit the URL from frontend you may have already logged into Instagram so the User Access Token is present in your browser's cookies and hence you are able to access all the information in edges
Try the same thing after logging out of Instagram or try it with incognito mode and you would find that edges are empty because the browser no longer holds the User Access Token needed to check for permissions and provide you with the information.
To do it from a backend service follow the steps provided here,
https://developers.facebook.com/docs/instagram-api/getting-started
Hope this helps. :)
Have you taken a look at the request docs?
You have the following options to authenticate your request:
request.get('http://some.server.com/').auth('username', 'password', false);
// or
request.get('http://some.server.com/', {
'auth': {
'user': 'username',
'pass': 'password',
'sendImmediately': false
}
});
// or
request.get('http://some.server.com/').auth(null, null, true, 'bearerToken');
// or
request.get('http://some.server.com/', {
'auth': {
'bearer': 'bearerToken'
}
});

publishing Sails / Node.js to Kongregate

So, finally my MMORTS game built on Sails is going to Kongregate.
Had few obstacles, like connecting websockets, but solved now.
Probably the last obstacle is to keep authenticated session. I was using frameworks everywhere and i have no idea how does the authentication sessions work under the hood.
The main problem is probably the CSRF or CORS. I am using Sails v1.0.
So, i start with HTML, which I upload to kongregate. I'm taking the simplest possible example:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<script src="jquery.js"></script>
<script src='https://cdn1.kongregate.com/javascripts/kongregate_api.js'></script>
<script src="sails.io.js"
autoConnect="false"
environment="production"
headers='{ "x-csrf-token": "" }'
></script>
<script type="text/javascript">
io.sails.url = 'https://my-secret-game.com'; // or where you want
</script>
</head>
<script src="main.js"></script>
</html>
And this is the main.js , which I also upload to kongregate
kongregateAPI.loadAPI(function(){
window.kongregate = kongregateAPI.getAPI();
var username = kongregate.services.getUsername();
var id = kongregate.services.getUserId();
var token = kongregate.services.getGameAuthToken();
$.get("https://my-secret-game.com/csrfToken", function (data, jwres) {
var params = {
username: username,
id: id,
token: token,
_csrf: data._csrf
};
$.post("https://my-secret-game.com/kong", params, function(data, jwr, xhr){
// cant set the cookie - because of chrome. this doesnt work
document.cookie = document.cookie + ';authenticated=true;sails.sid=' + data.id;
$.get("https://my-secret-game.com/csrfToken", function (data, jwres) {
var msg = {
testing_authentication: true,
_csrf: data._csrf
};
$.post("https://my-secret-game.com/test", msg, function(data, status){
// getting the 403 Forbidden, CSRF mismatch. trying to access
// the play/test route, which is protected by sessionAUTH
console.log('data.response', data.response)
});
});
});
});
});
The problem is, that i am getting 403 Forbidden whenever I try to POST my Sails backend with sessionAUTH. I also cant set cookies - probably because of Chrome. What can I do? When i get CSRF token, on the next request my Sails app responds about CSRF mismatch. It becomes wrong.
And this is the controller on my Sails backend server
module.exports = {
kong: function (req, res, next) {
var url = 'https://api.kongregate.com/api/authenticate.json';
var kong_api_key = 'my-secred-api-key';
var params = req.allParams();
var request = require('request');
var req_form = {
"api_key": kong_api_key,
"user_id": params.id,
"game_auth_token": params.token
};
request({
url: url,
method: "POST",
json: true,
body: req_form,
timeout: 5000
}, function (err, response, body){
if(err) { console.log(err, 'ERR43'); return res.ok(); }
else {
if(!response.body.success) {
console.log('unsuccessful login from kongregate')
return res.ok();
}
// trying to use a existing user and authenticate to it
User.find({username: 'admin-user'}).exec(function(err, users) {
var user = users[0];
req.session.authenticated = true;
req.session.user = { id: user.id };
// trying to send session_id, so that i could hold it on kongregates cookies as `sid`
return res.send({ user: user, id: req.session.id });
});
}
});
},
Could somoene please help to fix authentication and CSRF of my app?
In case needs more info about my configs, this is the config/session.js
var prefixes = 'dev';
module.exports.session = {
secret: 'my-secret',
cookie: {
secure: false
},
adapter: 'redis',
host: 'localhost',
port: 6379,
ttl: 3000000,
db: 0,
prefix: prefixes + 'sess:',
};
config/policies.js
module.exports.policies = {
user: {
'new': 'flash',
'create': 'flash',
'edit': 'rightUser',
'update': 'rightUser',
'*': 'sessionAuth'
},
play: {
'*': 'sessionAuth'
}
};
api/policies/sessionAuth.js
module.exports = function(req, res, next) {
if (req.session.authenticated) {
return next();
} else {
var requireLoginErr = [
{ name: 'requireLogin', message: 'You must be signed in' }
];
req.session.flash = {
err: requireLoginErr
};
res.redirect('/');
return;
}
};
config/security.js
module.exports.security = {
csrf: true,
cors: {
allowRequestMethods: 'GET,PUT,POST,OPTIONS,HEAD',
allowRequestHeaders: 'content-type,Access-Token',
allowResponseHeaders: '*',
allRoutes: true,
allowOrigins: '*',
allowCredentials: false,
},
};
Okey, since i had no answers (obviously - the question was bad), answering with my solution which i have solved by my self - so the next time i can read my self. Not sure how good it is, but at least it works.
Sails CORS is taken form Express.js and allows to connect sockets to kongregate if i allow it inside configs.
But it does not allow to authenticate in a normal way, by sending sails.sid (authentication token) via cookies.
Chrome does not allow to set cookies with javascript (i dont have backend on Kongregate) to headers at all due to security. So, if i can't send cookies with headers, Sails can't authenticate the requests in a normal way. Even if i allow CORS to accept the 'cookie' header - it's not allowed by browsers to set cookie headers with javascript.
I can make some unique header like "authentication" and set the sails.sid there, extend some core functionality of Sails to take this new header instead of cookie header. But the problem - on Sails backed i was not able to get at all this sails.sid and send it to my external frontend.. Where it is created? How can i get sails.sid on Sails backend? Not sure - can't google it.
So, i just did authentication in a most simple way possible - on account login/register, i just create a session key by my self - with bcrypt hashing user_id+secret_token (taken from sails config secrets). and sending to the frontend { user_id: 'abcd', secret_token: 'a2dw412515...' }
I have made my policies in Sails to authenticate on every POST/GET request - take the request's session_id and user_id, and compare using bcrypt, does the session_id is the same as encrypted user_id+secret_token. I hope its secure enough.
So, it worked. I just had to disable CSRF. Maybe some day i will implement it again, I just have to write it in my way, not leave the Sails defaults.
The working code:
FRONTEND
// you upload this HTML file to kongregate
// also you upload additionally ZIP named "kongregate_uploaded_folder" with libraries like sails.io, jquery
<!DOCTYPE html>
<html>
<head>
<script src="kongregate_uploaded_folder/jquery.js"></script>
<script src='https://cdn1.kongregate.com/javascripts/kongregate_api.js'></script>
<script src="kongregate_uploaded_folder/sails.io.js"
autoConnect="false"
environment="production"
></script>
</head>
<body style="padding:0; margin:0; overflow:hidden;">
<div style="position:absolute; margin: 0px; padding: 0px;">
<canvas id="main_canvas" style="position:absolute;" width="640" height="480" >Best initial resolution to have in Kongregate</canvas>
</div>
<script>
// the first thing happends - you try to connect your frontend with Kongregate
kongregateAPI.loadAPI(function(){
window.kongregate = kongregateAPI.getAPI();
if(!kongregate.services.isGuest()) {
var params = {
username: kongregate.services.getUsername(),
id: kongregate.services.getUserId(),
token: kongregate.services.getGameAuthToken(),
};
// call your backend to create a new session and give you session_id
$.post("https://your_game_server.com/kong", params, function(data, jwr, xhr){
var kong_session_id = data.kong_session_id;
var kong_user_id = data.kong_user_id;
var user = data.user;
// connect your sockets with the server in this way
io.socket = io.sails.connect("https://your_game_server.com", { useCORSRouteToGetCookie: false, reconnection: true });
// subscribe to the global sockets channel. You have to make this route and code, but here is a example
io.socket.get('/subscribe', { kong_session_id: kong_session_id, kong_user_id: kong_user_id }, function(data, jwr){
if (jwr.statusCode == 200){
io.socket.on(data.room, function(event){
// on any server-side event, you will get this "event" message. At this part you decide what to do with this data
incoming_socket_event(event); // i wont write this function
});
// your game continues here:
$.get("https://your_game_server.com/player_data?kong_session_id=" + kong_session_id + "&kong_user_id=" + kong_user_id, params, function(data, jwr, xhr){
// you will get authenticated "current_user"
}
});
})
}
});
</script>
</html>
BACKEND
// SAILS BACKEND: home_controller.js
module.exports = {
kong: function (req, res, next) {
// player has already opened your game in kongregate.com and frontend requests this endpoint POST /kong { id: 84165456, token: 'as54..' }
// you need to create a new session for this player, or register this player. This is your own session creation, since default sails session wont work with external website frontend.
var req_params = {
url: "https://api.kongregate.com/api/authenticate.json", // default URL to validate kongregate user
method: "POST",
json: true,
body: {
api_key: 'gg000g00-c000-4c00-0000-c00000f2de8', // kongregate will provide this api-key for server-side connection (this one has some letters replaced)
user_id: 84165456, // when frontend requests POST /kong { id=84165456 } , this 84165456 is provided by kongregate in the frontend
game_auth_token: "as54a45asd45fs4aa54sf" // when frontend requests POST /kong { token = 'as54..' }, this is provided by kongregate in the frontend
},
timeout: 20000
}
// request kongregate that this is the real player and you will get a username
request(req_params, function (err, response, body){
var response_params = response.body; // response from kongregate API
// search for user with this kongregate_id inside your database, maybe he is already registered, and you need just to create a new session.
User.find({ kongregate_id: response_params.user_id }).exec(function(err, usr) {
var user = usr[0]
// if player already has an account inside your online game
if(user) {
// create new session for this user.
require('bcryptjs').hash("your_own_random_secret_key" + user.id, 10, function sessionCreated(err, kong_session_id) {
// send this info to frontend, that this player has been connected to kongregate
return res.send({
user: user,
kong_session_id: kong_session_id,
kong_user_id: user.id
});
});
//if this is new user, you need to register him
} else {
var allowedParams = {
username: response_params.username, // kongregate will give you this player username
email: 'you_have_no_email#kong.com', // kongregate does not provide email
password: 'no_password_from_kongregate',
kongregate_id: response_params.user_id // kongregate will give you this player id
};
User.create(allowedParams, function(err, new_user) {
// create new session for this user.
require('bcryptjs').hash("your_own_random_secret_key" + new_user.id, 10, function sessionCreated(err, kong_session_id) {
// send this info to frontend, that this player has been connected to kongregate
return res.send({
user: new_user,
kong_session_id: kong_session_id,
kong_user_id: new_user.id
});
});
});
}
});
});
},
};
ROUTES
// config/routes.js
module.exports.routes = {
'GET /player_data': 'PlayController.player_data',
'GET /subscribe': 'PlayController.subscribe',
'POST /kong': {
action: 'home/kong',
csrf: false // kongregate is a external website and you will get CORS error without this
},
};
SECURITY
// config/security.js
module.exports.security = {
csrf: false,
cors: {
allowOrigins: ['https://game292123.konggames.com'], // your game ID will be another, but in this style
allowRequestMethods: 'GET,POST',
allowRequestHeaders: 'Content-Type',
allowResponseHeaders: '',
allRoutes: true,
allowCredentials: false,
},
};
SOCKETS
// config/sockets.js
module.exports.sockets = {
grant3rdPartyCookie: true,
transports: ["websocket"],
beforeConnect: function(handshake, cb) { return cb(null, true); },
};
CONFIG POLICIES
// /config/policies.js
module.exports.policies = {
play: {'*': 'sessionAuth'},
};
API POLICIES
// /app/sessionAuth.js
module.exports = function(req, res, next) {
var params = req.allParams();
// your own session handling way to get the user from session token
require('bcryptjs').compare("your_own_random_secret_key" + params.kong_user_id, params.kong_session_id, function(err, valid) {
req.session.authenticated = true;
req.session.user_id = params.kong_user_id;
return next();
});
};
CONTROLLER
// /api/controllers/PlayController.js
module.exports = {
player_data: async function (req, res, next) {
var users = await User.find(req.session.user_id);
return res.send({ current_user: users[0] });
},
subscribe: async function (req, res, next) {
var users = await User.find(req.session.user_id);
var roomName = String(users[0].id);
sails.sockets.join(req.socket, roomName);
res.json({ room: roomName });
},
}

Javascript scraper logging in

I seem to be doing something wrong.
I have a student website that I want to scrape, but first I need to log in. Currently I have a python scraper that does it. The website logs in with a post request to a url containing a sid and PIN.
var login_url = 'https://example.com';
var formData = {
sid: 'username',
PIN: 'password'
}
How would I go about creating the same scraper but with javascript? I have seen the request library, which seems like what I want to use but cannot get it to work.
You need to use the request module to POST the form data to your endpoint. The response from the server will be in the call back to the .post() method.
const request = require('request');
// do not reassign "request", if you need to set properties us a different variable
// use the action= value from the form for the URL
const url = 'https://central.carleton.ca/prod/twbkwbis.P_ValLoginn';
const data = {
sid: 'username',
PIN: 'password',
};
request.post({ url: url, formData: data }, (err, response, body) => {
if (err) {
console.log('failed', err);
} else {
console.log('the response', body);
}
});
If you are interesting in parsing the resulting HTML I recommend using CheerioJS - much like jQuery but server side.

Categories