How can I share a root path using Express? - node.js

I want to be able to have two endpoints sharing the root path, both for different purposes.
One will be for obtain a user via its ID and the other via token.
Right now I have the following routes:
router.get('/:idUser', paramValidationRules(), validate, verifyJWT, getUserFromId);
router.route('/me').get(verifyJWT, getUserFromToken);
Running tests, the 'me' on the second route is considered a parameter and its redirected to the first route. Is possible to share a root path specifying that one will be used strictly to 'me' and the other one to an integer?

First, you're always hitting /:idUser before /me, so it will always stop at /:iduser and never react me.
So to solve the issue that you can never access /me, put the /me route declaration before /:idUser.
As to only catching numbers, there isn't a built in way, but you could use middleware (and change the order of your routes to the original):
router.get('/:idUser', function(req, res, next) {
req.id = /^\d+$/.test(req.params.idUser);
next();
}, paramValidationRules(), validate, verifyJWT, getUserFromId);
Then, (unfortunately) in all your middleware and handler (or just the handler) in the opening of the function add:
if(!req.id)
return next();

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
})
}

pass session variables to another domain

It seems this cannot be easily done...if at all.
Suppose I have 2 domains, www.mydomain.com and www.mydomain.org. Each domain uses a Node.js/Express back-end and in addition both use the "express-session" module to create session information. I wish to be able to have a user 'log in' while on one domain and have that session information pass to the other when navigation is made to the second domain.
Each domain has a 'catch-all' route that displays a 'splash' page. This is signified by the following route:
app.get('/', function (req, res) {
//do stuff and display 'splash' page...
}
I thought to pass the session information using a route that has a parameter containing the 'session' variable, and using that to set the 'logged in' user on the second domain. For example:
app.get('/user/:client', function (req, res) {
req.session.subscriber = req.params.client; //set the 'logged in' user on the second domain
//do stuff and display 'splash' page...
}
The problem is that BOTH routes seem to be called when using the route with the parameter...I suppose this makes sense since the initial route is activated using a backslash ("/")...Is there some way to correct this?
Any help about cross-domain express-session variable 'sharing' would be greatly appreciated. Thank you in advance.

Restrict access to nodejs express routes

I have "internal" routes in my app :
app.get('/myroute', function(req, res) {
res.status(200).send('Hello!');
});
But the route is also accessible from outside:
curl http://example.com/myroute/?this=that
How to restrict the use of this route to the app / domain itself, ideally with a nice error?
As I see it, you have a few options:
Consider whether this route needs to be a web route at all, and not a function. If it's internal, surely a function would suffice?
Create a 'shared secret' for this function that must appear in either the header or as a request param. Then only callers that know this secret can call it.

router.param not triggering passport.js initialize in app.use

I've got a fairly straight forward Node Express routing app set up, to which I've just added passport.js authentication. I'm now trying to integrate this with the existing routes.
I run the basic middleware of:
app.use(passport.initialize());
app.use(passport.session());
and then if I run a simple
app.get('/route', (req, res)=>{
console.log(req.user)
});
I get the expected result of it printing the logged in user. So far so good...
However, I'm now trying to access this req.user within some of the child routes that I have set up. In the first route I'm trying the first step is to bring in a parameter and compare it against the req.user:
app.use('/route/:userId', idRouter);
And then:
idRouter.param("userId", async (req, res, next, userId) => {
console.log(userId)
console.log(req.user.id)
})
This route fires and prints out the parameter, but req.user is undefined. I can't see a reason why this is the case.
To help debug this I've put some logging in the deserialize function and I can see that it's not being called when I hit the idRouter. I can't see why this would be the case given it's inside an app.use function which should be called every time.
Help please!
I solved this in the end, it was an issue with CORS. Just needed to include credentials in API calls.

Authenticate before calling route controller

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.

Resources