├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── component.json ├── lib └── factory.js ├── main.js ├── package.json └── test ├── auto ├── server.js └── terminal-saucelabs.js ├── bootstrap ├── node.js └── testling.js ├── sasl.factory.test.js ├── sasl.test.js └── www ├── index.html ├── js ├── main.js └── suite.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | test/www/js/lib 3 | 4 | # Mac OS X 5 | .DS_Store 6 | 7 | # Node.js 8 | node_modules 9 | npm-debug.log 10 | 11 | # Component 12 | components 13 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | README.md 2 | Makefile 3 | doc/ 4 | examples/ 5 | test/ 6 | 7 | # Mac OS X 8 | .DS_Store 9 | 10 | # Node.js 11 | .npmignore 12 | node_modules/ 13 | npm-debug.log 14 | 15 | # Git 16 | .git* 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: "node_js" 2 | node_js: 3 | - 0.4 4 | - 0.6 5 | - 0.8 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012-2013 Jared Hanson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCES = *.js lib/*.js 2 | TESTS = test/*.test.js 3 | 4 | # ============================================================================== 5 | # Packaging 6 | # ============================================================================== 7 | 8 | build-browserify: 9 | mkdir -p build 10 | browserify main.js -o build/bundle.js 11 | 12 | build-component: components 13 | component build 14 | 15 | components: 16 | component install 17 | 18 | 19 | # ============================================================================== 20 | # Browser Tests 21 | # ============================================================================== 22 | 23 | CHROME = open -a "Google Chrome" 24 | FIREFOX = open -a "Firefox" 25 | SAFARI = open -a "Safari" 26 | PHANTOMJS = phantomjs 27 | 28 | MOCHA_PHANTOMJS = ./node_modules/.bin/mocha-phantomjs 29 | WWW_TESTS = test/www/index.html 30 | 31 | 32 | test: test-phantomjs 33 | 34 | test-chrome: test-browser 35 | $(CHROME) $(WWW_TESTS) 36 | 37 | test-firefox: test-browser 38 | $(FIREFOX) $(WWW_TESTS) 39 | 40 | test-safari: test-browser 41 | $(SAFARI) $(WWW_TESTS) 42 | 43 | test-phantomjs: node_modules test-browser 44 | $(MOCHA_PHANTOMJS) $(WWW_TESTS) 45 | 46 | test-browser: test/www/js/lib 47 | test/www/js/lib: 48 | cd test/www && volo add -nostamp 49 | 50 | 51 | # Prior to running tests on Sauce Labs, ensure that a local server is listening 52 | # and Sauce Connect is tunneling requests to it. 53 | # 54 | # $ java -jar Sauce-Connect.jar $SAUCE_LABS_USERNAME $SAUCE_LABS_ACCESS_KEY 55 | # $ node test/auto/server.js 56 | # 57 | test-saucelabs: node_modules test-browser 58 | clear && node test/auto/terminal-saucelabs.js 59 | 60 | 61 | # ============================================================================== 62 | # Node Tests 63 | # ============================================================================== 64 | 65 | MOCHA = ./node_modules/.bin/mocha 66 | 67 | test-node: node_modules 68 | @NODE_PATH=.. \ 69 | $(MOCHA) \ 70 | --reporter spec \ 71 | --require test/bootstrap/node $(TESTS) 72 | 73 | node_modules: 74 | npm install 75 | 76 | 77 | # ============================================================================== 78 | # Static Analysis 79 | # ============================================================================== 80 | 81 | JSHINT = jshint 82 | 83 | hint: lint 84 | lint: 85 | $(JSHINT) $(SOURCES) 86 | 87 | 88 | # ============================================================================== 89 | # Clean 90 | # ============================================================================== 91 | 92 | clean: 93 | rm -rf build 94 | 95 | clobber: clean 96 | rm -rf node_modules 97 | rm -rf components 98 | rm -rf test/www/js/lib 99 | 100 | 101 | .PHONY: test test-chrome test-firefox test-safari test-phantomjs test-cloud test-saucelabs test-node hint lint 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SASL 2 | 3 | This module is a JavaScript framework for SASL authentication and data security. 4 | Mechanisms are pluggable, allowing a server and client to negotiate supported 5 | mechanisms when performing authentication in connection-oriented protocols. 6 | 7 | ## Install 8 | 9 | ##### npm 10 | 11 | $ npm install saslmechanisms 12 | 13 | ##### volo 14 | 15 | $ volo add jaredhanson/js-sasl sasl 16 | 17 | ## Usage 18 | 19 | Create a SASL mechanism factory. 20 | 21 | ```javascript 22 | var factory = new sasl.Factory(); 23 | ``` 24 | 25 | Register supported SASL mechanisms. 26 | 27 | ``` 28 | factory.use(require('sasl-plain')); 29 | ``` 30 | 31 | ## Mechanisms 32 | 33 | |Mechanism |Developer | 34 | |-----------------------------------------------------------------------------------|------------------------------------------------| 35 | |[ANONYMOUS](https://github.com/jaredhanson/js-sasl-anonymous) |[Jared Hanson](https://github.com/jaredhanson) | 36 | |[DIGEST-MD5](https://github.com/jaredhanson/js-sasl-digest-md5) |[Jared Hanson](https://github.com/jaredhanson) | 37 | |[EXTERNAL](https://github.com/jaredhanson/js-sasl-external) |[Jared Hanson](https://github.com/jaredhanson) | 38 | |[PLAIN](https://github.com/jaredhanson/js-sasl-plain) |[Jared Hanson](https://github.com/jaredhanson) | 39 | |[XOAUTH2](https://github.com/jaredhanson/js-sasl-xoauth2) |[Jared Hanson](https://github.com/jaredhanson) | 40 | |[X-FACEBOOK-PLATFORM](https://github.com/jaredhanson/js-sasl-x-facebook-platform) |[Jared Hanson](https://github.com/jaredhanson) | 41 | |[X-OAUTH2](https://github.com/jaredhanson/js-sasl-x-oauth2) |[Jared Hanson](https://github.com/jaredhanson) | 42 | 43 | ## Compatibility 44 | 45 | ##### Browser 46 | 47 | [![browser support](https://ci.testling.com/jaredhanson/js-sasl.png)](http://ci.testling.com/jaredhanson/js-sasl) 48 | 49 | ##### Modules 50 | 51 | - [AMD](https://github.com/amdjs/amdjs-api) 52 | - [CommonJS](http://www.commonjs.org/) 53 | - [Node](http://nodejs.org/) 54 | 55 | ## Tests 56 | 57 | [![Travis CI](https://secure.travis-ci.org/jaredhanson/js-sasl.png)](http://travis-ci.org/jaredhanson/js-sasl) [![David DM](https://david-dm.org/jaredhanson/js-sasl.png)](http://david-dm.org/jaredhanson/js-sasl) 58 | 59 | ##### Browser 60 | 61 | To run tests in a browser, execute the Make target for the desired browser: 62 | 63 | $ make test-chrome 64 | $ make test-firefox 65 | $ make test-safari 66 | 67 | Headless tests can be executed directly from a terminal: 68 | 69 | $ make test-phantomjs 70 | 71 | ##### Node 72 | 73 | To run tests in Node: 74 | 75 | $ make test-node 76 | 77 | ## Credits 78 | 79 | - [Jared Hanson](http://github.com/jaredhanson) 80 | 81 | ## License 82 | 83 | [The MIT License](http://opensource.org/licenses/MIT) 84 | 85 | Copyright (c) 2012-2013 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> 86 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sasl", 3 | "version": "0.1.1", 4 | "description": "SASL mechanism factory.", 5 | "keywords": ["sasl", "auth", "authn", "authentication", "security"], 6 | "repo": "jaredhanson/js-sasl", 7 | "main": "main.js", 8 | "scripts": [ 9 | "main.js", 10 | "lib/factory.js" 11 | ], 12 | "license": "MIT" 13 | } 14 | -------------------------------------------------------------------------------- /lib/factory.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if (typeof exports === 'object') { 3 | // CommonJS 4 | factory(exports, module); 5 | } else if (typeof define === 'function' && define.amd) { 6 | // AMD 7 | define(['exports', 'module'], factory); 8 | } 9 | }(this, function(exports, module) { 10 | 11 | /** 12 | * `Factory` constructor. 13 | * 14 | * @api public 15 | */ 16 | function Factory() { 17 | this._mechs = []; 18 | } 19 | 20 | /** 21 | * Utilize the given `mech` with optional `name`, overridding the mechanism's 22 | * default name. 23 | * 24 | * Examples: 25 | * 26 | * factory.use(FooMechanism); 27 | * 28 | * factory.use('XFOO', FooMechanism); 29 | * 30 | * @param {String|Mechanism} name 31 | * @param {Mechanism} mech 32 | * @return {Factory} for chaining 33 | * @api public 34 | */ 35 | Factory.prototype.use = function(name, mech) { 36 | if (!mech) { 37 | mech = name; 38 | name = mech.prototype.name; 39 | } 40 | this._mechs.push({ name: name, mech: mech }); 41 | return this; 42 | }; 43 | 44 | /** 45 | * Create a new mechanism from supported list of `mechs`. 46 | * 47 | * If no mechanisms are supported, returns `null`. 48 | * 49 | * Examples: 50 | * 51 | * var mech = factory.create(['FOO', 'BAR']); 52 | * 53 | * @param {Array} mechs 54 | * @return {Mechanism} 55 | * @api public 56 | */ 57 | Factory.prototype.create = function(mechs) { 58 | for (var i = 0, len = this._mechs.length; i < len; i++) { 59 | for (var j = 0, jlen = mechs.length; j < jlen; j++) { 60 | var entry = this._mechs[i]; 61 | if (entry.name == mechs[j]) { 62 | return new entry.mech(); 63 | } 64 | } 65 | } 66 | return null; 67 | }; 68 | 69 | exports = module.exports = Factory; 70 | 71 | })); 72 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if (typeof exports === 'object') { 3 | // CommonJS 4 | factory(exports, 5 | module, 6 | require('./lib/factory')); 7 | } else if (typeof define === 'function' && define.amd) { 8 | // AMD 9 | define(['exports', 10 | 'module', 11 | './lib/factory'], factory); 12 | } 13 | }(this, function(exports, module, Factory) { 14 | 15 | exports = module.exports = Factory; 16 | exports.Factory = Factory; 17 | 18 | })); 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "saslmechanisms", 3 | "version": "0.1.1", 4 | "description": "SASL mechanism factory.", 5 | "keywords": ["sasl", "auth", "authn", "authentication", "security"], 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/jaredhanson/js-sasl.git" 9 | }, 10 | "bugs": { 11 | "url": "http://github.com/jaredhanson/js-sasl/issues" 12 | }, 13 | "author": { 14 | "name": "Jared Hanson", 15 | "email": "jaredhanson@gmail.com", 16 | "url": "http://www.jaredhanson.net/" 17 | }, 18 | "licenses": [ 19 | { 20 | "type": "MIT", 21 | "url": "http://www.opensource.org/licenses/MIT" 22 | } 23 | ], 24 | "main": "main", 25 | "devDependencies": { 26 | "mocha": "1.x.x", 27 | "chai": "1.x.x", 28 | "express": "3.x.x", 29 | "term-canvas": "0.0.x", 30 | "mocha-phantomjs": "2.x.x", 31 | "mocha-cloud": "0.0.x", 32 | "mocha-cloud-grid-view": "0.0.x" 33 | }, 34 | "engines": { "node": ">= 0.4.0" }, 35 | "scripts": { 36 | "test": "node_modules/.bin/mocha --reporter spec --require test/bootstrap/node test/*.test.js" 37 | }, 38 | "volo": { 39 | "dependencies": { 40 | } 41 | }, 42 | "testling": { 43 | "browsers": { 44 | "firefox": [ "17.0", "18.0", "19.0" ], 45 | "chrome": [ "23.0", "24.0", "25.0" ], 46 | "ie": [ "6.0", "7.0", "8.0", "9.0", "10.0" ], 47 | "safari": [ "4.0", "5.0.5", "5.1", "6.0" ], 48 | "opera": [ "10.0", "10.5", "11.0", "11.5", "11.6", "12.0" ] 49 | }, 50 | "harness" : "mocha", 51 | "files": [ 52 | "test/bootstrap/testling.js", 53 | "test/*.test.js" 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/auto/server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var server = express(); 3 | 4 | server.use(express.logger()) 5 | .use(express.static(__dirname + '/../www')) 6 | .use(express.static(__dirname + '/..')) 7 | .use(express.static(__dirname + '/../..')) 8 | .listen(7070, function() { 9 | console.log('HTTP server listening on %s:%d', this.address().address, this.address().port); 10 | }); 11 | -------------------------------------------------------------------------------- /test/auto/terminal-saucelabs.js: -------------------------------------------------------------------------------- 1 | var Harness = require('mocha-cloud') 2 | , Canvas = require('term-canvas') 3 | , GridView = require('mocha-cloud-grid-view') 4 | , size = process.stdout.getWindowSize(); 5 | 6 | var harness = new Harness('sasl', process.env['SAUCE_LABS_USERNAME'], process.env['SAUCE_LABS_ACCESS_KEY']); 7 | 8 | harness.browser('chrome', '', 'Mac 10.8'); 9 | harness.browser('chrome', '', 'Mac 10.6'); 10 | 11 | harness.url('http://localhost:7070/'); 12 | 13 | 14 | var canvas = new Canvas(size[0], size[1]); 15 | var ctx = canvas.getContext('2d'); 16 | var grid = new GridView(harness, ctx); 17 | grid.size(canvas.width, canvas.height); 18 | ctx.hideCursor(); 19 | 20 | process.on('SIGINT', function(){ 21 | ctx.reset(); 22 | process.nextTick(function(){ 23 | process.exit(); 24 | }); 25 | }); 26 | 27 | harness.start(function(){ 28 | grid.showFailures(); 29 | setTimeout(function(){ 30 | ctx.showCursor(); 31 | process.exit(grid.totalFailures()); 32 | }, 100); 33 | }); 34 | -------------------------------------------------------------------------------- /test/bootstrap/node.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | 3 | global.expect = chai.expect; 4 | -------------------------------------------------------------------------------- /test/bootstrap/testling.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | 3 | window.expect = chai.expect; 4 | -------------------------------------------------------------------------------- /test/sasl.factory.test.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if (typeof exports === 'object') { 3 | // CommonJS 4 | factory(require('../lib/factory')); 5 | } else if (typeof define === 'function' && define.amd) { 6 | // AMD 7 | define(['sasl/lib/factory'], factory); 8 | } 9 | }(this, function(Factory) { 10 | 11 | // mocks 12 | function FooMechanism() { 13 | } 14 | FooMechanism.prototype.name = 'FOO'; 15 | 16 | function BarMechanism() { 17 | } 18 | BarMechanism.prototype.name = 'BAR'; 19 | 20 | 21 | describe('Factory', function() { 22 | var factory = new Factory(); 23 | 24 | describe('.use()', function() { 25 | it('should be chainable', function() { 26 | expect(factory.use(FooMechanism)).to.equal(factory); 27 | }); 28 | }); 29 | }); 30 | 31 | describe('Factory with no mechanisms', function() { 32 | var factory = new Factory(); 33 | 34 | it('should not create an unsupported mechanism', function() { 35 | expect(factory.create(['FOO'])).to.equal(null); 36 | }); 37 | }); 38 | 39 | describe('Factory with FOO mechanism', function() { 40 | var factory = new Factory(); 41 | factory.use(FooMechanism); 42 | 43 | it('should create a supported mechanism', function() { 44 | expect(factory.create(['FOO'])).to.be.an.instanceOf(FooMechanism); 45 | }); 46 | 47 | it('should create a supported mechanism from second offered mechanism', function() { 48 | expect(factory.create(['BAR', 'FOO'])).to.be.an.instanceOf(FooMechanism); 49 | }); 50 | 51 | it('should not create an unsupported mechanism', function() { 52 | expect(factory.create(['BAR'])).to.equal(null); 53 | }); 54 | }); 55 | 56 | describe('Factory with FOO and BAR mechanisms', function() { 57 | var factory = new Factory(); 58 | factory.use(FooMechanism); 59 | factory.use(BarMechanism); 60 | 61 | it('should create a supported mechanism', function() { 62 | expect(factory.create(['FOO'])).to.be.an.instanceOf(FooMechanism); 63 | }); 64 | 65 | it('should create a supported mechanism from first preferred mechanism', function() { 66 | expect(factory.create(['BAR', 'FOO'])).to.be.an.instanceOf(FooMechanism); 67 | }); 68 | }); 69 | 70 | describe('Factory with named XFOO mechanism', function() { 71 | var factory = new Factory(); 72 | factory.use('XFOO', FooMechanism); 73 | 74 | it('should create a supported mechanism', function() { 75 | expect(factory.create(['XFOO'])).to.be.an.instanceOf(FooMechanism); 76 | }); 77 | 78 | it('should not create an unsupported mechanism', function() { 79 | expect(factory.create(['FOO'])).to.equal(null); 80 | }); 81 | }); 82 | 83 | return { name: 'test.sasl.factory' }; 84 | 85 | })); 86 | -------------------------------------------------------------------------------- /test/sasl.test.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if (typeof exports === 'object') { 3 | // CommonJS 4 | factory(require('../main')); 5 | } else if (typeof define === 'function' && define.amd) { 6 | // AMD 7 | define(['sasl'], factory); 8 | } 9 | }(this, function(sasl) { 10 | 11 | describe('sasl', function() { 12 | 13 | it('should export Factory', function() { 14 | expect(sasl.Factory).to.be.a('function'); 15 | }); 16 | 17 | it('should export Factory via module', function() { 18 | expect(sasl).to.equal(sasl.Factory); 19 | }); 20 | 21 | }); 22 | 23 | return { name: 'test.sasl' }; 24 | 25 | })); 26 | -------------------------------------------------------------------------------- /test/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SASL Tests 5 | 6 | 7 | 8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /test/www/js/main.js: -------------------------------------------------------------------------------- 1 | require.config({ 2 | baseUrl: 'js/lib', 3 | paths: { 4 | 'test': '../../..', 5 | 'mocha': 'mocha/mocha', 6 | 'chai': 'chai/chai' 7 | }, 8 | packages: [ 9 | { name: 'sasl', location: '../../../..' } 10 | ], 11 | shim: { 12 | 'mocha': { 13 | exports: 'mocha' 14 | } 15 | } 16 | }); 17 | 18 | require(['../suite']); 19 | -------------------------------------------------------------------------------- /test/www/js/suite.js: -------------------------------------------------------------------------------- 1 | define(['require', 2 | 'mocha', 3 | 'chai', 4 | 'mocha-results'], 5 | function(require, mocha, chai, results) { 6 | mocha.setup('bdd'); 7 | expect = chai.expect 8 | 9 | require(['test/sasl.test', 10 | 'test/sasl.factory.test'], 11 | function() { 12 | if (window.mochaPhantomJS) { mochaPhantomJS.run(); } 13 | else { results(mocha.run()); } 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/www/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "volo": { 3 | "baseUrl": "js/lib", 4 | "dependencies": { 5 | "require": "github:jrburke/requirejs/2.x.x", 6 | "mocha": "github:visionmedia/mocha/1.9.x", 7 | "chai": "github:chaijs/chai/1.x.x", 8 | "mocha-results": "github:jaredhanson/mocha-results/1.x.x" 9 | } 10 | } 11 | } --------------------------------------------------------------------------------