Issues with new express-openid-connect package - node.js

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

Related

How can I share a root path using Express?

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();

Whats the difference between a Controller and a Middleware

I am writing and API in express.js. the original API I wrote only utilized routes and raw SQL queries. I have since rewritten the API for the most part NOW using an ORM to react models and migrations.
My question what is the difference and use cases for middleware and controllers. currently only using middleware because most sources online online only explain what a middleware is.
I don't understand the use case of a controller. and I don't want to omit it from my API if its used in proper programming conventions
You should see middleware as a step in your API and controllers as the entity that will actually respond to the requests.
Bellow is an example where authenticationMiddleware is a middleware because it is a step during the processing but should not return the response. It can though, in case of error.
Then getItems actually handle the logic specific to this calls.
As a rule of thumb, middleware are often reused more than once and often they do not response. On contrary, controller respond and are most of the time specific to one endpoint.
const express = require("express");
const app = express();
function authenticationMiddleware(req, res, next) {
// Check that the user is authenticated using req.headers.Authorization
// for example
if (authenticated) {
// The user is authenticated, we can go to the next step
next();
} else {
// The user is not authenticated, we stop here
res.status(401);
res.send("Error during authentication");
}
}
function getItems(req, res, next) {
// Here we focus on the actual response, we assume that the user is authenticated
res.send({ items: [] });
}
app.get("/items", authenticationMiddleware, getItems);
app.post("/items", authenticationMiddleware, createItems); // Re-use the same middleware
app.listen(3000);
If you're referring to the node/express terminology, middleware are simply the callbacks used by the routing functions/methods (get, set, delete, use, etc). Callbacks can either send or not send responses back to the client. The callbacks are really the 'controllers' if you'd like to call them that (eg: ASP.NET Core MVC) but that's up to you. Below is a quote from Express. Note the term 'middleware' and where there's no mention of a 'controller'.
Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware
function in the application’s request-response cycle. The next
middleware function is commonly denoted by a variable named next.
Middleware functions can perform the following tasks:
Execute any code.
Make changes to the request and the response objects.
End the request-response cycle.
Call the next middleware function in the stack.
'Express' also defines different types of middleware which is useful:
Application-level middleware
Router-level middleware
Error-handling middleware
Built-in middleware Third-party middleware
Here's another nice look at it from Mozilla's pov that does mention a few controller/callback examples.
Beyond that, you can define what a 'controller' is within your team and the naming convention follows from there. Key is your SOLID profile and how you separate your concerns.

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.

How to secure firebase https function?

I have a firebase https function:
exports.updateDatabase = functions.https.onRequest((req, res) => {
// ...
});
Which can be called via: https://us-central1-xxx-xxx.cloudfunctions.net/date
Does it mean that anyone with this url is able to update the database?
Is there a way to secure it when calling it from browser?
You can't stop the function from being invoked by anyone who knows the URL.
You can stop the function from doing something harmful by only allowing it to perform its intended action by requiring that an authenticated user call it, assuming you trust that user.
There is an example of requiring authentication in the official code samples here.

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