├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── lib ├── index.js └── strategy.js ├── package.json ├── support └── mk │ ├── coveralls.mk │ ├── istanbul.mk │ ├── jshint.mk │ ├── mocha.mk │ ├── node.mk │ └── notes.mk └── test ├── bootstrap ├── node.js └── testling.js ├── package.test.js └── strategy.test.js /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | reports/ 3 | 4 | # Node.js 5 | node_modules/ 6 | npm-debug.log 7 | 8 | # Mac OS X 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "bitwise": true, 4 | "camelcase": true, 5 | "curly": true, 6 | "forin": true, 7 | "immed": true, 8 | "latedef": true, 9 | "newcap": true, 10 | "noarg": true, 11 | "noempty": true, 12 | "nonew": true, 13 | "quotmark": "single", 14 | "undef": true, 15 | "unused": true, 16 | "trailing": true, 17 | "laxcomma": true 18 | } 19 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | Makefile 2 | README.md 3 | build/ 4 | docs/ 5 | examples/ 6 | reports/ 7 | support/ 8 | test/ 9 | 10 | # Node.js 11 | .npmignore 12 | node_modules/ 13 | npm-debug.log 14 | 15 | # Mac OS X 16 | .DS_Store 17 | 18 | # Git 19 | .git* 20 | 21 | # Utilities 22 | .jshintrc 23 | .travis.yml 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: "node_js" 2 | node_js: 3 | - "0.10" 4 | - "0.8" 5 | # - "0.6" 6 | - "0.4" 7 | 8 | before_install: 9 | - "npm install istanbul -g" 10 | - "npm install coveralls -g" 11 | 12 | script: "make ci-travis" 13 | 14 | after_success: 15 | - "make submit-cov-to-coveralls" 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2014 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 ?= lib/*.js 2 | TESTS ?= test/*.test.js 3 | 4 | test: test-mocha 5 | test-cov: test-istanbul-mocha 6 | view-cov: view-istanbul-report 7 | lint: lint-jshint 8 | lint-tests: lint-tests-jshint 9 | 10 | 11 | # ============================================================================== 12 | # Node.js 13 | # ============================================================================== 14 | include support/mk/node.mk 15 | include support/mk/mocha.mk 16 | include support/mk/istanbul.mk 17 | 18 | # ============================================================================== 19 | # Analysis 20 | # ============================================================================== 21 | include support/mk/notes.mk 22 | include support/mk/jshint.mk 23 | 24 | # ============================================================================== 25 | # Reports 26 | # ============================================================================== 27 | include support/mk/coveralls.mk 28 | 29 | # ============================================================================== 30 | # Continuous Integration 31 | # ============================================================================== 32 | submit-cov-to-coveralls: submit-istanbul-lcov-to-coveralls 33 | 34 | # Travis CI 35 | ci-travis: test test-cov 36 | 37 | # ============================================================================== 38 | # Clean 39 | # ============================================================================== 40 | clean: 41 | rm -rf build 42 | rm -rf reports 43 | 44 | clobber: clean clobber-node 45 | 46 | 47 | .PHONY: test test-cov view-cov lint lint-tests submit-cov-to-coveralls ci-travis clean clobber 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # passport-strategy 2 | 3 | [![Build](https://travis-ci.org/jaredhanson/passport-strategy.png)](https://travis-ci.org/jaredhanson/passport-strategy) 4 | [![Coverage](https://coveralls.io/repos/jaredhanson/passport-strategy/badge.png)](https://coveralls.io/r/jaredhanson/passport-strategy) 5 | [![Quality](https://codeclimate.com/github/jaredhanson/passport-strategy.png)](https://codeclimate.com/github/jaredhanson/passport-strategy) 6 | [![Dependencies](https://david-dm.org/jaredhanson/passport-strategy.png)](https://david-dm.org/jaredhanson/passport-strategy) 7 | [![Tips](http://img.shields.io/gittip/jaredhanson.png)](https://www.gittip.com/jaredhanson/) 8 | 9 | 10 | An abstract class implementing [Passport](http://passportjs.org/)'s strategy 11 | API. 12 | 13 | ## Install 14 | 15 | $ npm install passport-strategy 16 | 17 | ## Usage 18 | 19 | This module exports an abstract `Strategy` class that is intended to be 20 | subclassed when implementing concrete authentication strategies. Once 21 | implemented, such strategies can be used by applications that utilize Passport 22 | middleware for authentication. 23 | 24 | #### Subclass Strategy 25 | 26 | Create a new `CustomStrategy` constructor which inherits from `Strategy`: 27 | 28 | ```javascript 29 | var util = require('util') 30 | , Strategy = require('passport-strategy'); 31 | 32 | function CustomStrategy(...) { 33 | Strategy.call(this); 34 | } 35 | 36 | util.inherits(CustomStrategy, Strategy); 37 | ``` 38 | 39 | #### Implement Authentication 40 | 41 | Implement `autheticate()`, performing the necessary operations required by the 42 | authentication scheme or protocol being implemented. 43 | 44 | ```javascript 45 | CustomStrategy.prototype.authenticate = function(req, options) { 46 | // TODO: authenticate request 47 | } 48 | ``` 49 | 50 | #### Augmented Methods 51 | The Strategy.authenticate method is called on an instance of this Strategy that's augmented with the following action functions. 52 | These action functions are bound via closure the the request/response pair. 53 | The end goal of the strategy is to invoke *one* of these action methods, in 54 | order to indicate successful or failed authentication, redirect to a 55 | third-party identity provider, etc. 56 | 57 | * [.success(user, info)](#Strategy+success) 58 | * [.fail(challenge, status)](#Strategy+fail) 59 | * [.redirect(url, status)](#Strategy+redirect) 60 | * [.pass()](#Strategy+pass) 61 | * [.error(err)](#Strategy+error) 62 | 63 | 64 | ##### strategy.success(user, info) 65 | Authenticate `user`, with optional `info`. 66 | 67 | Strategies should call this function to successfully authenticate a 68 | user. `user` should be an object supplied by the application after it 69 | has been given an opportunity to verify credentials. `info` is an 70 | optional argument containing additional user information. This is 71 | useful for third-party authentication strategies to pass profile 72 | details. 73 | 74 | **Kind**: instance method of [Strategy](#Strategy) 75 | **Api**: public 76 | 77 | | Param | Type | 78 | | --- | --- | 79 | | user | Object | 80 | | info | Object | 81 | 82 | 83 | ##### strategy.fail(challenge, status) 84 | Fail authentication, with optional `challenge` and `status`, defaulting 85 | to 401. 86 | 87 | Strategies should call this function to fail an authentication attempt. 88 | 89 | **Kind**: instance method of [Strategy](#Strategy) 90 | **Api**: public 91 | 92 | | Param | Type | 93 | | --- | --- | 94 | | challenge | String | 95 | | status | Number | 96 | 97 | 98 | 99 | ##### strategy.redirect(url, status) 100 | Redirect to `url` with optional `status`, defaulting to 302. 101 | 102 | Strategies should call this function to redirect the user (via their 103 | user agent) to a third-party website for authentication. 104 | 105 | **Kind**: instance method of [Strategy](#Strategy) 106 | **Api**: public 107 | 108 | | Param | Type | 109 | | --- | --- | 110 | | url | String | 111 | | status | Number | 112 | 113 | 114 | ##### strategy.pass() 115 | Pass without making a success or fail decision. 116 | 117 | Under most circumstances, Strategies should not need to call this 118 | function. It exists primarily to allow previous authentication state 119 | to be restored, for example from an HTTP session. 120 | 121 | **Kind**: instance method of [Strategy](#Strategy) 122 | **Api**: public 123 | 124 | ##### strategy.error(err) 125 | Internal error while performing authentication. 126 | 127 | Strategies should call this function when an internal error occurs 128 | during the process of performing authentication; for example, if the 129 | user directory is not available. 130 | 131 | **Kind**: instance method of [Strategy](#Strategy) 132 | **Api**: public 133 | 134 | | Param | Type | 135 | | --- | --- | 136 | | err | Error | 137 | 138 | 139 | 140 | ## Related Modules 141 | 142 | - [chai-passport-strategy](https://github.com/jaredhanson/chai-passport-strategy) — helpers for testing strategies with the Chai assertion library 143 | 144 | ## Tests 145 | 146 | $ npm install 147 | $ npm test 148 | 149 | ## Credits 150 | 151 | - [Jared Hanson](http://github.com/jaredhanson) 152 | 153 | ## License 154 | 155 | [The MIT License](http://opensource.org/licenses/MIT) 156 | 157 | Copyright (c) 2011-2014 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> 158 | 159 | Sponsor 160 | 161 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | var Strategy = require('./strategy'); 5 | 6 | 7 | /** 8 | * Expose `Strategy` directly from package. 9 | */ 10 | exports = module.exports = Strategy; 11 | 12 | /** 13 | * Export constructors. 14 | */ 15 | exports.Strategy = Strategy; 16 | -------------------------------------------------------------------------------- /lib/strategy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates an instance of `Strategy`. 3 | * 4 | * @constructor 5 | * @api public 6 | */ 7 | function Strategy() { 8 | } 9 | 10 | /** 11 | * Authenticate request. 12 | * 13 | * This function must be overridden by subclasses. In abstract form, it always 14 | * throws an exception. 15 | * 16 | * @param {Object} req The request to authenticate. 17 | * @param {Object} [options] Strategy-specific options. 18 | * @api public 19 | */ 20 | Strategy.prototype.authenticate = function(req, options) { 21 | throw new Error('Strategy#authenticate must be overridden by subclass'); 22 | }; 23 | 24 | 25 | /** 26 | * Expose `Strategy`. 27 | */ 28 | module.exports = Strategy; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passport-strategy", 3 | "version": "1.0.0", 4 | "description": "An abstract class implementing Passport's strategy API.", 5 | "keywords": [ 6 | "passport", 7 | "strategy" 8 | ], 9 | "author": { 10 | "name": "Jared Hanson", 11 | "email": "jaredhanson@gmail.com", 12 | "url": "http://www.jaredhanson.net/" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git://github.com/jaredhanson/passport-strategy.git" 17 | }, 18 | "bugs": { 19 | "url": "http://github.com/jaredhanson/passport-strategy/issues" 20 | }, 21 | "licenses": [ 22 | { 23 | "type": "MIT", 24 | "url": "http://www.opensource.org/licenses/MIT" 25 | } 26 | ], 27 | "main": "./lib", 28 | "dependencies": { 29 | }, 30 | "devDependencies": { 31 | "mocha": "1.x.x", 32 | "chai": "1.x.x" 33 | }, 34 | "engines": { 35 | "node": ">= 0.4.0" 36 | }, 37 | "scripts": { 38 | "test": "node_modules/.bin/mocha --reporter spec --require test/bootstrap/node test/*.test.js" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /support/mk/coveralls.mk: -------------------------------------------------------------------------------- 1 | COVERALLS ?= coveralls 2 | 3 | submit-istanbul-lcov-to-coveralls: 4 | cat $(ISTANBUL_LCOV_INFO_PATH) | $(COVERALLS) 5 | 6 | 7 | .PHONY: submit-istanbul-lcov-to-coveralls 8 | -------------------------------------------------------------------------------- /support/mk/istanbul.mk: -------------------------------------------------------------------------------- 1 | ISTANBUL ?= istanbul 2 | ISTANBUL_OUT ?= ./reports/coverage 3 | ISTANBUL_REPORT ?= lcov 4 | ISTANBUL_LCOV_INFO_PATH ?= $(ISTANBUL_OUT)/lcov.info 5 | ISTANBUL_HTML_REPORT_PATH ?= $(ISTANBUL_OUT)/lcov-report/index.html 6 | 7 | 8 | test-istanbul-mocha: node_modules 9 | NODE_PATH=$(NODE_PATH_TEST) \ 10 | $(ISTANBUL) cover \ 11 | --dir $(ISTANBUL_OUT) --report $(ISTANBUL_REPORT) \ 12 | $(_MOCHA) -- \ 13 | --reporter $(MOCHA_REPORTER) \ 14 | --require $(MOCHA_REQUIRE) \ 15 | $(TESTS) 16 | 17 | view-istanbul-report: 18 | open $(ISTANBUL_HTML_REPORT_PATH) 19 | 20 | 21 | .PHONY: test-istanbul-mocha view-istanbul-report 22 | -------------------------------------------------------------------------------- /support/mk/jshint.mk: -------------------------------------------------------------------------------- 1 | JSHINT ?= jshint 2 | 3 | lint-jshint: 4 | $(JSHINT) $(SOURCES) 5 | 6 | lint-tests-jshint: 7 | $(JSHINT) $(TESTS) 8 | 9 | 10 | .PHONY: lint-jshint lint-tests-jshint 11 | -------------------------------------------------------------------------------- /support/mk/mocha.mk: -------------------------------------------------------------------------------- 1 | MOCHA ?= ./node_modules/.bin/mocha 2 | _MOCHA ?= ./node_modules/.bin/_mocha 3 | MOCHA_REPORTER ?= spec 4 | MOCHA_REQUIRE ?= ./test/bootstrap/node 5 | 6 | test-mocha: node_modules 7 | NODE_PATH=$(NODE_PATH_TEST) \ 8 | $(MOCHA) \ 9 | --reporter $(MOCHA_REPORTER) \ 10 | --require $(MOCHA_REQUIRE) \ 11 | $(TESTS) 12 | 13 | 14 | .PHONY: test-mocha 15 | -------------------------------------------------------------------------------- /support/mk/node.mk: -------------------------------------------------------------------------------- 1 | node_modules: 2 | npm install 3 | 4 | clobber-node: 5 | rm -rf node_modules 6 | 7 | 8 | .PHONY: clobber-node 9 | -------------------------------------------------------------------------------- /support/mk/notes.mk: -------------------------------------------------------------------------------- 1 | NOTES ?= 'TODO|FIXME' 2 | 3 | notes: 4 | grep -Ern $(NOTES) $(SOURCES) $(TESTS) 5 | 6 | 7 | .PHONY: notes 8 | -------------------------------------------------------------------------------- /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/package.test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | 3 | var strategy = require('..'); 4 | 5 | describe('passport-strategy', function() { 6 | 7 | it('should export Strategy constructor directly from package', function() { 8 | expect(strategy).to.be.a('function'); 9 | expect(strategy).to.equal(strategy.Strategy); 10 | }); 11 | 12 | it('should export Strategy constructor', function() { 13 | expect(strategy.Strategy).to.be.a('function'); 14 | }); 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /test/strategy.test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it, expect */ 2 | 3 | var Strategy = require('../lib/strategy'); 4 | 5 | describe('Strategy', function() { 6 | 7 | var strategy = new Strategy(); 8 | 9 | it('authenticate should throw error', function() { 10 | expect(function() { 11 | strategy.authenticate(); 12 | }).to.throw(Error, 'Strategy#authenticate must be overridden by subclass'); 13 | }); 14 | 15 | }); 16 | --------------------------------------------------------------------------------