Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add better auth, a new substack module, and remove the useless mount …

…middleware

Change-Id: I5e27cf485dd9d0d6592dee730ac86048accb21db
  • Loading branch information...
commit 25dbafb1fdf12e86a4e7a18ba3642e76f4456b23 1 parent 14c347c
@creationix authored
Showing with 95 additions and 40 deletions.
  1. +48 −27 auth.js
  2. +0 −12 mount.js
  3. +1 −1  package.json
  4. +46 −0 substack.js
View
75 auth.js
@@ -1,32 +1,53 @@
-/*global Buffer*/
-var Crypto = require('crypto'),
- Url = require('url');
+// Based loosly on basicAuth from Connect
+// Checker takes username and password and returns a user if valid
+// Will force redirect if requested over HTTP instead of HTTPS
+module.exports = function basicAuth(checker, realm) {
-module.exports = function setup(match, secrets) {
- return function handle(req, res, next) {
- if (!req.hasOwnProperty("uri")) { req.uri = Url.parse(req.url); }
- if (!match.test(req.uri.pathname)) {
- return next();
- }
- if (req.client.remoteAddress !== '127.0.0.1') {
- res.writeHead(302, {"Location": "https://" + req.headers.host + req.url});
+ realm = realm || 'Authorization Required';
+
+ function unauthorized(res) {
+ res.writeHead(401, {
+ 'WWW-Authenticate': 'Basic realm="' + realm + '"',
+ 'Content-Length': 12
+ });
+ res.end("Unauthorized");
+ }
+
+ function badRequest(res) {
+ res.writeHead(400, {
+ "Content-Length": 11
+ });
+ res.end('Bad Request');
+ }
+
+ return function(req, res, next) {
+ // Check for non SSL connections
+ if (!req.socket.encrypted) {
+ var parts = req.headers.host.split(":");
+ var host = parts[0];
+ var port = parseInt(parts[1], 10);
+ if (port !== 80) {
+ port = port - (port % 1000) + 443;
+ host = host + ":" + port;
+ }
+ var url = "https://" + host + req.realUrl;
+ res.writeHead(301, {
+ Location: url,
+ "Content-Length": 0
+ });
res.end();
return;
}
- if (req.client.remoteAddress === '127.0.0.1' && req.headers.authorization) {
- var parts = req.headers.authorization.split(' ');
- parts = (new Buffer(parts[1], 'base64')).toString('utf8').split(':');
- var username = parts[0];
- var password = parts[1];
- var key = Crypto.createHmac('sha1', username).update(password).digest('base64');
- if (key === secrets[username]) {
- return next();
- }
- }
- res.writeHead(401, {
- "WWW-Authenticate": 'Basic realm="Secure Area"',
- "Content-Type": "text/plain"
- });
- res.end("Authorization Required");
- };
+ var authorization = req.headers.authorization;
+ if (!authorization) return unauthorized(res);
+ var parts = authorization.split(' ');
+ var scheme = parts[0];
+ var credentials = new Buffer(parts[1], 'base64').toString().split(':');
+ if ('Basic' != scheme) return badRequest(res);
+ var user = checker(req, credentials[0], credentials[1]);
+ if (!user) return unauthorized(res);
+ req.remoteUser = user;
+ next();
+ }
};
+
View
12 mount.js
@@ -1,12 +0,0 @@
-var Url = require("url");
-
-module.exports = function setup(method, mount, handler) {
- return function handle(req, res, next) {
- if (!req.hasOwnProperty("uri")) { req.uri = Url.parse(req.url); }
- if (req.method === method && req.uri.pathname === mount) {
- handler(req, res, next);
- } else {
- next();
- }
- };
-};
View
2  package.json
@@ -2,7 +2,7 @@
"name": "creationix",
"description": "Creationix is a meta package for my personal packages",
"tags": ["stack", "creationix", "meta", "sandbox"],
- "version": "0.1.5",
+ "version": "0.2.0",
"author": "Tim Caswell <tim@creationix.com>",
"repository": {
"type": "git",
View
46 substack.js
@@ -0,0 +1,46 @@
+var URL = require('url');
+
+function core(req, res, next) { next(); }
+
+module.exports = function setup(mountPoint/*, layers*/) {
+
+ // Calculate the SubStack
+ var stack = core;
+ Array.prototype.slice.call(arguments, 1).reverse().forEach(function (layer) {
+ var child = stack;
+ stack = function (req, res, next) {
+ try {
+ layer(req, res, function (err) {
+ if (err) { return next(err); }
+ child(req, res, next);
+ });
+ } catch (err) {
+ next(err);
+ }
+ };
+ });
+
+ // Normalize the mountPoint
+ if (mountPoint[mountPoint.length - 1] === "/") {
+ mountPoint = mountPoint.substr(0, mountPoint.length - 1);
+ }
+ var matchPoint = mountPoint + "/";
+
+ return function handle(req, res, next) {
+ var url = req.url;
+
+ if (url.substring(0, matchPoint.length) !== matchPoint) return next();
+ // Modify the url
+ if (!req.realUrl) req.realUrl = url;
+ req.url = url.substr(mountPoint.length);
+ req.uri = URL.parse(req.url);
+ stack(req, res, function (err) {
+ // Restore the url
+ req.url = url;
+ req.uri = URL.parse(req.url);
+ next(err);
+ });
+ }
+
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.