Unexpected behavior when validating a session token using parse.com - javascript

I'm trying to build a simple application with parse.com as my user manager.
I would like to make a login call to parse.com from my client side, and call my node.js server with the user's session token (I'll add it as a cookie). In the server side, I'll validate the session (using https://parse.com/docs/rest#users-validating) and allow access only if the session is valid.
For example (in my server):
app.get('/api', function(req, res, next) {
var token = getTokenFromRequest(req);
if(tokenIsValid(token)) {
next();
} else { // Redirect... }
});
app.get('/api/doSomething', function(req, res) {
// Do something....
});
the tokenIsValid(token) function should be implemented using https://parse.com/docs/rest#users-validating.
However, it seems that the REST API user validation returns the user even if the user is logged out (expected to return 'invalid session').
Is this a bug in the REST API user validation? What am I doing wrong? Is there a better way for doing that?
Thanks!

Via REST there's no concept of sessions really. REST calls are meant to be stateless meaning that the (current) user at /me will be serialized from the token provided. If the token is associated to a user it will return the JSON representation of that user otherwise in returns an error.
One way or another that call is asynchronous so you can't really use it in and if statement.
You can do:
app.get('/api', function(req, res, next) {
var token = getTokenFromRequest(req);
serializeUserFromToken(token,function(err,parseResponse) {
if(err) return next(err)
if(parseResponse.code && parseResponse.code === 101){
// called to parse succedded but the token is not valid
return next(parseResponse);
}
// parseResponse is the current User.
next();
});
});
Where serializeUserFromToken makes a request to Parse with the token in the X-Parse-Session-Token header field.

Related

How to save JWT token recieved from auth0 login securely (nodejs express)

I am new to Auth0 and trying to implement it in my regular express web application. I need to protect/validate the user before they access some of my endpoints. My understanding is that i can do this with the JWT that is returned from the login callback. I have gotten that far, but when I login, it redirects, and I'm unsure of how to pass in the access token/store it securely on the client side.
this is what my callback endpoint looks like after logging in. It returns the authorization code but I am lost from here.
https://auth0.com/docs/api-auth/tutorials/authorization-code-grant
I return this on login:
/callback?code=oi9-ZTieXo0hYL6A&state=sMJAUK4QVs7jziJ7lXvwmGKF
// Perform the final stage of authentication and redirect to previously requested URL or '/user'
router.get('/callback', function (req, res, next) {
passport.authenticate('auth0', function (err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function (err) {
if (err) { return next(err); }
const returnTo = req.session.returnTo;
delete req.session.returnTo;
res.redirect('/user);
});
})(req, res, next);
});
where do i go from here?
Auth0 does not recommend storing tokens in browser storage (session/local storage). For client side applications, tokens should be short lived and renewed when necessary via silent authentication (renewed via a cookie session with the auth server in a hidded iframe).
This is outlined here:
https://auth0.com/docs/security/store-tokens
If you have a backend, then handle the tokens there, if you are using a SPA + API then use the strategy outlined in the link.

RestApi security - how to restrict access

I am planning to have an REST API in node.js , I want to make sure if the request comes from my web domain allow the request or reject it, how do I do this?
Basically I am trying to restrict access to the REST api by simple technique, any advise on this ?
If your criteria is only a particular user can access it or only signed user can access it,then you can do it with a helper function like below.
app.get('/api/users', checkuser, function(req, res) {
UserModel.find(function(err, users) {
if (!err)
res.json(users);
else
console.log(err);
});
});
function checkuser(req, res, next) {
if (req.user != 'manoj') return res.json('message': 'you dont have permissions to access this url');
next(); //if it is manoj then call the next() iterator function that will take u to the final callback(userFind)
};

Protect API routes in Node.js

I have some routes in my Node.js API sending data from a MongoDB database to an Angular 4 frontend.
Example:
Node.js route:
router.get('/api/articles', (req, res) => {
Article.find({}, (err, articles) => {
if(err) return res.status(500).send("Something went wrong");
res.status(200).send(articles);
});
});
Angular 4 service function:
getArticles() {
return this.http.get('http://localhost:3000/api/articles')
.map(res => res.json()).subscribe(res => this.articles = res);
}
The question is, how do I protect my Node.js API routes from browser access? When I go to http://localhost:3000/api/articles I can see all my articles in json format.
This is not a security measure, just a way to filter the request. For security use other mechanisms like JWT or similar.
If the angular app is controlled by you then send a special header like X-Requested-With:XMLHttpRequest (chrome sends it by default for AJAX calls) and before responding check for the presence of this header.
If you are really particular about exposing the endpoint to a special case use a unique header may be X-Request-App: MyNgApp and filter for it.
You can't really unless you are willing to implement some sort of authentication — i.e your angular user will need to sign into the api.
You can make it less convenient. For example, simply switching your route to accept POST request instead of GET requests will stop browsers from seeing it easily. It will still be visible in dev tool or curl.
Alternatively you can set a header with your angular request that you look for in your express handler, but that seems like a lot of work for only the appearance of security.
Best method is to implement an authentication token system. You can start with a static token(Later you can implement dynamic token with authorisation).
Token is just a string to ensure the request is authenticated.
Node.js route:
router.get('/api/articles', (req, res) => {
let token = url.parse(req.url,true).query.token; //Parse GET param from URL
if("mytoken" == token){ // Validate Token
Article.find({}, (err, articles) => {
if(err) return res.status(500).send("Something went wrong");
res.status(200).send(articles);
});
}else {
res.status(401).send("Error:Invalid Token"); //Send Error message
}
});
Angular 4 service function:
getArticles() {
return this.http.get('http://localhost:3000/api/articles?token=mytoken') // Add token when making call
.map(res => res.json()).subscribe(res => this.articles = res);
}
With Express, you can use route handlers to allow or deny access to your endpoints. This method is used by Passport authentication middleware (which you can use for this, by the way).
function isAccessGranted (req, res, next) {
// Here your authorization logic (jwt, OAuth, custom connection logic...)
if (!isGranted) return res.status(401).end()
next()
}
router.get('/api/articles', isAccessGranted, (req, res) => {
//...
})
Or make it more generic for all your routes:
app.use('*', isAccessGranted)

Express send information to user with a page

I have the following code
var user = function(req,res,next) {
db.findOne({ username: req.params.uid }, function (err, docs) {
//error handaling
if(err){console.log(err)}
//check if user is real
if(docs === null){
res.end('404 user not found');
}else{
//IMPORTANT PART res.sendFile(__dirname + '/frontend/user.html');
}
});
}
app.get('/user/:uid',user);
Don't worry about the database stuff.
I want to know how to get req.params.uid sent to the client side and how to get it from there.
Thanks so much.
If your user is configured correctly every request will have a user:
var user = function(req,res) {
db.User.findOne({ _id: req.user._id }, function (err, docs) {
//error handaling
if(err){console.log(err)}
//check if user is real
if(docs === null){
res.end('404 user not found');
}else{
res.json(docs)
}
});
and then your api endpoint is just '/user/
In your client just make a GET request to this endpoint (maybe using AJAX) and your response will be any user that makes that given request.
Note: You don't need to pass in next unless you are defining middleware.
This is just a more complete answer based on my comment.
If you want to store a string of information about the user with each request they make, then you want to use cookies.
When the user first makes a request to the page, you would set the cookie via the res.cookie. So, in your code, the final if statement would look something like:
if(docs === null) {
res.end('404 user not found');
} else {
res.cookie('uid', req.params.uid, { httpOnly: true });
//IMPORTANT PART res.sendFile(__dirname + '/frontend/user.html');
}
Then, in the next request, and futures requests before the cookie expires, you can access it using:
req.cookies.uid
However, you need the cookie-parser middleware somewhere in your app beforehand:
var cookieParser = require('cookie-parser');
app.use(cookieParser());
If you need to access the value of uid on the clientside, you could either use a template, or set the httpOnly value to false when setting it using res.cookie. Then you could access the cookie using document.cookies.
Check out this W3Schools page for accessing cookies on the clientside.

pass an attr to all good responses in sails js

I'm currently working on a angular + sails project. I'm using json web tokens for auth. It works fine but I wanna set a new token for every validated request that my angular app does.
This is my auth policy
passport.authenticate('jwt', function (error, user, info) {
if (error) return res.serverError(error);
if (!user)
return res.send({
message: info.message,
code: info.code,
tokenError: info.name
});
// The token is ok past this line
// I check the user again
User.findOne({ email: user.email }, function (err, thisUser) {
if (err) { return res.send(err); }
if (!thisUser) {
// send a bad response
}
req.user = user;
// This is the new token that I wanna send to the frontend
var newToken = AuthService.createToken(thisUser);
next();
});
})(req, res);
With this policy I can create the new token, but then I would need a way to include this token in every response, this Is the point where I'm stuck.
I gues I could do it manually in every controller action, but this is want I want to avoid
The best way to standardize your responses in Sails is to use the custom responses feature. In short, instead of calling res.send() or res.json() in your controller actions, call res.ok() instead, and then customize the api/responses/ok.js file that is generated with every new Sails app. This is the same response that Sails blueprints use as well!
In your case, you'd want to save the token onto the request object (e.g. req.token) in your policy code, then use that property in your logic inside of ok.js.

Categories