Add Request Variable from Client to NodeJS Server for MiddleWare Router - javascript

I am trying to use routes to help server pages from a nodejs server based on a user being logged in. I am trying to take the login session details from the client side, and pass them back to the NodeJS server to be used in a middleware function for checking authentication.
How do I go about adding a variable to a request for a NodeJS route from the client side?
middleware.js
function loginRequired(req, res, next) {
if (!req.user) {
return res.status(401).render("unauthenticated");
}
next();
}
module.exports = { loginRequired };
server.js
app.use("/dashboard", middleware.loginRequired, mainPage);
The desired result would be, user clicks "Login", some variables are sent back, as well as the request to that route, the variables (i.e req.user) are used to check authentication.

You can send the variables in cookies, and use cookie parser, before your middleware. It provides parsed cookies.
For example, you can send a User variable in cookie, and then in your middleware use req.cookies which will contain your User variable.
Alternatively, you can send data in a POST request and use body-parser to do the same thing. But for authentication purpose, you should use cookies.

Related

serverside rendering with no client-side javascript

I am trying to create an application that can post data both through ajax and through traditional form requests. I am surprised by the lack of information I am finding online about the topic. I guess these days we all assume we have access to client side JS?
I went with express-session, but am getting frustrated at how hard it is to determine what's actually happening. From what I can understand it's cacheing cookie data on the client and somehow including those in requests automatically? Then is it safe to assume that this format will NOT work without client-side javascript support?
Given a form like this:
<form method="post" action="/create">
<input name="value1" onChange={this.handleInput} value={this.state.value1} />
<button onClick={this.submitForm}
</form>
My requests sent via ajax will pass auth (due to having session data):
event.preventDefault();
postUrl(`/create`, {value1: this.state.value1})
.then(jsonRes => {
// works
});
being picked up by auth middleware which uses express session and passport:
module.exports.secured = (loginUrl = "/employers") => {
return (req, res, next) => {
if ( (req.isAuthenticated()) ) { return next(); }
req.session.returnTo = req.originalUrl;
res.redirect(loginUrl);
return next();
};
};
which protect a pretty simple api route for creating:
router.post('/create', secured(), (req, res) => {
My thinking is that even if JS is enabled, I could handle the request at this route, but the problem is with authenticating.
What can I do to get my session data sent over in these 'non-js' requests?
I remember in traditional webstacks like Rails or PHP some sort of token is rendered into the form in a hidden field or in the action on render. If this would work, does anyone know how to get the 'vital data' so to speak out of the express session to send as the token? Not possible?
Looking in req.cookies or req.session of the req object that gets parsed in the serverside render, I do not see anything that would be useful for this.
What can I do to get my session data sent over in these 'non-js' requests?
Ussually the response to your login would send a Set-Cookie header to indicate to the client that it should store said cookie, implying it would be used to identify himself
Who stores cookies? its not javascript but the browser, so if you used curl or a scraper , your clients would have to fetch the cookie returned and include it in subsequent requests
What you mention about a token in the form is not for authentication but for cross site request forgery, meaning that since you served a token (and stored it somehow server side) you would only accept a login request including said token (proving someone navigated to your site's login page) so as to prevent other websites or clients who didnt went to your login to attempt POSTing (ie: a scraper )
Also, sessions dont necessarily mean authentication, modern frameworks tend to issue a session regardless if authenticated

Node JS : Allow only server side calls to my api

I have been racking my brains for a simple solution.
Lets say, I have 10 API endpoints in my Node JS application.
I have already allowed 3 of them to be public, the remaining 4 have JWT based authentication
Now I have 3 more routes, which will not have JWT and I need to only allow Server side calls. No browser or curl or postman, should be able to call them. How do I identify from the request object that it is originating from a server?
Or to put it in another way, how to I reject all cross origin calls to my api? As server side does not fall in CORS, they should filter through
----- EDIT -----
I recently came across a service that uses User Agent header to block server side calls.
Can i enforce User Agent header for my service and ensure that the header does not have browser agents. This can be hoodwinked easily, but as a theoretical solution, what would be the nodejs interceptor that discards requests whose user agent refers to a browser agent?
You can use the express-ipfilter package and only apply it to certain routes you want to protect:
const express = require('express'),
ipfilter = require('express-ipfilter').IpFilter;
// Whitelist the following IPs
const ips = ['127.0.0.1'];
// Create the route
app.get("/securePath", ipfilter(ips, {mode: 'allow'}), (req, res) => {
// only requests from 127.0.0.1 (localhost/loopback) can get here
});
app.get("/openPath", (req, res) => {
// all requests can get here
});
app.listen(3000);
If you are using Node behind a proxy, you may need to configure the proxy to set a header with the actual IP and then pass the ipfilter function a function in the detectIp property to the second parameter.
Let's say you are using nginx and have it configured to send the original IP through the x-Real-IP header, you can pass this function to ipfilter:
const express = require('express'),
ipfilter = require('express-ipfilter').IpFilter,
ips = ['127.0.0.1'];
app.get("/securePath", ipfilter(ips, {mode: 'allow', detectIp: getIp}), (req, res) => {
// only requests from 127.0.0.1 (localhost/loopback) that go through the proxy can get here.
});
app.get("/openPath", (req, res) => {
// all requests can get here
});
app.listen(3000);
function getIp(req) { return req.headers["X-Real-IP"] }
You should use a similar authentication/authorization as for the routes that have JWT authentication from the clients.
This means that the caller service should also authenticate using a JWT token, having a special role of service or something like that (this is 100% your decision on what convention you choose). That token should be signed by the caller and verified by the receiving microservice.
This solution has the advantage that it does not depends on the infrastructure, it works the same no matter where the services are deployed.

What is the best way to access the JWT from node?

I have implemented JWT authentication using Node.js. When the user signs in, Node.js signs/creates a JWT and sends it back. Thereafter, it is stored in the localStorage. Now, this is probably where I am going wrong, but... to move forward, I make use of the express router, and within the router code (which is obviously at the node level) I want to be able to access the token (which is in localStorage) so that I can make a call to the API for further data. However, I just realised that localStorage is at the client-end and that node/express/router doesn't recognise localStorage. So I am stuck. Obviously, I am doing something fundamentally wrong... I should not need to access localStorage from the express router file. Perhaps, I should really be making the API calls not from the express router file, but from client side.
Any hints/directions?
localstorage is bad way to save token. you should save token in cookies and use then where you want.
EXAMPLE:
new Cookies(req,res).set('access_token',token,{
httpOnly: true,
secure: true // for your production environment
});
and then read:
var token = new Cookies(req,res).get('access_token');
You need to send the JWT that is stored on the client side every time you make an API request to the server side.
https://jwt.io/introduction/
Scroll down to the section How do JSON Web Tokens work? The JWT should be sent in the header of the API calls in the form:
Authorization: Bearer <token>
How you do this depends on how exactly you'll send the HTTP requests to the API, but it should be pretty simple in any respects. You can find out about how to add Headers to an angular $http request at this link:
https://docs.angularjs.org/api/ng/service/$http
Then it's up for each of your authenticated express routes to check the headers, pull the JWT out, ensure that it's valid, and then proceed with the request (or halt it if the JWT is invalid).

Express Session and Cookie

I don't understand how serializing and deserializing work with express session.
When I installed Express-session it said that I needed a serialize and deserialize function:
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
Server.js Post route from login form:
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));
My question is when the user attempts to login from the form on my HTML and hits the endpoint as specified above '/login', is this where express session comes into play? So express session will create a cookie with a session id as user._id as specified in my serializeUser function and it will give this cookie to the client? So now when the client makes any subsequent requests to that same server at the endpoint '/login', it will automatically call deserialize user without going through the passport middleware that is provided in the router.post('/login', ...)?
I am not sure when and where these two serialize functions are called and how express session actually uses them? Any clarification would be appreciated.
To understand this, we have to go through the basic idea of what is a cookie and how does it work?
Cookie:
It is collection of data that is stored in computers browser and is sent with every request to the server in request headers and received by the browser from server in response headers.
What is need of a cookie?
Now we know that http requests are stateless (means every request is a fresh request for server that is for example if u login to some website which is the first request made by you and then u make a second request to display your profile then at this point server does not know who are u), so for authorisation the server needs to know who u are and this information is stored in a cookie.
When u log in , ur credentials are send to the server and server sets these credentials in cookie which is then send to the browser , and after that every request u make , that cookie is send back to the server which is then verified and hence allowing u to access the relevent information.
Now a point should come into your mind that are cookies safe for storing users credentials?
The answer is a big NO , as as the user can manipulate it at his/her leisure . Yes a cookies data can be manipulated anytime , so its not safe to store user credentials in cookie , so whats the solution ?
Here we come to idea of sessions.
Sessions:
Session is an object that is stored in server side instead of browser and hence remains safe. Now how it helps in authorisation , see:
When user signs in , request is sent to server and an object session is made which stores the credential of users and this session object is given a unique id which is encrypted using that serializerUser() function and this id is stored in cookie and which is then send to browser. Now the user if try also to manipulate it , he/she cannot as the cookie just contains the session id which is encrypted and can not be decoded by any means.
And then this cookie is send to browser with another request which then goes through deserializeUser() function and gets decoded which matches with the stored session id hence verifying the user.

Facebook login with Parse client site, use user object with Express js

I am trying to create a login procedure with the Parse and Facebook Javascript SDK. The authentication works without a problem on the client side, but I need to access the user object (created by Parse SDK) on the server side too. How can I do this the most elegant way? I thought when I log in into Facebook via Parse a cookie is set and so I can access the user object from the server. Or should I do the login process server side? Any recommendations?
I'm facing the same problem. Turns out that you can use either server-side auth or client-side auth. You cannot mix-and-match the two. Have a look at their official blog post about sessions.
var parseExpressCookieSession = require('parse-express-cookie-session');
// In your middleware setup...
app.use(express.cookieParser('YOUR_SIGNING_SECRET'));
app.use(parseExpressCookieSession({ cookie: { maxAge: 3600000 } }));
// Making a "login" endpoint is SOOOOOOOO easy.
app.post("/login", function(req, res) {
Parse.User.logIn(req.body.username, req.body.password).then(function() {
// Login succeeded, redirect to homepage.
// parseExpressCookieSession will automatically set cookie.
res.redirect('/');
},
function(error) {
// Login failed, redirect back to login form.
res.redirect("/login");
});
});
Also, I came across this when digging through the doc:
You can add Parse.User authentication and session management to your
Express app using the parseExpressCookieSession middleware. You just
need to call Parse.User.logIn() in Cloud Code, and this middleware
will automatically manage the user session for you.
You can use a web form to ask for the user's login credentials, and
log in the user in Cloud Code when you receive data from this form.
After you call Parse.User.logIn(), this middleware will automatically
set a cookie in the user's browser. During subsequent HTTP requests
from the same browser, this middleware will use this cookie to
automatically set the current user in Cloud Code.
...
When you work with user data, you should use HTTPS whenever possible.
To protect your app and your users, the parseExpressCookieSession
middleware requires you to use HTTPS. For your convenience, we also
provide a parseExpressHttpsRedirect middleware for redirecting all
HTTP requests to HTTPS.

Categories

Resources