Node JS Route Behavior makes no sense - javascript

I'm trying to make a simple authentication page using Node with Express framework.
At this moment, I'm not particularly worried about the weak protection.
However, my route file is displaying weird behavior.
Here is the code:
var express = require('express');
var router = express.Router();
var admin = require("../controllers/admin");
router.get('/', function(req, res) {
console.log('Entered top route.');
if(req.body.isAuthenticated) {
res.redirect('admin/index');
} else {
res.redirect('admin/login');
}
});
router.post('/authenticate', function(req,res) {
if(req.body.pword == "key") {
console.log("Resetting body.isAuth'ed");
req.body.isAuthenticated = true;
console.log("New val: " + req.body.isAuthenticated);
res.redirect('admin/index');
} else {
console.log("Failed login attempt: " + req.body.pword);
res.redirect('admin/login');
}
});
router.get('/login', admin.login);
router.get('/index', admin.index);
module.exports = router;
The idea is that the route is entered, upon which we hit the top route (properly logged by console). This redirects based on whether a req variable is set. This all works properly, and the login (I'm using jade templating) is properly rendered. The login file has a form which calls back to this routing file with 'admin/authenticate'. This also works properly; I'm able to properly retrieve the input (confirmed via console logs). However, the actions I take in the /authenticate/ function, even though they are the exact same thing I do in the '/' route right above, fail. I get 404's and Express Not Found printouts which are entirely useless.
My console properly logs 'Failed login attempt' or 'Resetting body...New val: true", but then doing the exact same res.redirect that is initially done in the router.get('/') method above fails, whereas the res.redirects in that function properly redirect and render the correct values.
Any ideas what could be wrong? I could post the admin.login/admin.index methods in the controllers/admin file. However, they're very simple and I think this error stems from a basic misunderstanding of the difference between get and post methods or something (this is my first time using Node).
Thanks!

I think the issue is because of the relative path.
Doing res.redirect('admin/index') from path / and path /authenticate is not same.
res.redirect('admin/index') from /authenticate will redirect user to /authenticate/admin/index, may be thats why it is giving 404.
Try to change res.rediret('admin/index') to res.redirect('/admin/index') in authenticate callback.

Related

Moving Passport Google strategy authenticate method from route to controller breaks

I am using the 'passport-google-oauth' strategy from Passport with Nodejs based Express app to provide authentication. This worked great when I had the logic inside the route file as follows:
router.route('/auth/google')
.get(passport.authenticate('google', {
scope: ['https://www.googleapis.com/auth/userinfo.profile']
});
);
When I moved everything into a controller to make the app more manageable, it stopped working. Specifically, no error is being thrown. The GET request succeeds and the debug method outputs the string, but then it just loads forever and I'm not being redirected to the Google page to select which account to log in with. Any ideas what is going on here and what I need to change to make it flow like fine wine?
// route file
router.route('/auth/google')
.get(backendController.googleAuthenticate);
// controller file
exports.googleAuthenticate = () => {
debug('attempting Google authentication');
passport.authenticate('google', {
scope: ['https://www.googleapis.com/auth/userinfo.profile'],
failWithError: true
});
}

How to go about creating temporary authentication for a website?

I'm new to authentication with websites, and I've been doing a lot of reading on the different kinds of user authentication (for example session vs token authentication) you can use. However, a lot of it seems more than what I need, and I'm not sure which ones will be suitable for my cause.
My idea is to generate temporary user accounts and passwords that will expire after the first use. I want this integrated with my website, so they have one chance to view restricted pages, after which they will not allowed access to those parts again (unless provided with new credentials).
Any direction in the right step will be appreciated.
Update: I'm using Javascript(Node) as my server side language
Session-based authentication is actually incredibly lightweight if you're using a Node backend, due to most (if not all) webserver libraries supporting "middleware", which modify requests before they hit your route functions. The Express-compatable middleware client-sessions is fantastic for this, and I used it previously in a project with great success. It adds a cookie on the first request a user makes to your site which identifies them, and if at some point they log in, you can flag that session as authenticated, store session information, and other data related to them specifically.
Assuming you want both login & logout, the simplest way would to be to use POSTs over HTTPS to login & logout routes. Inside of the resolution for the login route, you would simply "mark for deletion" inside whatever database you're working with.
An example might look like this:
var app = express();
function authenticate(user, pw){
//do your application specific login verification here
}
function deleteAccount(user){
//do your application specific user removal here
}
app.use(require("express-session")({
secret : "YOUR-SECRET-KEY-HERE"
cookieName : "Session"
//any other desired config options go here
})
app.post("/login", function(req, res){
var user = req.body.user;
var pw = req.body.pw;
req.Session.isAuthenticated = authenticate(user, pw)
if(req.Session.isAuthenticated){
markForDeletion(user, pw);
}
res.write("logged in as: " + user);
res.end();
});
app.post("/logout", function(req, res){
deleteAccount(req.Session.username);
req.Session.username = "";
req.Session.isAuthenticated = false;
res.write("logged out!");
res.end();
});

How to pass request parameters back to Angular

I currently have an app which uses Express with Jade templates.
I'm building a new version of the app using Angular with client-side HTML.
I need access to certain request parameters in order to determine user permissions in my Angular code. My problem is that I don't know how to get ahold of these parameters in my Angular controllers/services.
Below is what currently occurs in Express with the Jade structure:
routes.js:
router.get('/player/:id',
playerRoute.show
);
player.js:
var show = function(req, res) {
res.render('player', {user: req.user});
};
...and now my new version's handler:
var player = function(req, res) {
//res.sendFile(path.join(__dirname, '../v2', 'index.html'));
res.json({user: req.user});
};
The correct user JSON is sent back to my client-side with the code above. When res.json is commented out and res.sendFile uncommented the correct HTML is rendered. My dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
After all that, your question just boils down to:
MY dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
You don't. The usual case is to just render the HTML along with the assets needed to render the initial app (hide everything, show a splash screen whatever). Further data (like getting your user) is handled by API calls to your server via Angular's HTTP facilities. That means they are separate. After that API call, your app determines what to render.
Otherwise, you could just render the data in the HTML as some global variable and have Angular pick it up from there. This is messy IMO, but doesn't require a separate API call to get the data.
copied from my own answer to a similar question
To get a variable from server to client javascript try templating a json string into the html and loading it from the javascript. EJS handles quote escaping and I think Jade does too. For reference content!= safeString tells Jade to skip escaping, so does content !{safeString}.
- var user={id:1, displayName:'foo'}
#example
meta(data-userJSON=JSON.stringify(user))
script(src="//code.jquery.com/jquery-1.11.3.min.js")
script.
var user = JSON.parse(
$('#example meta').attr('data-userJSON')
)
console.log(user);
span #{user.id}
span #{user.displayName}
Here's how I ended up handling this situation. I simply created a new API endpoint which I can easily hit with an Angular service. Here's the Node setup:
routes.js:
router.get('/currentUser',
apiController.currentUser.index
);
currentUser.js:
var index = function(req, res) {
res.json({user: req.user});
};
module.exports = {
index: index
};
Still seems odd to me to make an API call to get the request parameters, but it works. Feedback appreciated.

Meteor cookies and Server side routes

It seems that in Meteor, we cannot call a server side route to render a file to the page without some sort of work-around from our normal workflow in terms of authentication.
Software/Versions
I'm using the latest Iron Router 1.* and Meteor 1.* and to begin, I'm just using accounts-password.
Background/Context
I have an onBeforeAction that simply redirects the user to either the welcome page or home page base upon if the user is logged in or not:
both/routes.js
if (Meteor.isClient) {
Router.onBeforeAction(function () {
if (!Meteor.user() || Meteor.loggingIn())
this.redirect('welcome.view');
else
this.next();
}
,{except: 'welcome.view'}
);
Router.onBeforeAction(function () {
if (Meteor.user())
this.redirect('home.view');
else
this.next();
}
,{only: 'welcome.view'}
);
}
In the same file, both/routes.js, I have a simple server side route that renders a pdf to the screen:
Router.route('/pdf-server', function() {
var filePath = process.env.PWD + "/server/.files/users/test.pdf";
console.log(filePath);
var fs = Npm.require('fs');
var data = fs.readFileSync(filePath);
this.response.write(data);
this.response.end();
}, {where: 'server'});
Cookie related code added
I found a SO answer where a method to set and get the cookies is outlined here: SO Cookies technique
And then added the following code to my project:
client/main.js
Deps.autorun(function() {
if(Accounts.loginServicesConfigured() && Meteor.userId()) {
setCookie("meteor_userid",Meteor.userId(),30);
setCookie("meteor_logintoken",localStorage.getItem("Meteor.loginToken"),30);
}
});
But this does not work as expected, the setCookie code is not valid for some reason.
My Questions
Question 1: Using cookies, how do I properly set/get and check for the cookies?
Question 2: What precautions should I take using the cookies approach?
Side Question: Is cookies the best way to go about this, or is there a
simpler way to achieve the same thing?
You can call a method that generates a temporary access token and when you get a positive answer from the server (meaning that the token was created), you can check the validity of this token before loading the PDF.
As for using cookies: It might be more convenient when compared to calling a method, waiting and then redirect/open a new tab. I tested your code, with the W3C client side javascript functions, and it worked at client side. The function getCookie assume that you're the client, not the server. You need to check the request and extract the cookies.

Node.js preresponse with Express

So I'm doing a web page with Node.js and Express framework. I already have registration and login (I'm holding users id in a session). Next step is to render different page whenever a user is authenticated.
Some of those pages require a User object which is just a mapping of a user from my db. So whenever an authenticated request comes I need to retrieve the user from my db. But writing this code every time seems to be a bad way to do this. So here's the question: is it possible (and if it, then how?) to do, say preresponse, so I can automaticaly retrieve User object whenever I know that the user is authenticated and THEN do the main response?
Middleware is what you are referring to. Middleware is just a function that gets called sequentially when the route is triggered. So to have a loadUser function:
function loadUser(req, res, next) {
// You would fetch your user from the db
var user = users[req.params.id];
if (user) {
req.user = user;
next();
} else {
next(new Error('Failed to load user ' + req.params.id));
}
}
app.get('/user/:id', loadUser, function(req, res){
res.send('Viewing user ' + req.user.name);
});
You can define as many middleware functions as your need. Just be sure to call next() at the end to pass the route handling on to the next function.
This EXACT example is covered in the express.js route middleware docs. Go read it and you'll see the pattern of using middleware to factor out common functionality that you need at many route paths in your app.

Categories

Resources