Authenticate before calling route controller - node.js

I'm working on an API using restify. There will be a dozen or more endpoints and each one requires authentication. The API will be stateless, so each API request, regardless of endpoint, will pass credentials.
What I'd like to do, if possible, is to authenticate before negotiating the route. Otherwise, if I have a route:
server.get('/activities', activities.index);
Then, within activities.index (and every other routing method), I have to duplicate the following:
var user = require('../models/user')(server);
user.authenticate(req.authorization, function(err, user) {
...
// Do the real activities-related stuff.
});
This is one of those things where it feels like there must be a better way of doing it, but I don't know what it is.
Anyone have any thoughts?

So you can register handlers to be ran before every route is ran.
http://mcavage.me/node-restify/#Common-handlers:-server.use()
server.use(function(req, res, next){
//do authentication here
if(authenticated){
return next();
}
else{
res.send({auth:false});
})
So when you use server.use when the user asks for /activites it will run all of the server.use you created in the order you created them before running the code for the route.

Related

Issues with new express-openid-connect package

I have been trying to use express-openid-connect for the last few days with no success. I am able to get the flow to work when hard coding my params. However, my goal is to be able to dynamically call auth() depending on the user being logged in. My initial attempt included calling
app.use(auth(functionThatGetsParams()));
Using the approach above, express complains that secret is required. For some reason, the auth call is getting called before anything else is resolved.
I also tried doing a few different ways,
app.use((req,res, next)=> process.env.secret = 'hello');
app.use(auth({secret: process.env.secret}));
The example above also returns the secret issue. However, setting process.env.secret outside of app.use, works fine.
My issue seems to be related to the things I do in the app.use block. The approach I am looking to use is have a call that resolves who my user is and based off of that gets the right settings.
app.use(ConnectionResolver.resolve);
I use a call similar to the above which is basically a handler that does some async stuff to get the client info and right settings then ends with next().
I would expect that then calling
app.use(auth(ConnectionManager.getAuthSettings()));
Would return the auth settings I need, but when I debug, it looks like this line gets called before anything else, so then secret is missing as the error says.
One other option I believe I may have seen online is creating a list of auth calls for each client, which I can then use for authentication, but I have not seen any examples of how that works.
Does anyone have any ideas on how this might be possible? The environment I am in is multi tenant. So I need to be able to dynamically use a certain auth config depending on the user making the call.
Any help would be greatly appreciated.
You are misunderstanding the concept of middleware.
the auth function, is a middleware factory function, it gets a set of options and returns a middleware function based on those options.
The function passed to the use method of the express app, will execute only when an incoming request will arrive.
When you do app.use(auth(getParams())) what happens is that when your server is starting, it will call getParams function, pass the result to auth function which in turn will return the auth middleware function that will be passed to the app.use function.
Once a request will arrive, the auth middleware (the one returned by the auth factory function) will execute.
You don't need to use auth conditionally. You should set it up, and then you can use the requiresAuth middleware provided by express-openid-connect package to protect your paths that requires authorization/authentication.
If your secret is loading asynchronically, wrap your entire express app setup in a bootstrap function, load your secret and only then call the server bootstrap function.
async function loadSecret() {
//load secret from external source
}
function bootstrapServer(secret) {
const app = express()
app.use(auth({ ..., secert }))
app.get('protected', requiresAuth(), (req, res) => {
// your protected route, will automatically return 401 if not authenticated
})
app.get('non-protected', (req, res) => {
// This route will be open to all without authentication
})
}

Microservices API Authentication with API Gateway in NodeJS/Express

I'm creating a Microservice architecture using Node JS and Express. I know that one of the main features of Microservices are a service oriented architecture where teams can design, develop and ship their applications independently. So in my design I think that each microservice offers their APIs and they communicate between each other with the API in this way each Microservice is independent and have it's own life waiting for request.
I am writing this question because I have several doubts about
authentication and communication between microservices.
For the autentication I have made some test with JWT to authenticate the API of a Microservice and all works fine, this is an example of express middleware for authentication:
const tokenCheck = (req, res, next) => {
let token = getToken(req);
if (token) {
jwt.verify(token, "password, (err, decoded) => {
if (err) {
throw "Failed to authenticate token.";
} else {
req.user = decoded;
next();
}
});
} else {
throw "No token provided.";
}
};
Used in this way:
router.get("/", tokenCheck, Controller.get);
So each route is protected with a layer of autentication.
Instead about communication between microservices I read the best way is to use an API Gateway and I found this library to do it, furthermore i read that it's better to add the authentication middleware inside the API Gateway because if you re-implement these things in each single microservice, you are duplicating the code at first, but more importantly you have two different pieces of software to maintain.
Now my question are two:
1) Is right use an API gateway like this to make communication between microservices?
2) If I move the authentication middleware from the microservices to the API Gateway I have to remove the middleware from the API routes and in this way the API will be unprotected if someone other than the gateway make requests and I think this is wrong because anyone can call that routes, instead if I mantain the middleware also is the mircorservice the code is duplicated, can anyone tell me what is the right way to do it?
I have been working on Node.js from past couple of years and here is my understanding, hope this helps you clear your thoughts.
The answer to your question:
Let me explain to you the work of both the parts you have stated in the question.
http-proxy-middleware
Proxy: In simple words, the proxy means duplicate clone to turn your traffic too.
Read more: What is the proxy server?
Your custome middleware
Your custom middleware is the project specific code to check if all the requests are authenticated.
It would check if the request has a token and if the token is valid.
Conclusion:
You need your custom middleware compulsorily. Another one (http-proxy-middleware
) is optional.
Update:
Now my question are two:
Is right use an API gateway like this to make communication between
microservices?
Answer: No, it is not the right way.
If I move the authentication middleware from the microservices to
the API Gateway I have to remove the middleware from the API routes
and in this way the API will be unprotected if someone other than the
gateway make requests and I think this is wrong because anyone can
call that routes, instead if I mantain the middleware also is the
mircorservice the code is duplicated, can anyone tell me what is the
right way to do it?
For this, you can impose the authentication middleware on app so that all the routes execute the middleware.
Update your server code.
// Init App
const App = Express();
// Authentication code
App.use((req, res, next) => {
let token = getToken(req);
if (token) {
jwt.verify(token, password, (err, decoded) => {
if (err) {
throw "Failed to authenticate token.";
} else {
req.user = decoded;
next();
}
});
} else {
throw "No token provided.";
}
});

ExpressJS middleware vs logic

What is the best way to structure the logic in an ExpressJS API.
So lets say I want to create a register and login function, and lets say I want a user to be logged in when he is successfully registered.
Now there are different ways I can achieve this, my question is then essentially: Which method is best and why?
METHOD 1
Everything is middleware:
router.post('/path', someMiddleware, register, login, function(req, res){
//You are registered and logged in.
});
So here both the register and login is treated as middleware, with both of them ending with a call to next(). This also results in the best reusability, because I can call either login and/or register again in any other express routing.
METHOD 2
Register is middleware and calls login (which is now just a standard function):
router.post('/path', someMiddleware, register, function(req, res){
//You are registered and logged in.
});
So here register is still middleware, but just before calling next() it calls login() which in this case is not middleware. The problem here is that if user that is already registered wants to login, should I create a hybrid login function that is also middleware and just call it in that specific post request?
METHOD 3
Logic is not in middleware and gets called in the wrapper:
router.post('/path', someMiddleware, funcWrapper(register, login), function(req, res){
//You are registered and logged in.
});
and then (in pseudo):
funcWrapper(actions...){
foreach actions
action()
}
Here logic and middleware are split, there is a wrapper that loops through all the functions that are passed in as parameter (in this case register and login)
Just a last question:
If I haven't asked enough questions, I have a last one. Is it better practice to end all express routing calls with
..., function(req, res){
//response
});
or with
..., lastMiddleware);
and then in the lastMiddleware there is some response

Express middleware and parameter handling ordering on route

So I am running some API tests and I noticed that one test is failing because it is running some parameter handling logic before middleware, now here is an example of the route definition:
app.post("/something/:some_param",
middlewareA, middlewareB, middlewareC,
function(req, res) {
// Do stuff
});
Now I assumed (wrongly I think) that middleware would be invoked first then it would handle the parameter handler for :some_param however it seems to be the other way around. (by parameter handler I mean app.param())
Problem I have here is that if the above is correct and parameter handlers are run first, some of the logic within the parameter handler assumes the user is logged in already and blows up if they are not, and middlewareA handles user authentication and if they are not logged in redirects them etc, so ideally I would want middlewareA to be called first, so is there a way to achieve this ordering?
The only way I could see this working would be if the parameter handler could utilize middleware but there is no documentation on the API docs on this subject, so is there any best practice to handle this sort of scenario? as I do not want to have to shoe horn my middlewareA logic into my :some-param handling logic as I also have many other :other-param handlers etc which would also need this authentication (and other) middleware run before they run.
Yes, param handlers run before middleware. You can deal with this by either:
recoding your param handler as a middleware. There's not that much difference between the 2 mechanisms.
OR, in your param handler, just run the desired middleware directly as below:
.
function someParam(req, res, next, paramValue) {
myAuthMiddleware(req, res, function (error, result) {
if (error) {
next(error);
return;
}
//Here the user will be logged in
// do what you need to do with req and paramValue
next();
});
}

How can a Sails controller get request history

I am developing a website using Nodejs (with Sails & Passport frameworks). I am wondering how a Sails controller get the request history of a user.
For instance, a user requests for '/', but a controller redirects the user to '/signin'. Then the user requests for '/signin' using res.redirect(). So the request history looks like
'/'
'/signin'.
Now a SignInController handles the request and at the end, it want to redirect the user back to '/'. So the controller should know the history of the user's request. I guess there should be some frameworks which can record request histories and store them using session or something. Could anyone give me some hints about this?
Let me know if I understood well but what you want to do is to redirect the user to whatever URL he was before a login, right?
To do that you can use the policies (which are executed for all requests, only on the methods you want).
What we do here is save the latest position only (Not the entire history)
In api/policies/ensureReturnToUrl:
'use strict';
module.exports = function (req, res, next) {
req.session.returnTo = req.url;
return next();
};
The configuration part look like that in config/policies.js:
'*': ['passport', 'isAuthenticated', 'ensureReturnToUrl'],
AuthController: {
'*': ['passport']
}
You will have to be careful here to put this policy in the right place only. For example, you don't want to have it on you "/signin" methods (That goes against the whole point)
Then, after a successful login, you just have to read the "returnTo" property and redirect the user: (For example in a AuthController)
if (req.session.returnTo) {
res.redirect(req.session.returnTo);
} else {
res.redirect('/');
}
Obviously this need to be adapted for your use case but the policies are definitely what you need.

Resources