Socket
Socket
Sign inDemoInstall

cansecurity

Package Overview
Dependencies
79
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.1 to 3.1.0

test/resources/rsa-private.pem

2

lib/sessionManager.js

@@ -301,3 +301,3 @@ /*global module, require, Buffer, console */

tokenlib.init( config.sessionKey || genRandomString( RANDOM_STRING_LENGTH ), encryptHeader );
tokenlib.init( {key: config.sessionKey || genRandomString( RANDOM_STRING_LENGTH ), encrypt: encryptHeader, privateKey: config.privateKey, publicKey: config.publicKey } );

@@ -304,0 +304,0 @@ return publicMethods;

const crypto = require('crypto'), jwt = require('jsonwebtoken'), now = require('./util').now;
let sessionKey = null, encryptHeader = false, warn = () => {};
let sessionKey = null, privKey = null, pubKey = null, encryptHeader = false, algorithm = null,
usePublic = false,
warn = () => {};
module.exports = {
init : (key, encrypt) => {
init : ({key = null, privateKey = null, publicKey = null, encrypt = false} = {}) => {
sessionKey = key;
encryptHeader = encrypt || false;
privKey = privateKey;
pubKey = publicKey;
encryptHeader = encrypt;
// which algorithm do we use?
usePublic = privKey || pubKey ? true : false;
algorithm = usePublic ? "RS256" : "HS256";
},

@@ -16,4 +23,3 @@ setWarn : (fn) => {

generate : (name, user, expiry) => {
const token = jwt.sign({sub:name,exp:expiry,"cs-user":user},sessionKey,{algorithm:"HS256"});
const token = jwt.sign({sub:name,exp:expiry,"cs-user":user},usePublic ? privKey : sessionKey,{algorithm:algorithm});
return(encryptHeader ? module.exports.cipher(token) : token);

@@ -31,3 +37,3 @@ },

try {
decoded = jwt.verify(token,sessionKey,{algorithms:"HS256"});
decoded = jwt.verify(token,usePublic ? pubKey : sessionKey,{algorithms:algorithm});
expiry = decoded.exp;

@@ -34,0 +40,0 @@ warn(`token expiry ${expiry} now ${t}`);

{
"name": "cansecurity",
"description": "cansecurity is your all-in-one security library for user authentication, authorization and management in node expressjs apps",
"version": "3.0.1",
"version": "3.1.0",
"license": "MIT",

@@ -6,0 +6,0 @@ "url": "http://github.com/deitch/cansecurity",

@@ -108,3 +108,5 @@ # cansecurity

* `sessionExpiry`: OPTIONAL. Integer in minutes how long sessions should last, default is `15`. Used both for expressjs sessions and CS sessions. Setting `sessionExpiry` will **only** affect how long a session is valid **for cansecurity**. It will **not** affect the underlying expressjs session itself.
* `sessionKey`: OPTIONAL. String. Secret key shared between nodejs servers to provide single-sign-on. This is a string. The default, if none is provided, is a random 64-character string. This is **required** if you want to take advantage of cansecurity's stateless sessions. Keep this very secret.
* `sessionKey`: OPTIONAL. String. Secret key shared between nodejs servers to provide single-sign-on.
* `privateKey`: OPTIONAL. String. PEM-encoded RSA private key to use to encrypt the token.
* `publicKey`: OPTIONAL. String. PEM-encoded RSA public key to use to validate the token.
* `validate`: REQUIRED. Function that will get a user by username, and possibly validate their password, asynchronously. For more details, see below.

@@ -116,2 +118,22 @@ * `encryptHeader`: OPTIONAL. With a value of true, the entire JWT is encrypted using `rc4-hmac-md5` algorithm.

##### Token Signing Keys
`cansecurity` supports both shared key token validation and public/private key token validation. Which it uses depends on what parameters you pass:
* `sessionKey`: shared session key using `"HS256"` algorithm.
* `privateKey` / `publicKey`: public/private key using `"RS256"` algorithm.
* none of the above: will automatically generate a shared session key, a random 64-character string.
Because the default, if no option is provided, is to auto-generate a shared session key, you **must** provide _either_ a public/private key pair _or_ a session if you want to share tokens between servers.
The behaviour of `cansecurity` changes based on which parameters you provide:
* No `sessionKey`, `publicKey` or `privateKey`: auto-generate a random shared session key, as described above.
* Only `sessionKey`: sign and validate tokens using provided session key with `"HS256"` algorithm.
* Only `privateKey`: sign tokens using provided private key with `"RS256"` algorithm. **Any attempt to validate tokens will fail.**
* Only `publicKey`: validate tokens using provided public key with `"RS256"` algorithm. **Any attempt to sign tokens will fail.**
* Both `privateKey` and `publicKey`: sign and validate tokens using provided private and public keys with `"RS256"` algorithm.
* `sessionKey` and either `publicKey` or `privateKey`: launch-time error.
Note that encrypted headers do not yet work with private/public keys, as they rely on the same session key to encrypt.
#### Validation

@@ -118,0 +140,0 @@ Validation is straightforward. Once you have set up cansecurity properly, it functions as standard expressjs middleware:

@@ -33,4 +33,4 @@ /*jslint node:true, nomen:true, unused:vars */

module.exports = {
init: function () {
return cs.init( {
init: function (param) {
return cs.init( Object.assign({
validate: function ( login, pass, callback ) {

@@ -66,86 +66,9 @@ var found = null;

}
},
sessionKey: SESSIONKEY
} );
}
}, param || {}) );
},
initEncrypted: function () {
return cs.init( {
validate: function ( login, pass, callback ) {
var found = null;
// search for our user
_.each( user, function ( val, key ) {
var ret = true;
if ( val.name === login ) {
found = val;
ret = false;
}
return ( ret );
} );
if ( !found ) {
callback( false, null, "invaliduser" );
} else if ( pass === undefined ) {
callback( true, found, found.name, found.pass );
} else if ( pass === found.pass ) {
callback( true, found, found.name, found.pass );
} else {
callback( false, null, "invalidpass" );
}
},
loader: {
group: function ( req, res, next ) {
req.cansecurity.item = 1;
next();
}
},
sessionKey: SESSIONKEY,
encryptHeader: true
} );
},
initTokenLib: function ( encrypt ) {
tokenLib.init(SESSIONKEY, encrypt || false);
tokenLib.init({key: SESSIONKEY, encrypt: encrypt || false});
return tokenLib;
},
initLegacy: function () {
return cs.init( {
getUser: function ( login, success, failure ) {
var found = null;
// search for our user
_.each( user, function ( val, key ) {
var ret = true;
if ( val.name === login ) {
found = val;
ret = false;
}
return ( ret );
} );
if ( found ) {
success( found, found.name, found.pass );
} else {
failure();
}
},
validatePassword: function ( login, pass, cb ) {
var p = null,
message = "invaliduser",
resuser = null;
// search for our user
_.each( user, function ( val, key ) {
var ret = true;
if ( val.name === login ) {
ret = false;
if ( val.pass === pass ) {
message = null;
resuser = val;
p = pass;
} else {
message = "invalidpass";
}
}
return ( ret );
} );
cb( resuser, message, p );
},
sessionKey: SESSIONKEY
} );
}
};
};

@@ -337,3 +337,3 @@ /*jslint node:true, nomen:true, unused:vars */

app = express();
app.use(cookieParser());
app.use(cookieParser());
app.use(session({secret: "agf67dchkQ!",resave:false,saveUninitialized:false}));

@@ -359,3 +359,1 @@ app.use(cansec.validate);

});

@@ -110,3 +110,3 @@ /*jslint node:true, unused:vars */

before( function () {
cansec = cs.initEncrypted();
cansec = cs.init({encryptHeader: true});
app = express();

@@ -128,3 +128,3 @@ app.use( cookieParser() );

before( function () {
cansec = cs.initEncrypted();
cansec = cs.init({encryptHeader: true});
app = restify.createServer();

@@ -140,2 +140,2 @@ app.use( cansec.validate );

});
} );
} );
/*jslint node:true, unused:vars */
/*global before,it,describe */
var express = require( 'express' ), restify = require('restify'),
fs = require('fs'),
path = require('path'),
jwt = require('jsonwebtoken'),

@@ -9,2 +11,4 @@ app,

cs = require( './resources/cs' ),
privKey = fs.readFileSync(path.join(__dirname,'resources/rsa-private.pem')),
pubKey = fs.readFileSync(path.join(__dirname,'resources/rsa-public.pem')),
cookieParser = require('cookie-parser'),

@@ -30,7 +34,7 @@ session = require('express-session'),

decoded = jwt.decode(match[2]);
// take JWT (match[2]), split on '.', base64 decode 2nd part (claims),
// take JWT (match[2]), split on '.', base64 decode 2nd part (claims),
// check that the 'cs-user' claim is identical to userInfo
return decoded["cs-user"] === userInfo;
},
path = "/public",
path = "/public",
alltests = function () {

@@ -56,3 +60,3 @@ it( 'should reject invalid token', function ( done ) {

var user = "john",
token = tokenlib.generate( user, "1234", now() + 15 * 60 );
token = tokenlib.generate( user, "1234", now() + 15 * 60 );
async.waterfall( [

@@ -93,14 +97,46 @@

}
], done );
], done );
} );
};
describe( 'authtoken', function () {
describe('express', function(){
describe('sessionKey', function() {
describe('express', function(){
before( function () {
cansec = cs.init();
app = express();
app.use( cookieParser() );
app.use( session( {
secret: "agf67dchkQ!",resave:false,saveUninitialized:false
} ) );
app.use( cansec.validate );
app.get( path, function ( req, res, next ) {
// send a 200
require('../lib/sender')(res,200);
} );
r = request( app );
} );
alltests();
});
describe('restify', function(){
before( function () {
// we need to handle the mess that restify creates
// we create a prototype chain for http.IncomingMessage, so when restify changes it, it changes the new middle layer,
// which we can restore
cansec = cs.init();
app = restify.createServer();
app.use( cansec.validate );
app.get( path, function ( req, res, next ) {
// send a 200
require('../lib/sender')(res,200);
} );
r = request( app );
} );
alltests();
});
});
describe('publicKey', function() {
before( function () {
cansec = cs.init();
cansec = cs.init({privateKey: privKey, publicKey: pubKey});
app = express();
app.use( cookieParser() );
app.use( session( {
secret: "agf67dchkQ!",resave:false,saveUninitialized:false
} ) );
app.use( cansec.validate );

@@ -114,19 +150,22 @@ app.get( path, function ( req, res, next ) {

alltests();
});
describe('restify', function(){
before( function () {
// we need to handle the mess that restify creates
// we create a prototype chain for http.IncomingMessage, so when restify changes it, it changes the new middle layer,
// which we can restore
cansec = cs.init();
app = restify.createServer();
app.use( cansec.validate );
app.get( path, function ( req, res, next ) {
// send a 200
require('../lib/sender')(res,200);
describe('mismatched keys', function() {
before( function () {
cansec = cs.init({privateKey: privKey, publicKey: "abcdefg"});
app = express();
app.use( cookieParser() );
app.use( cansec.validate );
app.get( path, function ( req, res, next ) {
// send a 200
require('../lib/sender')(res,200);
} );
r = request( app );
} );
r = request( app );
} );
alltests();
it( 'should reject mismatched token', function ( done ) {
var user = "john",
expiry = now() + 15 * 60,
token = tokenlib.generate( user, "1234", expiry );
r.get( path ).set( "Authorization", "Bearer "+token ).expect( 401 ).expect( authHeader, 'error invalidtoken', done );
} );
});
});
} );
} );
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc