License MIT - Copyright Nicolas Chambrier [email protected]
- You can use this module with Express or any other Connect-based application
- You'll find an application middleware to configure access control layer
- You'll be able to globally protect a list of paths in your application, or...
- ... protect any action, one by one, using the route middleware
From NPM (easiest and best way):
npm install connect-access-control
From Git (if you want to contribute, or get a dev version):
git clone http://github.com/naholyr/connect-access-control.git node_modules/connect-access-control
Load the middleware:
var accessControl = require('connect-access-control');
Enable access control in your application:
app.use(accessControl(options));
If you use default retrieve and save options, you must have enabled session support before enabling access control:
app.use(connect.middleware.session(...));
app.use(accessControl(...));
The middleware will populate request with a new key "user" (see option reqKey to customize this). req.user will provide the following methods:
grant(roles, callback)add role(s) to user, and call callback() after credentials are savedrevoke(roles, callback)remove role(s) from user, and call callback() after credentials are savedrevokeAll(callback)remove all roles from user, and call callback() after credentials are savedisSuperAdmin()checks if user has a super-admin rolegetRoles()returns the list of user's roleshas(roles)checks if user matches the given combination of roles (see "Checking roles")login(callback)marks user as logged in, retrieve his initial roles (see optioninitialize), and call callback() after credentials are savedlogout(callback)marks user as logged out, and call callback() after credentials are savedisLoggedIn()checks if user has been marked as logged in
Global options:
accessControl.securedPathslist of automatically secured paths (called "global protection"), each one can be a string (exact path) or a regular expressionaccessControl.requiredLoggedInset to true if global protection should require to be logged inaccessControl.requiredRolesroles that must be required for globally protected pagesaccessControl.ignoredPathslist of paths that won't trigger the access control (noreq.usercreated), each one can be a string (exact path) or a regular expressionaccessControl.superAdminlist the roles that will be considered as super-admin rolesaccessControl.limitedAccessCallbackwill be called for secured pages with required roles that are not matched (function(req,res,next))accessControl.notLoggedInCallbackwill be called for secured pages requiring logged in user (function(req,res,next))accessControl.loginPaththe defaultnotLoggedInCallbackwill redirect to this pathaccessControl.initializewill retrieve initial roles from user as soon as he logs in (function(req,callback), wherecallbackisfunction(roles or null if nothing loaded)), default does not initialize anythingaccessControl.retrievewill retrieve current roles for user (function(req,callback)wherecallbackisfunction(loggedin,roles)), default will retrieve from sessionaccessControl.savewill save current roles from user (function(req,loggedin,roles,callback)) wherecallbackisfunction()), default will save to sessionaccessControl.reqKeywill allow you to customize how req will be populated, default is "user" to create areq.userobject
Instance options:
ignoredPathswill be merged with global optionignoredPathssecuredPathswill be merged with global optionsecuredPathsrequiredLoggedInwill replace global optionrequiredLoggedInrequiredRoleswill replace global optionrequiredRolessuperAdminwill be merged with global optionsuperAdmininitializewill replace global optioninitializeretrievewill replace global optionretrievesavewill replace global optionsave
Globally (this is not the best way in my opinion, but maybe the easiest at beginning):
// Global protection
accessControl.securedPaths.push('/private');
// Globally protected pages require login
accessControl.requiredLoggedIn = true;
// Globally protected pages require role "authorized"
accessControl.requiredRoles.push("authorized");
Per page:
// Require logged in
app.get('/private', accessControl.secure(true), function (req, res) { ... });
// Require role "admin" or "moderator"
app.get('/moderate', accessControl.secure([["admin", "moderator"]]), function (req, res) { ... });
Look at the sample Express application provided in the sample directory.
The way roles are required is directly inspired by symfony's credentials system. You can imbricate arrays to alternate AND and OR operations.
Here are some examples that will explain this system more easily than the full explanation ;)
["role1", "role2] role1 AND role2
[["role1", "role2"]] role1 OR role2
["role1", ["role2", "role3"]] role1 AND (role2 OR role3)
["role1", ["role2", ["role3", "role4"]]] role1 AND (role2 OR (role3 AND role4))
As you see, the first level of array = AND operation, then each time you add a level you alternate: OR, then AND, then OR, etc...
With this simple system you can declare any complex combinations of roles to secure your pages.
1.0.02011-07-30: Initial release