Skip to content

Commit

Permalink
Adding local authentication
Browse files Browse the repository at this point in the history
Undoing change to sample

Updating README

Updating README

Updating README

Updating README

Updating README

Updating test
  • Loading branch information
avoidwork committed Aug 5, 2014
1 parent 8512981 commit 6e151e3
Show file tree
Hide file tree
Showing 11 changed files with 415 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## 0.2.0
- Created `Tenso.redirect(req, res, uri)`, & `Tenso.error(req, res, status, arg)`
- Added `local` authentication, which is controlled by config
- Added `express-session` as a dependency, and enabled sessions
- Updated turtle.io to gain `res.redirect()`

## 0.1.1
- Decorating `hostname` on Tenso instance
- Removed temp function that made it into a release
Expand Down
50 changes: 47 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Caching can be disabled by setting the `cache-control` header to a "private" or
## Configuration
This is a sample configuration for Tensō, without authentication or SSL. This would be ideal for development, but not production! Enabling SSL is as easy as providing file paths for the two keys.

```json
```javascript
{
"auth": /* Optional, see Authentication section */
"hostname": "localhost", /* Optional, default is 'localhost' */
Expand All @@ -96,7 +96,7 @@ Planned authentication options are `Basic Auth`, `OAuth2 Bearer Token`, `Twitter
### Basic Auth
`Basic Auth` will be applied to the entire API if enabled.

```json
```javascript
{
"auth": {
"basic": {
Expand All @@ -111,7 +111,7 @@ Planned authentication options are `Basic Auth`, `OAuth2 Bearer Token`, `Twitter
### Oauth2 Bearer Token
The `protect` Array is the endpoints that will be protected by `OAuth2 Bearer Tokens`.

```json
```javascript
{
"auth": {
"bearer": {
Expand All @@ -123,6 +123,50 @@ The `protect` Array is the endpoints that will be protected by `OAuth2 Bearer To
}
```

### Local
The `protect` Array is the endpoints that will be protected by `local` authentication. Do not protect `/`, as it'll block the authentication end points.

`local` authentication will rely on sessions, so SSL is required for production servers.

```javascript
{
"auth": {
local: {
enabled: true,
auth: function ( req, res ) {
if ( !req.session.authorized ) {
if ( ... ) {
req.session.authorized = true;
}
else {
req.session.authorized = false;
}

req.session.save();
}

if ( req.session.authorized ) {
this.redirect( req, res, "/stuff" );
}
else {
this.error( req, res, 401, "Unauthorized" );
}
},
middleware: function( req, res, next ) {
if ( req.session.authorized ) {
next();
}
else {
res.redirect( "/login" );
}
},
login: "/login"
}
"protect": ["/stuff"]
}
}
```

## Logging
Standard log levels are supported, and are emitted (by configuration) to `stdout` & `stderr`, & `syslog`.

Expand Down
15 changes: 15 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
"enabled": false,
"tokens": []
},
"local": {
"enabled": false,
"callback": null,
"login": "/login"
},
"twitter": {
"enabled": false,
"consumer_key": "",
"consumer_secret": "",
"callback_url": ""
},
"protect": ["/"]
},
"hostname": "localhost",
Expand All @@ -18,6 +29,10 @@
"dtrace": false,
"syslog": false
},
"session": {
"key": "",
"max_age": 60000
},
"ssl": {
"key": null,
"cert": null
Expand Down
93 changes: 87 additions & 6 deletions lib/tenso.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
* @license BSD-3 <https://raw.github.com/avoidwork/tenso/master/LICENSE>
* @link http://avoidwork.github.io/tenso
* @module tenso
* @version 0.1.1
* @version 0.2.0
*/
( function () {
"use strict";

var TurtleIO = require( "turtle.io" ),
SERVER = "tenso/0.1.1",
SERVER = "tenso/0.2.0",
CONFIG = require( __dirname + "/../config.json" ),
keigai = require( "keigai" ),
util = keigai.util,
Expand All @@ -21,6 +21,8 @@ var TurtleIO = require( "turtle.io" ),
clone = util.clone,
iterate = util.iterate,
merge = util.merge,
uuid = util.uuid,
session = require( "express-session" ),
passport = require( "passport" ),
BearerStrategy = require( "passport-http-bearer" ).Strategy;

Expand All @@ -33,7 +35,7 @@ function Tenso () {
this.hostname = "";
this.messages = {};
this.server = new TurtleIO();
this.version = "0.1.1";
this.version = "0.2.0";
}

/**
Expand All @@ -45,6 +47,32 @@ function Tenso () {
*/
Tenso.prototype.constructor = Tenso;

/**
* Sends an Error to the Client
*
* @method redirect
* @memberOf Tenso
* @param {Object} req Client request
* @param {Object} res Client response
* @param {Mixed} uri Target URI
*/
Tenso.prototype.error = function ( req, res, status, arg ) {
this.server.error( req, res, status, arg );
};

/**
* Redirects the Client
*
* @method redirect
* @memberOf Tenso
* @param {Object} req Client request
* @param {Object} res Client response
* @param {Mixed} uri Target URI
*/
Tenso.prototype.redirect = function ( req, res, uri ) {
this.server.respond( req, res, this.server.messages.NO_CONTENT, this.server.codes.FOUND, {location: uri} );
};

/**
* Sends a response to the Client
*
Expand All @@ -60,7 +88,9 @@ Tenso.prototype.constructor = Tenso;
Tenso.prototype.respond = function ( req, res, arg, status, headers ) {
var ref = [headers || {}];

this.server.respond( req, res, hypermedia( this.server, req, response( arg, status ), ref[0] ), status, ref[0] );
if ( !res._header ) {
this.server.respond( req, res, hypermedia( this.server, req, response( arg, status ), ref[0] ), status, ref[0] );
}
};

/**
Expand All @@ -84,8 +114,18 @@ function auth ( obj, config ) {
config.auth = tmp;
}
else {
var login;

array.each( array.keys( config.auth ), function ( i ) {
if ( i.enabled && i.login ) {
login = i.login;

return false;
}
} );

protect = ( config.auth.protect || [] ).map( function ( i ) {
return new RegExp( "^" + string.escape( i ), "i" );
return new RegExp( "^" + i !== login ? string.escape( i ) : "$", "i" );
} );

middleware = function ( req, res, next ) {
Expand All @@ -104,8 +144,18 @@ function auth ( obj, config ) {
}
};

obj.server.use( session( {
name: "tenso",
resave: true,
rolling: false,
saveUninitialized: false,
secret: config.session.key || uuid(),
cookie: {
maxAge: config.session.max_age || 60000
}
} ) );

obj.server.use( middleware );
obj.server.use( passport.initialize() );

if ( config.auth.bearer.enabled ) {
( function () {
Expand All @@ -126,6 +176,8 @@ function auth ( obj, config ) {
}
};

obj.server.use( passport.initialize() );

passport.use( new BearerStrategy (
function( token, done ) {
fn( token, function ( err, user ) {
Expand All @@ -147,6 +199,35 @@ function auth ( obj, config ) {
obj.server.use( passport.authenticate( "bearer", {session: false} ) );
} )();
}
else if ( config.auth.local.enabled ) {
config.routes.get[config.auth.local.login] = "POST to authenticate"
config.routes.post = config.routes.post || {};
config.routes.post[config.auth.local.login] = function ( req, res ) {
var args = array.cast( arguments ),
session;

if ( req.session === undefined ) {
req.sessionStore.get( req.sessionId, function ( session ) {
if ( req.session === undefined ) {
if ( session ) {
req.session = session;
req.session.save();
}
else {
req.session = {};
}

if ( parse( req.url ).pathname !== config.auth.local.login ) {
config.auth.local.auth.apply( obj, args );
}
} } );
}
else {
config.auth.local.auth.apply( obj, args );
}
}
obj.server.use( config.auth.local.middleware );
}
}

return config;
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "tenso",
"description": "Tensō is a REST API facade for node.js, designed to simplify the implementation of APIs.",
"version": "0.1.1",
"version": "0.2.0",
"homepage": "http://avoidwork.github.io/tenso",
"author": {
"name": "Jason Mulligan",
Expand Down Expand Up @@ -29,7 +29,8 @@
},
"dependencies": {
"keigai": "0.6.1",
"turtle.io": "2.1.18",
"turtle.io": "2.2.2",
"express-session": "^1.7.2",
"passport": "0.2.0",
"passport-http-bearer": "1.0.1"
},
Expand Down
32 changes: 31 additions & 1 deletion sample.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var tenso = require( "./lib/tenso" );
var tenso = require( "./lib/tenso" ),
array = require( "keigai" ).util.array;

tenso( {
routes: require( "./routes.js" ),
Expand All @@ -7,13 +8,42 @@ tenso( {
dtrace: true
},
auth: {
protect: ["/uuid"],
basic: {
enabled: false,
list:["test:123"] // "username:password"
},
bearer: {
enabled: false,
tokens:["test-123"]
},
local: {
enabled: true,
auth: function ( req, res ) {
var args = array.chunk( req.body.split( /&|=/ ), 2 );

req.session = req.session || {};

if ( !req.session.authorized ) {
if ( args[0][1] == "test" && args[1][1] == "123" ) {
req.session.authorized = true;
}
else {
req.session.authorized = false;
}
}

this.redirect( req, res, "/uuid" );
},
middleware: function( req, res, next ) {
if ( req.session.authorized ) {
next();
}
else {
res.redirect( "/login" );
}
},
login: "/login"
}
}
} );
Loading

0 comments on commit 6e151e3

Please sign in to comment.