@webgap/authorization-utils
Version:
WebGAP authorization module for express routes using Role-based Access Control - RBAC.
118 lines (110 loc) • 3.64 kB
JavaScript
/**
* (C) Copyright 2014 WebGAP (http://www.webgap.eu/).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Created by: ManuelMartins
* Created on: 07-08-2014
*
*/
;
var Roles = require('./lib/Roles');
var notifier = require('@webgap/notifier');
/**
* Express.js Middleware
* Handles authorization on express routes using Role-based Access Control - RBAC
*
* Built to use with Passport. 'req._passport.session.user' is expected
*
* A user must contain a list of roles. A set of Roles is available Notifier.Role: USER, PROVIDER, ADMIN
*
* Usage:
* router.get('/admin', isAuthorized(['admin']), function (req, res) {
* res.render('backend/admin/admin.html', template.generate(req));
* });
*
* @param {Object} options
* @param {Object} options.notifier
* @param {string} options.unauthorizedURL defaults to '/unauthorized'
* @param {string} options.loginURL defaults to '/auth/login'
* @param {string} options.unauthenticatedMessageKey defaults to 'messages.warning.authentication-required'
* @param {string} options.unauthorizedMessageKey defaults to 'messages.error.authorization-required'
* @constructor
*/
function Authorizator(options) {
options = options || {};
this.notifier = options.notifier || notifier;
this.unauthorizedURL = options.unauthorizedURL || '/unauthorized';
this.loginURL = options.loginURL || '/auth/login';
this.unauthenticatedMessageKey = options.unauthenticatedMessageKey || 'messages.warning.authentication-required';
this.unauthorizedMessageKey = options.unauthorizedMessageKey || 'messages.error.authorization-required';
}
/**
* Checks whether a user with a specific role is authorized or not to access a route suitable for Expressjs
*
* @param roles
*/
Authorizator.prototype.isAuthorized = function isAuthorized(roles) {
var self = this;
return function authorizationMiddleware(req, res, next) {
if (!req._passport.session || !req._passport.session.user) {
return handleRedirect(req, res, notifier, self.unauthenticatedMessageKey, self.loginURL);
}
else if (!self.hasAccess(req.user, roles)) {
return handleRedirect(req, res, notifier, self.unauthorizedMessageKey, self.unauthorizedURL);
}
else {
return next();
}
};
};
/**
* Hanldles redirect on error
*
* @param {object} req
* @param {object} res
* @param {object} notifier
* @param {string} messageKey
* @param {string} url
*
*/
function handleRedirect(req, res, notifier, messageKey, url) {
notifier.notify({
notification: {
request: req,
message: messageKey
}
}, function afterNotify(err) {
if (err) {
console.warn('Notifier module error. \n%s', err);
}
res.redirect(url);
});
}
/**
* Returns true if an User has a specific role or roles
*
* @param user
* @param roles
* @returns {boolean}
*/
Authorizator.prototype.hasAccess = function hasAccess(user, roles) {
if (!roles || !user || !user.roles) {
return false;
}
return roles.some(function(element) {
return user.roles.indexOf(element) >= 0;
});
};
module.exports = Authorizator;
module.exports.Role = Roles;