I'm a beginner in Express framework and having some difficulty with the code flow. I have following code in app.js
app.use('/', index);
app.use('/login', login);
app.use(require('./routes/authenticate_user'))
app.use('/user', userDetails);
Problem is that If a user enters an invalid route suppose '/wrong' then my middleware sends the response for that instead of app throwing 404 Not found. Is there something I'm missing?(looks obvious). Thanks for any help.
There are a couple choices for how/where you run the authentication middleware.
1) You can run it immediately after any non-authenticated routes have been defined. This will give you a non-auth error for any route, whether it's a real route or not other than the few routes that the user is allowed to go to without authentication.
2) You can manually add the middleware to each defined route that is supposed to have authentication such as:
app.get('/something', yourAuthMiddleware, yourRouteHandler);
This will run the auth check only on routes that are actually defined. This allows you to give a 404 rather than an auth error for routes that are not defined.
The advantage of the first option (which is essentially how you have it now) is that a non-authenticated user doesn't even get to find out which routes are defined or not. If they're not authenticated, they don't get in at all except to the couple of routes that they are allowed to. In my opinion, this is the right design.
The second option will let you give a 404 for a route that isn't defined, but it requires manually adding auth to each route or each router that you define that needs auth. This allows a non-authenticated user to find out which routes are defined and which ones are not.
Related
I would like to use the method route() on an express router to service a specific route with different HTTP methods. The following code works fine:
var express = require('express');
var router = express.Router();
router.route('/register')
.get(adm.signUpForm)
.post(adm.signUp);
However, when trying to use a middleware on the post route, I'm getting stuck. The following code works:
// LOGIN processing
router.post('/login', passport.authenticate("local", {
successRedirect: '/',
failureRedirect: '/login'
}), function(){
//empty
});
Here, the middleware function passport.authenticate(...) is called to check if the user credentials are valid or not. Authenticated users get re-directed to the homepage at "/"; Unknown users (or with incorrect password) get re-directed back to the "/login" form.
Now, I would like to re-factor this code and use something similar to the code example shown above (sign-up route), i. e. I would like to use router.route('/login).xxxx to service HTTP request xxxx on route '/login'. How can I tell express to use my passport.authenticate middleware function on the POST request to '/login'?
router.route('/login')
.get(adm.loginForm)
.post(<my-middleware-function ???>, adm.login);
... where adm.loginForm is the end-point function that issues the login form upon a GET request to /login and adm.login is the end-point function that should be called when the server receives a POST request on this route, i. e. once the login form is submitted.
To the best of my knowledge, the express (4.x) documentation doesn't mention anything about installing a middleware function for a specific route and (at the same time) a specific HTTP request. I know that router.route('/login').use() can be used to install a middleware function for all HTTP requests on this route, but I only want my middleware to be called upon POST requests.
Any suggestions? Thanks.
You can add them where you mentioned:
router.route('/login').post(checkPassport, adm.login)
You can also chain them together:
router.route('/login').post(checkPassport).post(adm.login)
checkPassport is the middleware you'll need to write that handles the passport authentication logic
I am overall clueless about how and why you set up a node.js app, and how any of the app.use functions work - the tutorials on it don't explain the why of anything.
Anyway, I have socket.io, res.locals and index.js set up like so in the app.js root file.
const sockets = require('./models/socket')(io)
app.use(function (req, res, next) {
res.locals.user_id = req.session.user_id;
next();
});
const routes = require('./routes/index');
app.use('/', routes);
I'd like to be able to access res.locals in the socket.js model, like I can in index.js found in the routes folder.
I can't guess how to go about doing this. If anybody is able to explain how and why I can or can't that would be a bonus. Thanks!
Welcome to Expressjs, there are a few fundamentals you should probably research before going any further, they'll help solve some of your confusion. I'll give a brief explanation of them but I suggest you do further research. I'll then answer your actual question at the end.
Middleware and app.use
Expressjs is built upon an idea that everything is just "middleware". Middleware is a function which runs as part of a request chain. A request chain is essentially a single client request, which then goes through a chain of a number of middleware functions until it either reaches the end of the chain, exits early by returning a response to the client, or errors.
Express middleware is a function which takes the following three arguments.
req (request) - Representing the request made by a client to your
server.
res (response) - Representing the response you will return to
the client.
next - A way of telling express that your current
middleware function is done, and it should now call the next piece of
middleware. This can either be called "empty" as next(); or with an
error next(new Error());. If it is called empty, it will trigger
the next piece of middleware, if it is called with an error then it
will call the first piece of error middleware. If next is not called at the
end of a piece of middleware, then the request is deemed finished and the
response object is sent to the user.
app.use is a way of setting middleware, this means it will run for every request (unless next() is either not called by the previous piece of middleware for some reason, or it's called with an error). This middleware will run for any HTTP request type (GET, POST, PUT, DELETE, etc).
app.use can take multiple arguments, the important ones for beginners to learn are: app.use(func) and app.use(path, func). The former sets "global" middleware which runs no matter what endpoint (url path) the client requests, the latter (with a specific path) is run only if that specific path is hit. I.e. app.use('/hello', (req, res, next) => { res.send('world'); }); will return "world" when the endpoint "/hello" is hit, but not if the client requests "/hi". Where as app.use((req, res, next) => { res.send('world'); }); would return "world" when you hit any endpoint.
There are more complex things you can do with this, but that's the basics of attaching middleware to your application. The order they are attached to the application, is the order in which they will run.
One more thing, this will blow your mind, an express application made with the standard const app = express() can also be used as middleware. This means you can create several express applications, and then mount them using app.use to a single express application. This is pretty advanced, but does allow you to do some really great things with Express.
Why can you not access res.locals in socket.io? (The real question)
Within your middleware handler, you are setting up a res.locals.use_id property. This only lives with that individual request, you can pass it around as long as the request is alive by passing it into other functions, but outside of that request it doesn't exist. res is literally the response object that tells Express how to respond to the clients request, you can set properties of it during the request but once that HTTP request has ended it's gone.
Socket.io is a way of handling web socket requests, not standard HTTP requests. Thus, in a standard express HTTP request you will not be able to hand off the connection to anything with socket.io, because the connection is a single short lived HTTP request. Likewise, you won't be able to do the same the other way.
If you wish to find the users id in a socket.io request, you'll have to do this within the socket.io request itself.
Right now, you're entering a piece of middleware for an Express.js request, you are then calling next() which runs the next piece of express middleware, at no point does it cross over into Socket.io realms. This is often confused by tutorials because Socket.io can handle requests across the same port as Express is listening on, but the two are not crossed over. So you will need to write separate middleware for both Express.js requests chains, and socket.io request chains. There are ways of writing this code once and then writing an adapter to use it across both platforms, but that's not what you've tried to do here.
I would suggest you look at doing just nodejs and express for a time before taking on socket.io as well, otherwise you're trying to learn a whole heap of technologies all at once is quite a lot to try and take on board all at once.
I am trying to implement the passport local authentication in my backend. It is a todo app which is built with the help of the MEAN stack. Unfortunately, I am facing some problems implementing it. The folder structure is
In Controllers folder, the controllers for the various routes are present.
In routes folder, the file "api.route.js" contains the main route. I want to implement authentication here such that no further routes can be accessed if the user is not autheticated.
In the api subfolder, the different routes are configured.
In the config subfolder, the passport local strategy is defined.
Another new problem I have noticed is that the routes after todo are not detected.
Example : localhost:3000/api/todos
localhost :3000/api/todos/login
route does not work. It says Error 404. Every other sub routes are the same. Any help which will help me to implement will be appreciated. The github profile for this project is :
https://github.com/AritraWork97/TODO-FULLSTACK
The main folder is Todo Backend, it contains the backend code
To, protect routes in back-end I think express-jwt will be handy.
Initialize it like this,
const jwt = require("express-jwt");
const auth = jwt({secret: jwt_secret});
Then put the auth middleware before a route that you want to protect.
router.get("/secret/:uid", auth, profileCtrl.secret);
Backstory: I'm trying to debug an issue in one piece of middleware that I think is coming from other piece. But, I'm not sure. So anyway, I would like to be able to check what middleware is actually being called, because I'm not sure of the ordering.
Is it possible to inspect the set of middleware that is currently being used?
I have tried to find any piece of internal state where Express might be storing the middleware, but I was not able to.
You can't see what is specifically "middleware", but you can inspect all registered handlers.
In express 4:
// Routes registered on app object
app._router.stack
// Routes registered on a router object
router.stack
Fine for inspection/debugging, probably not a great idea to program against any variable prefaced with an underscore.
How middleware works:
The middlewares are generally used to transform a request or response object, before it reaches to other middlewares.
If you are concerned with the order in which the middlewares are called, express calls the middleware, in the order in which they are defined.
Example,
app.use(compression());
app.use(passport.initialize());
app.use(bodyParser());
app.use(cookieParser());
the order is
compression,
passport,
bodyParser,
cookieParser
(plus I think your bodyParser and cookieParser middlewares should be before the other middlewares like passport).
That is the reason why the error handling middlewares are kept at last, so that if it reaches them, they give an error response.
So basically, request drips down the middlewares until one of them says that it does not want it to go any further(get, post methods are such middlewares, that stop the request).
Now, the debugging part:
You may not be able to inspect the middleware properly internally, but you can check whether middleware has worked properly by inserting your own custom middleware in between and then put a breakpoint on it.
Let's say you want is to debug what happened to your request after the bodyParser middlewares does it tasks, you can do is put your custom middleware in between and check the request and response whether they are modified properly or not.
how you do this is by following example.
Example,
app.use(bodyParser());
//custom middleware to inspect which middleware is not working properly
app.use(function(req,res,next){
console.log("check something!"); //do something here/put a breakpoint
next();
/*this function is the third parameter
and need to be called by the middleware
to proceed the request to the next middleware,
if your don't write this line, your reqest will just stop here.
app.get/app.post like methods does not call next*/
});
app.use(cookieParser());
This is one way in which you move this custom debugger in between the middlewares, until you figure out which one is giving faulty outputs.
Also, if you want to check the middlewares functionality, you can look at the documentation of those middlewares. They are quite good.
Check by playing with your custom middleware.
I have a web server using httprouter and negroni. Users log into this system through external OAuth. We save the token to the encrypted session which indicates whether or not they are logged in. I would like to use a middleware to verify whether or not this token exists, and then kick the user back to the login page if it does not. I want to exclude some routes from using the authentication middleware. There is an example in the negroni README of doing this with gorilla mux, but I can't quite get my head around doing this scalably with httprouter. Something similar to my server setup is below:
router := httprouter.New()
router.GET("/login", Login) // auth not required
router.GET("/", Index) // auth required
s := negroni.Classic()
s.Use(sessions.Sessions("example-web-dev", cookiestore.New([]byte("some garbage"))))
s.Use(authenticator.Get())
s.UseHandler(router)
Where /login is a route I do not want to require authorization through the middleware and / is. authenticator.Get() is my authentication handler func with contents I don't think are relevant to the question.
How can I apply authenticator.Get() to / but not /login? Keeping in mind that there will be several other "public" routes alongside /login and many other gated routes as well.
Some links:
https://github.com/codegangsta/negroni
https://github.com/codegangsta/negroni/issues/25
http://godoc.org/github.com/codegangsta/negroni
http://godoc.org/github.com/julienschmidt/httprouter
I was eventually able to wrap my brain around this process. The solution is to create new negroni.Negroni instances for each individual route. In the case above:
router := httprouter.New()
router.Handler("GET", "/login",
negroni.New(negroni.HandlerFunc(loginHandler)))
router.Handler("GET", "/",
negroni.New(authenticator.Get(),
negroni.HandlerFunc(indexHandler)))
server := negroni.Classic()
server.UseHandler(router)
server.Use(sessions.Sessions("example-web-dev",
cookiestore.New([]byte("some secret"))))
server.Run(":3000")
loginHandler and indexHandler will both need to have this method signature:
func(http.ResponseWriter, *http.Request, http.HandlerFunc)
With the given example, all routes will utilize the middleware provided by negroni.Classic() and the sessions middleware added to server, but only / will use the middleware I created in authenticator.Get().
if using httprouter, params can be retrieved by calling the router.Lookup function. Here is what I did:
_, params, _ := router.Lookup("GET", req.URL.Path)
where router is an instance of httprouter.Router