UNPKG

authorify

Version:

Authorization and authentication system for REST server

380 lines (368 loc) 15.5 kB
<!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' &amp;&amp; password === 'password') { * callback(1, ['admin']); * } else if (username === 'user' &amp;&amp; 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>