authorify
Version:
Authorization and authentication system for REST server
380 lines (368 loc) • 15.5 kB
HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
<style type="text/css">
.highlight { display: block; background-color: #ddd; }
</style>
<script type="text/javascript">
function highlight() {
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
}
</script>
</head>
<body onload="prettyPrint(); highlight();">
<pre class="prettyprint lang-js"><span id='node_modules-authorify'>/**
</span> * This is an authentication and authorization middleware for a REST server with data encryption and signing.
* You can use it with [restify][1] or other server compatible with a generic middleware: `function (req, res, next) {...}`.
* See more details in README file.
*
* @class node_modules.authorify
* @uses node_modules.authorify.authentication
* @uses node_modules.authorify.authorization
*
* @author Marcello Gesmundo
*
* # License
*
* Copyright (c) 2012-2014 Yoovant by Marcello Gesmundo. All rights reserved.
*
* This program is released under a GNU Affero General Public License version 3 or above, which in summary means:
*
* - You __can use__ this program for __no cost__.
* - You __can use__ this program for __both personal and commercial reasons__.
* - You __do not have to share your own program's code__ which uses this program.
* - You __have to share modifications__ (e.g bug-fixes) you've made to this program.
* - For more convoluted language, see the LICENSE file.
*
* [1]: http://mcavage.me/node-restify
*
*/
module.exports = function(app) {
'use strict';
// dependencies
var _ = require('underscore'),
fs = require('fs'),
async = require('async'),
path = require('path'),
forge = require('node-forge'),
math = require('mathjs');
// namespace
var my = {};
my.config = {
<span id='global-property-name'> /**
</span> * @ignore
* @private
*/
name: 'authorify',
<span id='node_modules-authorify-cfg-logger'> /**
</span> * @cfg {Object} [logger = console] The logger. It MUST have
* log, error, warn, info, debug methods
*/
logger: console, // for best logging please use winston: npm install winston
<span id='node_modules-authorify-cfg-debug'> /**
</span> * @cfg {Boolean} debug=true true to enable verbose log
*/
debug: false,
<span id='node_modules-authorify-cfg-persist'> /**
</span> * @cfg {Boolean} persist=false Persistence of token
* If persist is false, the token (and it's session) will expire after the tokenTtl config.
* If persist is true, the token will never expire and tokenTtl config will be ignored.
*/
persist: false,
<span id='node_modules-authorify-cfg-sidTtl'> /**
</span> * @cfg {Integer} sidTtl=300 The time to live for the handshake and authentication session in seconds
*/
sidTtl: 300, // 5min
<span id='node_modules-authorify-cfg-tokenTtl'> /**
</span> * @cfg {Integer} tokenTtl=3600 The time to live for the token and it's authorized session in seconds
*/
tokenTtl: 3600, // 60min
<span id='node_modules-authorify-cfg-sidLength'> /**
</span> * @cfg {Integer} sidLength=40 The number of characters to create the session ID.
*/
sidLength: 40,
<span id='node_modules-authorify-cfg-connection'> /**
</span> * @cfg {connection} connection REDIS connection information
* @cfg {Number} connection.port=6379 REDIS port
* @cfg {String} connection.host='127.0.0.1' REDIS host
* @cfg {String} [connection.db] REDIS database for sessions
* @cfg {String} [connection.user] REDIS user
* @cfg {String} [connection.pass] REDIS password
*/
connection: {
port: 6379,
host: '127.0.0.1',
db : 'session',
user: undefined,
pass: undefined
},
<span id='node_modules-authorify-cfg-crypto'> /**
</span> * @cfg {Object} crypto=node-forge Cryptographic engine
*/
crypto: forge,
<span id='node_modules-authorify-cfg-cert'> /**
</span> * @cfg {String} cert The server X.509 certificate in pem format
*/
cert: fs.readFileSync(path.join(__dirname,'cert/serverCert.cer'), 'utf8'),
<span id='node_modules-authorify-cfg-key'> /**
</span> * @cfg {String} key The server private RSA key in pem format
*/
key: fs.readFileSync(path.join(__dirname,'cert/serverCert.key'), 'utf8'),
<span id='node_modules-authorify-cfg-ca'> /**
</span> * @cfg {String} ca The Certification Authority certificate in pem format
*/
ca: fs.readFileSync(path.join(__dirname,'cert/serverCA.cer'), 'utf8'),
<span id='node_modules-authorify-cfg-sessionStore'> /**
</span> * @cfg {Object} sessionStore The store for the sessions
*/
sessionStore: undefined,
<span id='node_modules-authorify-cfg-SECRET'> /**
</span> * @cfg {String} SECRET The secret key used in hash operations
*/
SECRET: 'secret', // use your own SECRET!
<span id='node_modules-authorify-cfg-SECRET_CLIENT'> /**
</span> * @cfg {String} SECRET_CLIENT The key used in conjunction with SECRET to verify handshake token. This key must be the same on both the server and the client.
*/
SECRET_CLIENT: 'secret_client', // use your own SECRET_CLIENT,
<span id='node_modules-authorify-cfg-SECRET_SERVER'> /**
</span> * @cfg {String} SECRET_SERVER The key used in conjunction with SECRET to create authorization token
*/
SECRET_SERVER: 'secret_server', // use your own SECRET_SERVER
<span id='node_modules-authorify-cfg-encryptedBodyName'> /**
</span> * @cfg {String} encryptedBodyName = 'ncryptdbdnm' The property name for the encrypted body value
*/
encryptedBodyName: 'ncryptdbdnm',
<span id='node_modules-authorify-cfg-encryptedSignatureName'> /**
</span> * @cfg {String} encryptedSignatureName = 'ncryptdsgnnm' The property name for the signature value of the body
*/
encryptedSignatureName: 'ncryptdsgnnm',
<span id='node_modules-authorify-cfg-signBody'> /**
</span> * @cfg {Boolean} signBody = true Sign the body when it is sent encrypted
*/
signBody: true,
<span id='node_modules-authorify-cfg-encryptQuery'> /**
</span> * @cfg {Boolean} encryptQuery = true Encrypt the values in url query string
*/
encryptQuery: true,
<span id='node_modules-authorify-cfg-authHeader'> /**
</span> * @cfg {String} authHeader='Authorization' The header used for authentication and authorization
*/
authHeader: 'Authorization',
<span id='node_modules-authorify-cfg-handshakePath'> /**
</span> * @cfg {String} handshakePath='/handshake' The route exposed by the server for the handshake phase
*/
handshakePath: '/handshake',
<span id='node_modules-authorify-cfg-authPath'> /**
</span> * @cfg {String} authPath='/auth' The route exposed by the server for the authentication/authorization phases
*/
authPath: '/auth',
<span id='node_modules-authorify-cfg-logoutPath'> /**
</span> * @cfg {String} logoutPath='/logout' The route exposed by the server for the logout
*/
logoutPath: '/logout',
<span id='node_modules-authorify-cfg-clockSkew'> /**
</span> * @cfg {Integer} clockSkew=0 Max age (in seconds) of the request/reply.
* Every request must have a valid response within clockSkew seconds.
* Note: you must enable a NTP server both on client and server. Set 0 to disable date check or 300 like Kerberos.
*/
clockSkew: 0,
<span id='node_modules-authorify-cfg-login'> /**
</span> * The login handler. You MUST define your own login strategy.
*
* ## Example
*
* var fs = require('fs'),
* authorify = require('auhtorify')({
* key: fs.readFileSync('serverCert.key'), 'utf8'),
* cert: fs.readFileSync('serverCert.cer'), 'utf8'),
* ca: fs.readFileSync('serverCA.cer'), 'utf8'),
* login: function(id, app, username, password, callback) {
* // manage id and app as your needs
* if (username === 'username' && password === 'password') {
* callback(1, ['admin']);
* } else if (username === 'user' && password === 'pass') {
* callback(2, ['user']);
* } else {
* callback(new Error('user and/or password wrong'));
* }
* }
* });
*
* @cfg {Function} login
* @param {String} id The id (uuid) assigned to the client
* @param {String} app The app (uuid) assigned to the application that the client want to use
* @param {String} username The username for the browser login
* @param {String} password The password for the browser login
* @param {Function} callback Function called when the identifier is created
* @return {callback(err, userId, admins)} The callback to execute as result
* @param {String/Error} callback.err Error if occurred
* @param {String} callback.userId The user identifier
* @param {String/Array} callback.admins The role/s of the user
*
*/
login: function(id, app, username, password, callback) {
throw new Error('you must implement your own login method');
},
<span id='node_modules-authorify-cfg-freeRoutes'> /**
</span> *
* Enable routes without Authorization header. When false the authorization header is mandatory for every route even if the route does not have a specific authorization. Set true to try to manage a route if it does not have an authorization handler.
*
* ## Example 1
*
* // dependencies
* var restify = require('restify'),
* authorify = require('auhtorify')({
* freeRoutes: true
* // other options
* });
*
* // create the server
* var server = restify.createServer();
*
* // add middlewares
* server.use(restify.queryParser({ mapParams: false }));
* server.use(restify.bodyParser());
* server.use(authorify.authentication);
*
* // last route handler
* var ok = function(req, res, next){
* res.send({ success: true });
* };
*
* // routes
* // in the route below 'ok' can handled if the request is with or without the Authorization header
* server.get('/free', ok);
* // in the route below if the request doesn't have the Authorization header, the sec.isLoggedIn()
* // handler is performed, but fails and the 'ok' handler isn't reached
* server.get('/secure', sec.isLoggedIn(), ok);
*
* ## Example 2
*
* // dependencies
* var restify = require('restify'),
* authorify = require('auhtorify')({
* freeRoutes: false
* // other options
* });
*
* // create the server
* var server = restify.createServer();
*
* // add middlewares
* server.use(restify.queryParser({ mapParams: false }));
* server.use(restify.bodyParser());
* server.use(authorify.authentication);
*
* // last route handler
* var ok = function(req, res, next){
* res.send({ success: true });
* };
*
* // routes
* // in the route below 'ok' can handled only if the request has the Authorization header
* server.get('/free', ok);
* // in then route below if the request doesn't have the Authorization header, the sec.isLoggedIn() handler
* // isn't reached and the request fails; if the request have the Authorization header but the user
* // isn't logged, the 'ok' handler ins't performed (e.g.: session expired)
* server.get('/secure', sec.isLoggedIn(), ok);
*
*
* @cfg {Boolean} freeRoutes=true
*
*/
freeRoutes: true,
<span id='node_modules-authorify-cfg-userIdFieldName'> /**
</span> * The field name used for the user identifier into the routes.
*
* ## Example
*
* var restify = require('restify'),
* authorify = require('auhtorify')({
* userIdFieldName: 'myuser'
* // other options
* });
* server.get('/secure/user/:myuser', sec.isSelf(), ok);
*
*
* @cfg {String} userIdFieldName='user'
*/
userIdFieldName: 'user'
};
// merge app.config with default config
app.config = _.extend(my.config, app.config);
app.name = app.config.name;
if (!app.config.sessionStore) {
app.config.sessionStore = require('restify-session')({
ttl: app.config.sidTtl,
persist: false,
debug: app.config.debug,
logger: app.config.logger,
sidLength: app.config.sidLength,
connection: app.config.connection
});
}
app._ = _;
app.async = async;
app.config.sessionStore.name = app.name + ' session store';
app.sessionStore = app.config.sessionStore;
app.mathParser = math().parser();
app.logger = app.config.logger;
app.client = require('authorify-client')(app.config);
<span id='node_modules-authorify-method-load'> /**
</span> * Load a plugin module to add some functionality.
*
* ## Example
*
* var authorify = require('auhtorify')({
* // add your options
* });
* authorify.load('pluginname', 'shortname', opts); // opts is an optional object to configure the plugin
* var loadedPlugin = authorify.plugin['shortname'];
* // below you can use all methods/properties exported by the plugin (loadedPlugin)
*
* @param {String} name The name of the plugin. THe plugin must be installed into the
* application folder that uses the authorify module.
* @param {String} [shortname] An optional short name for the plugin loaded as property in the root application
* (authorify.plugin['shortname']).
* @param {Object} [opts] The options required by the plugin.
*/
app.load = function(name, shortname, opts) {
if (_.isObject(shortname)) {
opts = shortname;
shortname = name;
} else if (!shortname) {
shortname = name;
}
opts = opts || {};
app.plugin = app.plugin || {};
var plugin = require(name)(app, opts);
if (plugin) {
app.logger.info('%s plugin %s loaded with name %s', app.name, name, shortname);
app.plugin[shortname] = plugin;
}
};
app.logger.info('%s setup completed', app.name);
return app;
};
<span id='node_modules-authorify-property-authentication'>/**
</span> * {@link node_modules.authorify.authentication The authentication middleware.}
*
* @property {function (req, res, next)} authentication
* @param {IncomingMessage} req Request
* @param {ServerResponse} res Response
* @param {Function} next The callback
* @param {Error} next.err The error instance if occurred
*/
<span id='node_modules-authorify-property-authorization'>/**
</span> * {@link node_modules.authorify.authorization The authorization middleware.}
*
* @property {Object} authorization
*
*/
</pre>
</body>
</html>