Skip to content

Commit

Permalink
copied basic browserid framework for wsapis; session_context
Browse files Browse the repository at this point in the history
  • Loading branch information
jedp committed Aug 28, 2012
1 parent 0915ac3 commit 289a5df
Show file tree
Hide file tree
Showing 14 changed files with 461 additions and 11 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# default var/ dir
var/

# vim ancillary files
*.un~
*~
*.swp
*.swo

Expand All @@ -8,6 +11,7 @@

# locally installed node modules
node_modules
npm-debug.log
.gitmodules

# awsbox setup notes
Expand Down
18 changes: 11 additions & 7 deletions server/bin/app → idp/bin/app
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@

/**
* Module dependencies.
*/
#!/usr/bin/env node
/* -*- mode: js2 -*- */

var express = require('express'),
http = require('http'),
path = require('path');
path = require('path'),
wsapi = require('../lib/wsapi'),
logger = require('../lib/logging').logger,
configuration = require('../lib/configuration');

var app = express();

app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('port', configuration.get('bind_to').port);
app.set('views', path.join(__dirname, '../views'));
app.set('view engine', 'jade');
app.use(express.favicon());
Expand All @@ -29,6 +30,9 @@ app.get('/', function(req, res) {
res.render('index', {title: 'w00t'});
});

// handle wsapi requests
wsapi.setup({}, app);

http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
logger.info("IdP server listening on port " + app.get('port'));
});
32 changes: 32 additions & 0 deletions idp/lib/configuration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const path = require('path'),
convict = require('convict');

var conf = module.exports = convict({
bind_to: {
host: {
doc: "The ip address the server should bind",
format: 'string = "127.0.0.1"',
env: 'IP_ADDRESS'
},
port: {
doc: "The port the server should bind",
format: 'integer{1,65535} = 3000',
env: 'PORT'
}
},

process_type: 'string',

authentication_duration_ms: {
doc: "How long a user may stay signed in",
format: 'integer = 2419200000'
},

var_path: {
doc: "Path where deployment-specific resources live (keys, logs, etc.)",
format: 'string = "var"',
env: 'VAR_PATH'
}
});

conf.set('process_type', path.basename(process.argv[1], ".js"));
45 changes: 45 additions & 0 deletions idp/lib/httputils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// various little utilities to make crafting boilerplate responses
// simple

function sendResponse(resp, content, reason, code) {
if (content) {
if (reason) content += ": " + reason;
} else if (reason) {
content = reason;
} else {
content = "";
}
resp.send(content, {"Content-Type": "text/plain"}, code);
}

exports.notFound = function(resp, reason) {
sendResponse(resp, "Not Found", reason, 404);
};

exports.serverError = function(resp, reason) {
sendResponse(resp, "Server Error", reason, 500);
};

exports.serviceUnavailable = function(resp, reason) {
sendResponse(resp, "Service Unavailable", reason, 503);
};

exports.authRequired = function(resp, reason) {
sendResponse(resp, "Authentication Required", reason, 401);
};

exports.badRequest = function(resp, reason) {
sendResponse(resp, "Bad Request", reason, 400);
};

exports.forbidden = function(resp, reason) {
sendResponse(resp, "Forbidden", reason, 403);
};

exports.throttled = function(resp, reason) {
sendResponse(resp, "Too Many Requests", reason, 429);
};
38 changes: 38 additions & 0 deletions idp/lib/logging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Wrapper around winston for general server logging
*/

const winston = require('winston'),
configuration = require('./configuration'),
path = require('path'),
utils = require('./utils'),
LOG_DIR = path.join(configuration.get('var_path'), 'log'),
LOG_FILEPATH = path.join(LOG_DIR, configuration.get('process_type') + '.log');

// ensure log dir exists
utils.mkdir_p(LOG_DIR);

exports.logger = new(winston.Logger)({
transports: [new (winston.transports.File)({
timestamp: function() { return new Date().toISOString(); },
filename: LOG_FILEPATH,
colorize: true,
handleExceptions: true
})]
});

exports.enableConsoleLogging = function() {
exports.logger.add(
winston.transports.Console,
{
colorize: true,
handleExceptions: true
}
);
};

if (process.env.LOG_TO_CONSOLE) {
exports.enableConsoleLogging();
}

exports.logger.exitOnError = false;
118 changes: 118 additions & 0 deletions idp/lib/secrets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

const path = require('path'),
fs = require('fs'),
jwcrypto = require('jwcrypto'),
Buffer = require('buffer').Buffer,
crypto = require('crypto');

// make this async capable
function bytesToChars(buf) {
var str = "";
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

// yes, we are biasing the output here a bit.
// I'm ok with that. We can improve this over time.
for (var i=0; i < buf.length; i++) {
str += alphabet.charAt(buf[i] % alphabet.length);
}

return str;
}

exports.generate = function(chars, cb) {
if (cb) {
crypto.randomBytes(chars, function(ex, buf) {
cb(bytesToChars(buf));
});
} else {
return bytesToChars(crypto.randomBytes(chars));
}
};

// we don't bother to make this async, cause it's not needed
exports.weakGenerate = function(chars) {
var str = "";
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

for (var i=0; i < chars; i++) {
str += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
}

return str;
};

// functions to set defaults

// default key name is 'root'
function checkName(name) {
return name ? name : 'root';
}

// default directory is the var dir.
function checkDir(dir) {
return dir ? dir : require('./configuration').get('var_path');
}

exports.hydrateSecret = function(name, dir) {
dir = checkDir(dir);
var p = path.join(dir, name + ".sekret");
var secret = undefined;

try{ secret = fs.readFileSync(p).toString(); } catch(e) {};

if (secret === undefined) {
secret = exports.generate(128);
fs.writeFileSync(p, '');
fs.chmodSync(p, 0600);
fs.writeFileSync(p, secret);
}
return secret;
};

exports.loadSecretKey = function(name, dir) {
name = checkName(name);
dir = checkDir(dir);
var p = path.join(dir, name + ".secretkey");
var secret = undefined;

// may throw
secret = fs.readFileSync(p).toString();

if (secret === undefined) {
return null;
}

// parse it
return jwcrypto.loadSecretKey(secret);
};

function readAndParseCert(name, dir) {
name = checkName(name);
dir = checkDir(dir);
var p = path.join(dir, name + ".cert");
var cert = undefined;

// may throw
cert = fs.readFileSync(p).toString();

if (cert === undefined) {
return null;
}

// parse it
// it should be a JSON structure with alg and serialized key
// {alg: <ALG>, value: <SERIALIZED_KEY>}
var payloadSegment = jwcrypto.extractComponents(cert).payloadSegment;
return JSON.parse(new Buffer(payloadSegment, 'base64').toString());
}

exports.publicKeyCreationDate = function(name, dir) {
return new Date(readAndParseCert(name, dir).iat);
};

exports.loadPublicKey = function(name, dir) {
return jwcrypto.loadPublicKey(JSON.stringify(readAndParseCert(name, dir)['public-key']));
};
17 changes: 17 additions & 0 deletions idp/lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const fs = require('fs'),
path = require('path');

var existsSync;
// existsSync moved from path to fs in 0.8.x
if (typeof fs.existsSync === 'function') {
existsSync = fs.existsSync;
} else {
existsSync = path.existsSync;
}

var mkdir_p = module.exports.mkdir_p = function mkdir_p(dir) {
if (!existsSync(dir)) {
mkdir_p(path.dirname(dir));
fs.mkdirSync(dir, "0755");
}
};
Loading

0 comments on commit 289a5df

Please sign in to comment.