how to track user activities on a web application - node.js

I wanted to know how we can track all user activities in a application using node.js
for example,
after user login, user might delete some data, upload some files, edit some details, etc. How can we store all this and show user, what activity was performed on which date.
Is there any module that i can use?

This might not the accurate answer to your query but still this can be an way to log user activity.
If you are using nodejs backend just defined an middleware for very activity user performs for example below.
// this is middleware
user_middleware_logger=(res,req,next)=>{ console.log(res['user_id']); next() }
// actual routes
app.post('add_user', **user_middleware_logger**, function (req, res, next) {
res.send('delete')
})
app.pust('update', **user_middleware_logger**, function (req, res, next) {
res.send('updated')
})

Related

How do I redirect a failed login attempt in node-oidc-provider

I'm setting up an OpenID Connect Provider using node.js, express.js, and node-oidc-provider. I've been working my way through the examples at https://github.com/panva/node-oidc-provider-example/tree/master/03-oidc-views-accounts, but it never deals with a failed authentication. How do I redirect the user back to the login page if they mis-type their password?
expressApp.get('/interaction/:grant', async (req, res) => {
// The initial route hit by the client (Relying Party) that renders the login view if needed.
...
});
expressApp.post('/interaction/:grant/login', parse, (req, res, next) => {
User.authenticate(req.body.email, req.body.password)
.then((users) => {
// returns an array of user objects that match the credentials
if(!users.length)
{
// What now? I can't just redirect back to /interaction/:grant - I get session not found
}
// the rest works well enough (for now)....
...
}).catch(next);
});
Just like in any express app. Think of it this way. Only resolve the interactions with success, or error if you wish to exit the interactions and return control back to the client.
I tend to develop interactions separately and only plug them to oidc-provider when they’re done.

How to use authenticated middleware properly in nodejs

I just started working on node using express framework.
app.use('/', auth, users);
and this is my route file
router.get('/' , function(req, res, next) {
render("dashboard");
});
router.get('/first' , function(req, res, next) {
//first request
});
router.get('/second' , function(req, res, next) {
//second request
});
so on...
My question is, when i pass middleware it checks for every request whether its authenticated or not using passportjs, but suppose i have a dashboard and i am sending 10 ajax requests to grab data for the widgets. So only for dashboard it will call deserialize function 11 times ,first to render the page and then for 10 ajax request. I read answer given over here,
How to properly use Passport.js?
But is it fine to go with this approach?
Yes, it is fine to go with this approach if you don't want to have security issues. You have to check the user for every request, it is very simple someone to check the network tab in the browser debugger, understand what's going on and then start spoofing your requests. You can't sacrifice security for performance because you want to execute few query less.

StormPath groups authorization using express-stormpath

Using stormpath.groupsRequired middleware call,
router.get('/', stormpath.loginRequired, stormpath.groupsRequired(['org1-admin']), function (req, res) {
res.render('index', {});
});
I can not hardcode the ‘org1-admin’ role, what options do I have? If I put this into a session , the session is not available for middleware. Any thoughts?
The user role ‘org1-admin’ will be identified when the app is launched based on the org1 param passed in the initial launch request url and ‘admin’ role read from config entry.
After the initial launch , this role should be available for subsequent routes to authorize. Appreciate your feedback!
If the group to check is determined on a per-request basis, you’ll need to modify the flow to use the groupsRequired middleware more like a function:
app.get('/', stormpath.loginRequired, function (req, res) {
var group = 'foo'; // grab the group from your request context
stormpath.groupsRequired([group])(req,res,function(){
// If we got here, the user is in the group. Otherwise the groupsRequired middleware would have ended the response with 403
res.render('index', {});
});
});
I hope this helps! This is a good use-case and I’d like to add something to this library which makes it easier to do this.

redirect before loading URL

I'm developing a node.js app where I'm using passport to build OAuth authentication system. I can access the user through request object in each resource load after configurating it. But my question is: How can I do to check before every URL load - resources defined with app.get('/', function(..) {...}) - if user is loged and redirect the client if it's not loged. I could do it just adding a test in every method, but this is not what I want.
Thanks!
You want a middleware that checks whether the user is logged in.
isAuthenticated = function (req, res, next) {
if (req.user)
return next(); // All good, let the route handler process the request.
else
res.redirect('/login'); // Not logged in.
}
And to use it on every route that needs to be logged in:
app.get('/something', isAuthenticated, function (req, res) {
// Only in here if the user is authenticated.
});
You can also use the middleware on every route, by doing app.use(isAuthenticated), but you will need to have extra logic in the method to not create infinite redirect loops to /login, etc.

Group/rule-based authorization approach in node.js and express.js

What are good strategies for role-based authorization in express.js? Especially with express-resource?
With Express-resource there are no handlers, so I think there are three options:
Use a middleware
Pass the authorization function to the resource and check each resource request separately
Check authorization with every request right after authentication
Are there any other solutions?
Group/Role-based authorization is a pretty antique approach. Are there newer methods of access control? If not, how can role-based authorization be applied to node.js? Where to store group-rule relationships (with NoSQL/CouchDB/Redis)?
As an example, the structure:
/
/forums
/forums/threads
Each resource with index, new, create, show, edit update and destroy. Some people can edit/delete etc. threads and forums, some people shouldn't.
I would say that it's hard to solve this in a clean manner using express-resource, since it doesn't allow for route-specific middleware (at least not in a clean way).
I would opt for a similar layout as an express-resource module, but route it with plain old express. Something like this:
// Resource
var forum = {
index: // ...
show: // ...
create: // ...
update: // ...
destroy: // ...
};
// Middleware
var requireRole = function(role) {
return function(req, res, next) {
if('user' in req.session && req.session.user.role === role)
next();
else
res.send(403);
}
};
// Routing
app.get('/forums', forum.index);
app.get('/forums/:id', forum.show);
app.post('/forums', requireRole('moderator'), forum.create); // Only moderators can create forums
app.delete('/forums/:id', requireRole('admin'), forum.destroy); // Only admins can delete forums
UPDATE: There have been ongoing discussions regarding route-specific middleware in express-resource, e.g. here. The prevailing view seems to be to have an array per action, e.g.:
var forums = {
index: [ requireRole('foo'), function(req, res, next) { ... } ]
};
You could take a look through the pull requests and see if there is anything you could use. I totally understand it, of course, if you don't feel comfortable with that. I'm pretty sure we will see something like this in express-resource in the future.
The only other solution I can think of is along the lines of Jan Jongboom's answer, which would be to mount the resources with express-resource, but have middleware attached "outside" of that, something like:
app.delete('*', requireRole('admin')); // Only admins are allowed to delete anything
app.put('/forums/*', requireRole('moderator')); // Only moderators are allowed to update forums
But I regret that this leaks URLs all over the place.
I have been researching the same question and have come across a few good modules. I have been focusing on the node-acl package that can be found here. https://github.com/optimalbits/node_acl.
This package seems to have implemented the ACL pattern in a very understandable way and has provided ways to easily integrate it into your node/express application.
Firstly, you'll want to define your resources, roles, and permissions.
For example, the resources can be:
/
/forums
/forums/threads
The roles can be
public
admin
user
john
jane
In this example, the roles john and jane can map to actual user accounts, but they will inherit all the permissions of the user role.
The permissions on the resources
create
show
update
destroy
Or your standard CRUD operations.
Now that those have been defined, we can take a look at how it would look to set up the acl using node-acl. These notes are derived from the documentation
import the package
var acl = require('acl');
Set up your backend. My app is using mongodb, but the node-acl package does support other storage mechanisms
acl = new acl(new acl.mongodbBackend(dbInstance, prefix));
My app is using mongoose so dbInstance would be replaced with mongoose.connection.db
Now lets add our roles to the ACL. In node-acl, roles are created by giving them permissions. Its like killing two birds with one stone (no birds are actually harmed)
acl.allow('admin', ['/', '/forum', '/forum/threads'], '*');
acl.allow('public', ['/', '/forum', '/forum/threads'], 'show');
acl.allow('user', ['/', '/forum', '/forum/threads'], ['create', 'show']);
Lets assume a new resource is created by john, we will add a new record that allows john to also update and delete that resource.
acl.allow('john', ['/forum/threads/abc123'], ['update', 'delete']);
My application is also using express, so I will use the routing middleware approach to check routes. In my routing configuration, I would add the line
In most express configurations, this looks like for the pos
app.post('/', acl.middleware(), function(req, res, next) {...});
app.post('/forums', acl.middleware(), function(req, res, next) {...});
app.post('/forums/:forumId', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads/:threadId', acl.middleware(), function(req, res, next) {...});
When no parameters are passed, this will check if the role defined in req.userId is allowed to execute the http method on the resource identified but the route.
In this example the http method is post, but it will do the same thing for each http idenitified in your configuration.
This raises the question, about the permissions defined earlier. To answer those questions, we would have to change the permissions from
create
show
update
destroy
To the conventional
post
get
put
delete
Although this example shows everything hardcoded, the better practice is to have a management interface for your permissions so they can be created, read, updated, and deleted dynamically without having to modify your code.
I like the node-acl plugins approach as it allows for very fine grained permission-role assignments using a very straight forward and flexible api. There is a lot more in their documentation, my example shows were I am with the package.
Hopefully this helps.
Connect-roles is quite good, simple and the documentation is also very clear.
var user = roles;
app.get('/profile/:id', user.can('edit profile'), function (req, res) {
req.render('profile-edit', { id: req.params.id });
})
app.get('/admin', user.is('admin'), function (req, res) {
res.render('admin');
}
In express you can add a handler that hooks into every operator (http://expressjs.com/guide.html#passing-route control) where you can do precondition validation. Here you can retrieve the role for the user and restrict access based on the HTTP verb (PUT, DELETE, etc.) or the URL (param('op') is 'edit' or so).
app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req.user) {
next();
} else {
next(new Error('cannot find user ' + req.params.id));
}
});
I wrote a module as non-explicit routing middleware. Works well with express-routes.
Gandalf on GitHub
You can try Casbin: https://casbin.org/, it has a Node.js version. It also has a Express.js middleware called express-authz: https://casbin.org/docs/en/middlewares

Resources