Is there any reason to put user authentication farther down the chain instead at the middleware level in express? - node.js

Is there any reason to put user authentication farther down the chain INSTEAD at the middleware level of express (i.e. app.use(express.express.basicAuth(...) )?
(It seems like there is no good reason to live outside of the middleware.)
Why I'm asking. I've gotten some inherited code where the previous programmer put user.auth in the controller.
So a call from the client follows this path:
client >>
middleware of express >>
api_server (ROUTER passes on requests to proper CONTROLLER) >>
api_server (CONTROLLER gets what it needs from DB) >>
api_server (CONTROLLER sends response with data to VIEW on way back to client) >>
client happy ;D
(Please provide suggestions on how to make this question more precise if it's lacking somewhere. I'm getting up to speed on setting up an entire system.)'
Thanks you.

Unless you are targeting that specific route there is no reason to do this. You can even do url specific auth with global middleware as well. The following code is common in my applications.
app.use('/administrator/*', authMiddleware);

Related

Call NodeJS function from client-side

I have NodeJS on / path.
On /another.ejs path, I have a little website and I wanna get data from /value path.
I cannot do this call with pure JS and AJAX, because of CORS.
Can I do something like when I click on button, it calls function in NodeJS and return data?
I don't know why CORS is going on in same domain name, but you can try some other ways to get result from routes.
Using proxy to throw result between server and client.
You can use proxy things.
Means creating middle hand (link to another stackoverflow answer)
Also look: PHP: no.php
CORS Module
Also see above comment by codeherk.

Node.js: Authorizing routes vs. authorizing methods

Quick background
I am building an API with Node.js, Express and Mongoose. The authentication I implemented works with the passport-headerapikey package. I search the DB for the user with the api-key and add that user to the req Object. Thus ensuring my knowledge about the identity the whole time until the request ends.
Authorization
Let's get to the issue.
Up until now I called an authorize() function in every endpoint manually before doing anything. Like so:
router.post('/', (req, res) => {
autorize('admin', req.user.role) // method is called at every route manually
.then(() => {
... do stuff here
})
.catch(err => req.status(403).send())
}
My colleague said to me it is not a good solution and, rather than just securing the endpoint itself, I should have a session management that makes the current user available globally so that I can authorize at any point in every function individually.
Meaning:
A Method createUser(obj) could then call inside itself an authorization method or check for a condition like so:
createUser(obj) {
if (currentUser.role !== 'admin') {
return false
}
obj = new User(obj)
return obj.save()
}
That would mean I would return false in every function if a condition is met. Accessing the globally available currentUser for that session. (e.g. globalCurrentUser.role !== admin or something along those lines)
My question(s)
Is it bad practice to just secure endpoints and not functions?
Can't I just require an extra param "auth" with every function, so that when called it needs to receive the currentUser.role like in my authorize() function or it returns false? That means I pass the user manually to every function or it will simply fail
If I should have a session management for global access of the user during the request: Do you have suggestions for frameworks?
Thanks in advance,
Benno
Authentication and authorisation are two different things and should be treated separately. Authentication says "who are you?" and authorisation says "do you have permission?". Baring in mind that Express is designed entirely around middleware, I would do the following.
Abstract your authentication into a single piece of middleware which runs for all your endpoints using app.use() before you mount your router / routes.
Create an authorisation function which can be called from anywhere, it takes a user (or id or whatever you have) and a role, and it then checks if the user has that role.
Think of it like this, your authorisation will never change, it is core to your application. If you decided to ditch Expressjs and use Koa or move from traditional HTTP requests to Web Sockets you wouldn't want to change your authorisation logic. But your authentication may well change, you may wish to no longer use a header to store the token, perhaps you switch to cookies or something else entirely, you may wish to change this.
You'll end up with a piece of global middlware which checks an auth token and attaches the user object to the req. Then you'll have a utility function called something like userHasRole which will be called at any endpoint which requires a specific role within the application. You're then free to check permissions at any point in the application. This may be in very different places across your application, for instance you might check if they're an admin at the beginning of a request to some admin dashboard, but you might check permissions later on if they try to access a particular resource. When accessing a particular resource you might want to let them through and determine at the last minute if they have access to the resource. (It's hard to give a specific example without knowing more about your application).
In some instances it might be suitable to check at the beginning of the business logic, in other places it might make sense to check later on. This shouldn't matter, you should be able to run this check whenever you need to. This will depend entirely on the business logic and placing it in every single function ever may be useless if it's just formatting a string output, but it might be useful when trying to pull out a DB record.

Best way to handle API calls from frontend

Okay, so atm i have a frontend application built with Nuxt JS using Axios to do requests to my REST API(separate).
If a user does a search on the website the API URL is visible in XMLHttprequests so everyone could use the API if they want to.
What is the best way of making it so that only users that search through my website gets access to the API and people that just directly to the URL gets denied. I suppose using some sort of token system, but what is the best way to do it? JWT? (Users never log in so there is no "authentication")
Thanks!
IMO, you CANNOT block other illegal clients accessing your
backend as you describe that the official client and other illegal have the same knowledge about your backend.
But you can make it harder for illegal clients to accessing your backend through some approach such as POST all requests, special keys in header, 30-minutes-changed token in header and server-side API throttling by client IP.
If the security of the search API is really important, authenticate it by login; if not, just let it go since it is not in your critical path. Let's focus on other important things.
I'm in the same "boat" and my current setup is actually in VueJs but before even come to StackOverflow I developed a way to actually, the frontend calls the server and then the server calls the API, so in the browser, you will only see calls to the server layer that, the only constraint is that the call must come from the same hostname.
backend is handled with expressJs and frontend with VueJs
// protect /api calls to only be originated from 'process.env.API_ALLOW_HOST'
app.use(api.allowOnlySameDomainRequests());
...
const allowHostname = process.env.API_ALLOW_HOST ||'localhost';
exports.api = {
...
allowOnlySameDomainRequests: (req, res, next) => {
if(req.url.startsWith('/api') && req.hostname === allowHostname) {
// an /api call, only if request is the same
return next();
} else if (!req.url.startsWith('/api')) {
// not an /api call
return next();
}
return res.redirect('/error?code=401');
},
...
};
In our case, we use Oauth2 (Google sign through passportJs) to log in the user, I always have a user id that was given by the OAuth2 successful redirect and that user id is passed to the API in a header, together with the apikey... in the server I check for that userid permissions and I allow or not the action to be executed.
But even I was trying to find something better. I've seen several javascript frontend apps using calls to their backend but they use Bearer tokens.
As a curious user, you would see the paths to all the API and how they are composed, but in my case, you only see calls to the expressJs backend, and only there I forward to the real API... I don't know if that's just "more work", but seemed a bit more "secure" to approach the problem this way.

Cross domain Sails.js + Socket.io authorization

I'm working in an application which delivers push content to a group of web applications hosted in different domains. I'm using Sails.js and Socket.io, and structured it like this:
The client script, running on each web application's client's browser, is something like:
socket.on('customEvent', function(message){
//do something with message on event trigger
}
And then, in the server, the event 'customEvent' is emitted when needed, and it works (e.g. on the onConnect event: sails.io.emit('customEvent',{message ...}).
But I'm facing a problem when it comes to handle authorization. The first approach I've tried is a cookie-based auth, as explained here (by changing the api/config/sockets.js function authorizeAttemptedSocketConnection), but it isn't a proper solution for production and it isn't supported in browsers with a more restrictive cookie policy (due to their default prohibition to third-party cookies).
My question is: how to implement a proper cross-browser and cross-domain authorization mechanism using sails.js, that can be supported in socket.io's authorization process?
======
More details:
I also tried adding a login with a well-known oauth provider (e.g. facebook), using this example as a base. I've got the Passport session, but I'm still unable to authenticate from the client script (it only works in pages hosted by my node app directly).
A JSONP request to obtain the session might be a solution, but it didn't work well in Safari. Plus I prefer the user to be authenticated in one of the web apps, rather than in my node application directly.
I believe your routes must handle CORS mate. Example:
'/auth/logout': {
controller: 'AuthController',
action: 'logout',
cors: '*'
},
Of course you can specify the list of ip your are accepting (and then replace the '*').
Worth mentionning that you must specify where socket.io has to connect to (front-end JS):
socket = io.connect(API.url);
For any common http GET/PUT/POST/DELETE, please ensure that your ajax envelope goes with the credentials (cookie). For example with angular:
$httpProvider.defaults.withCredentials = true
Let me know how it goes.

Express.js: Is this a RESTful interface?

I am pretty new to node and express.js and I'm new to the concept of REST applications as well. I want to code a typical CRUD app, some sort of diary. Hence, I have a collection of entries, can view a single entry and can add, edit and delete an entry.
I'm not quite getting yet, how URi's have to be set up to represent a REST conform API. I would create something like this in my app.js:
// GET REQUEST ROUTING
app.get('/', diary_router.home);
app.get('/entries/', diary_router.listEntries);
app.get('/entries/:id', diary_router.getSingleEntry);
// POST REQUEST ROUTING
app.post('/entries/', diary_router.addEntry);
// PUT REQUEST ROUTING
app.put('/entries/', diary_router.updateEntry);
// DELETE REQUEST ROUTING
app.delete('/entries/', diary_router.deleteEntry);
Could that be called a REST conform interface? Should I rather add the respective action in the routes, such as this and does the item-ID need to be shown in the URL for PUT and DELETE actions, too?:
// GET REQUEST ROUTING
app.get('/', diary_router.home);
app.get('/entries/', diary_router.listEntries);
app.get('/entries/show/:id', diary_router.getSingleEntry);
// POST REQUEST ROUTING
app.post('/entries/add/', diary_router.addEntry);
// PUT REQUEST ROUTING
app.put('/entries/update/:id', diary_router.updateEntry);
// DELETE REQUEST ROUTING
app.delete('/entries/delete/:id', diary_router.deleteEntry);
What would be best practice here? Any help is much appreciated.
B.
In the loose definition of REST that we seem to have converged on in web-land, the first option seems to fit best.
Edit: and yes, you should specify the ID in the PUT and DELETE routes.
HTTP is a really cool protocol for applying verbs (request methods) to nouns (URLs). In that spirit, it's probably best to use the request method to differentiate what you want to do to the resource that you're requesting.
Note: you can use the methodOverride middleware in express if you're worried about browsers not being able to use arbitrary HTTP methods.
The way the methodOverride middleware works is that you use an <input type="hidden" name="_method" value="PUT"> or similar to specify the method, despite it just being a regular POST request, and the methodOverride middleware will set the method property on the request that you get in your express application. This way, you can signal the intended request method without the client actually having to support that method.

Resources