├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── etc
└── conf.json
├── lib
├── index.js
├── strategy.js
└── utils.js
├── package.json
└── test
├── bootstrap
└── node.js
├── package.test.js
├── strategy.error.test.js
├── strategy.fail.test.js
├── strategy.fields.test.js
├── strategy.normal.test.js
├── strategy.options.test.js
├── strategy.passreq.test.js
└── strategy.test.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: jaredhanson
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ** READ THIS FIRST! **
2 |
3 | #### Are you looking for help?
4 |
5 | Reminder: The issue tracker is not a support forum.
6 |
7 | Issues should only be filed in this project once they are able to be reproduced
8 | and confirmed as a flaw in the software or incorrect information in associated
9 | documention.
10 |
11 | If you are encountering problems integrating this module into your application,
12 | please post a question on the [discussion forum](https://github.com/passport/discuss)
13 | rather than filing an issue.
14 |
15 | #### Is this a security issue?
16 |
17 | Do not open issues that might have security implications. Potential security
18 | vulnerabilities should be reported privately to jaredhanson@gmail.com. Once any
19 | vulerabilities have been repaired, the details will be disclosed publicly in a
20 | responsible manner. This also allows time for coordinating with affected parties
21 | in order to mitigate negative consequences.
22 |
23 |
24 | If neither of the above two scenarios apply to your situation, you should open
25 | an issue. Delete this paragraph and the text above, and fill in the information
26 | requested below.
27 |
28 |
29 |
30 |
31 |
32 |
33 | ### Expected behavior
34 |
35 |
36 |
37 | ### Actual behavior
38 |
39 |
40 |
41 | ### Steps to reproduce
42 |
43 |
44 |
45 | ```js
46 | // Format code using Markdown code blocks
47 | ```
48 |
49 | ### Environment
50 |
51 | * Operating System:
52 | * Node version:
53 | * passport version:
54 | * passport-local version:
55 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ** READ THIS FIRST! **
2 |
3 | #### Are you implementing a new feature?
4 |
5 | Requests for new features should first be discussed on the [developer forum](https://github.com/passport/develop).
6 | This allows the community to gather feedback and assess whether or not there is
7 | an existing way to achieve the desired functionality.
8 |
9 | If it is determined that a new feature needs to be implemented, include a link
10 | to the relevant discussion along with the pull request.
11 |
12 | #### Is this a security patch?
13 |
14 | Do not open pull requests that might have security implications. Potential
15 | security vulnerabilities should be reported privately to jaredhanson@gmail.com.
16 | Once any vulerabilities have been repaired, the details will be disclosed
17 | publicly in a responsible manner. This also allows time for coordinating with
18 | affected parties in order to mitigate negative consequences.
19 |
20 |
21 | If neither of the above two scenarios apply to your situation, you should open
22 | a pull request. Delete this paragraph and the text above, and fill in the
23 | information requested below.
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | ### Checklist
33 |
34 |
35 |
36 |
37 | - [ ] I have read the [CONTRIBUTING](https://github.com/jaredhanson/passport-local/blob/master/CONTRIBUTING.md) guidelines.
38 | - [ ] I have added test cases which verify the correct operation of this feature or patch.
39 | - [ ] I have added documentation pertaining to this feature or patch.
40 | - [ ] The automated test suite (`$ make test`) executes successfully.
41 | - [ ] The automated code linting (`$ make lint`) executes successfully.
42 |
--------------------------------------------------------------------------------
/.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 | - "11"
4 | - "10"
5 | - "9"
6 | - "8"
7 | - "7"
8 | - "6"
9 | - "5"
10 | - "4"
11 | - "3" # io.js
12 | - "2" # io.js
13 | - "1" # io.js
14 | - "0.12"
15 | - "0.10"
16 | - "0.8"
17 |
18 |
19 | # NOTE: `istanbul` and `coveralls` are pinned for compatibility with node 0.8.
20 | before_install:
21 | - "npm install -g istanbul@0.2.2"
22 | - "npm install -g coveralls@2.11.4"
23 |
24 | script:
25 | - "make check"
26 |
27 | after_success:
28 | - "make report-cov"
29 |
30 | sudo: false
31 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | ### Tests
4 |
5 | The test suite is located in the `test/` directory. All new features are
6 | expected to have corresponding test cases with complete code coverage. Patches
7 | that increase test coverage are happily accepted.
8 |
9 | Ensure that the test suite passes by executing:
10 |
11 | ```bash
12 | $ make test
13 | ```
14 |
15 | Coverage reports can be generated and viewed by executing:
16 |
17 | ```bash
18 | $ make test-cov
19 | $ make view-cov
20 | ```
21 |
--------------------------------------------------------------------------------
/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 | include node_modules/make-node/main.mk
2 |
3 | MOCHAFLAGS = --require ./test/bootstrap/node
4 | JSDOCFLAGS = -c etc/conf.json
5 |
6 |
7 | # Perform self-tests.
8 | check: test
9 |
10 | apidoc: $(SOURCES)
11 | $(JSDOC) $(JSDOCFLAGS) -t node_modules/@www.passportjs.org/jsdoc-template -d wwwhtml $^
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # passport-local
2 |
3 | [Passport](https://www.passportjs.org/) strategy for authenticating with a
4 | username and password.
5 |
6 | This module lets you authenticate using a username and password in your Node.js
7 | applications. By plugging into Passport, password-based sign in can be easily
8 | and unobtrusively integrated into any application or framework that supports
9 | [Connect](https://github.com/senchalabs/connect#readme)-style middleware, including
10 | [Express](https://expressjs.com/).
11 |
12 |
13 |
14 | :seedling: [Tutorial](https://www.passportjs.org/tutorials/password/?utm_source=github&utm_medium=referral&utm_campaign=passport-local&utm_content=nav-tutorial) •
15 | :dart: [How-to](https://www.passportjs.org/howtos/password/?utm_source=github&utm_medium=referral&utm_campaign=passport-local&utm_content=nav-howto) •
16 | :hammer_and_wrench: [API Reference](https://www.passportjs.org/api/passport-local/1.x/?utm_source=github&utm_medium=referral&utm_campaign=passport-local&utm_content=nav-api) •
17 | :heart: [Sponsors](https://www.passportjs.org/sponsors/?utm_source=github&utm_medium=referral&utm_campaign=passport-local&utm_content=nav-sponsors)
18 |
19 |
20 |
21 | ---
22 |
23 |
24 | Advertisement
25 |
26 | 1Password, the only password manager you should trust. Industry-leading security and award winning design.
27 |
28 |
29 | ---
30 |
31 | [](https://www.npmjs.com/package/passport-local)
32 | [](https://travis-ci.org/jaredhanson/passport-local)
33 | [](https://coveralls.io/github/jaredhanson/passport-local)
34 | [...](https://github.com/jaredhanson/passport-local/wiki/Status)
35 |
36 | ## Install
37 |
38 | ```bash
39 | $ npm install passport-local
40 | ```
41 |
42 | ## Usage
43 |
44 | #### Configure Strategy
45 |
46 | The local authentication strategy authenticates users using a username and
47 | password. The strategy requires a `verify` callback, which accepts these
48 | credentials and calls `done` providing a user.
49 |
50 | ```js
51 | passport.use(new LocalStrategy(
52 | function(username, password, done) {
53 | User.findOne({ username: username }, function (err, user) {
54 | if (err) { return done(err); }
55 | if (!user) { return done(null, false); }
56 | if (!user.verifyPassword(password)) { return done(null, false); }
57 | return done(null, user);
58 | });
59 | }
60 | ));
61 | ```
62 |
63 | ##### Available Options
64 |
65 | This strategy takes an optional options hash before the function, e.g. `new LocalStrategy({/* options */, callback})`.
66 |
67 | The available options are:
68 |
69 | * `usernameField` - Optional, defaults to 'username'
70 | * `passwordField` - Optional, defaults to 'password'
71 |
72 | Both fields define the name of the properties in the POST body that are sent to the server.
73 |
74 | #### Parameters
75 |
76 | By default, `LocalStrategy` expects to find credentials in parameters
77 | named username and password. If your site prefers to name these fields
78 | differently, options are available to change the defaults.
79 |
80 | passport.use(new LocalStrategy({
81 | usernameField: 'email',
82 | passwordField: 'passwd',
83 | session: false
84 | },
85 | function(username, password, done) {
86 | // ...
87 | }
88 | ));
89 |
90 | When session support is not necessary, it can be safely disabled by
91 | setting the `session` option to false.
92 |
93 | The verify callback can be supplied with the `request` object by setting
94 | the `passReqToCallback` option to true, and changing callback arguments
95 | accordingly.
96 |
97 | passport.use(new LocalStrategy({
98 | usernameField: 'email',
99 | passwordField: 'passwd',
100 | passReqToCallback: true,
101 | session: false
102 | },
103 | function(req, username, password, done) {
104 | // request object is now first argument
105 | // ...
106 | }
107 | ));
108 |
109 | #### Authenticate Requests
110 |
111 | Use `passport.authenticate()`, specifying the `'local'` strategy, to
112 | authenticate requests.
113 |
114 | For example, as route middleware in an [Express](http://expressjs.com/)
115 | application:
116 |
117 | ```js
118 | app.post('/login',
119 | passport.authenticate('local', { failureRedirect: '/login' }),
120 | function(req, res) {
121 | res.redirect('/');
122 | });
123 | ```
124 |
125 | ## Examples
126 |
127 | * [express-4.x-local-example](https://github.com/passport/express-4.x-local-example)
128 |
129 | Illustrates how to use the password strategy within an [Express](https://expressjs.com)
130 | application.
131 |
132 | Additional examples can be found on the [wiki](https://github.com/jaredhanson/passport-local/wiki/Examples).
133 |
134 | ## License
135 |
136 | [The MIT License](http://opensource.org/licenses/MIT)
137 |
138 | Copyright (c) 2011-2015 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)>
139 |
--------------------------------------------------------------------------------
/etc/conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["plugins/markdown"]
3 | }
4 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The `passport-local` module provides a {@link https://www.passportjs.org/ Passport}
3 | * strategy for authenticating a username and password.
4 | *
5 | * @module passport-local
6 | */
7 |
8 |
9 | // Module dependencies.
10 | var Strategy = require('./strategy');
11 |
12 | /*
13 | * `{@link Strategy}` constructor.
14 | *
15 | * @type {function}
16 | */
17 | exports = module.exports = Strategy;
18 |
19 | /*
20 | * `{@link Strategy}` constructor.
21 | *
22 | * @type {function}
23 | */
24 | exports.Strategy = Strategy;
25 |
--------------------------------------------------------------------------------
/lib/strategy.js:
--------------------------------------------------------------------------------
1 | // Module dependencies.
2 | var passport = require('passport-strategy')
3 | , util = require('util')
4 | , lookup = require('./utils').lookup;
5 |
6 | /**
7 | * Create a new `Strategy` object.
8 | *
9 | * @classdesc This `Strategy` authenticates requests that carry a username and
10 | * password in the body of the request. These credentials are typically
11 | * submitted by the user via an HTML form.
12 | *
13 | * @public
14 | * @class
15 | * @augments base.Strategy
16 | * @param {Object} [options]
17 | * @param {string} [options.usernameField='username'] - Form field name where
18 | * the username is found.
19 | * @param {string} [options.passwordField='password'] - Form field name where
20 | * the password is found.
21 | * @param {boolean} [options.passReqToCallback=false] - When `true`, the
22 | * `verify` function receives the request object as the first argument,
23 | * in accordance with `{@link Strategy~verifyWithReqFn}`.
24 | * @param {Strategy~verifyFn|Strategy~verifyWithReqFn} verify - Function which
25 | * verifies username and password.
26 | *
27 | * @example
28 | * var LocalStrategy = require('passport-local').Strategy;
29 | *
30 | * new LocalStrategy(function(username, password, cb) {
31 | * users.findOne({ username: username }, function(err, user) {
32 | * if (err) { return cb(err); }
33 | * if (!user) { return cb(null, false, { message: 'Incorrect username or password.' }); }
34 | *
35 | * crypto.pbkdf2(password, user.salt, 310000, 32, 'sha256', function(err, hashedPassword) {
36 | * if (err) { return cb(err); }
37 | * if (!crypto.timingSafeEqual(user.hashedPassword, hashedPassword)) {
38 | * return cb(null, false, { message: 'Incorrect username or password.' });
39 | * }
40 | * return cb(null, user);
41 | * });
42 | * });
43 | * });
44 | *
45 | * @example Construct strategy using top-level export.
46 | * var LocalStrategy = require('passport-local');
47 | *
48 | * new LocalStrategy(function(username, password, cb) {
49 | * // ...
50 | * });
51 | */
52 | function Strategy(options, verify) {
53 | if (typeof options == 'function') {
54 | verify = options;
55 | options = {};
56 | }
57 | if (!verify) { throw new TypeError('LocalStrategy requires a verify callback'); }
58 |
59 | this._usernameField = options.usernameField || 'username';
60 | this._passwordField = options.passwordField || 'password';
61 |
62 | passport.Strategy.call(this);
63 |
64 | /** The name of the strategy, which is set to `'local'`.
65 | *
66 | * @type {string}
67 | * @readonly
68 | */
69 | this.name = 'local';
70 | this._verify = verify;
71 | this._passReqToCallback = options.passReqToCallback;
72 | }
73 |
74 | // Inherit from `passport.Strategy`.
75 | util.inherits(Strategy, passport.Strategy);
76 |
77 | /**
78 | * Authenticate request by verifying username and password.
79 | *
80 | * This function is protected, and should not be called directly. Instead,
81 | * use `passport.authenticate()` middleware and specify the {@link Strategy#name `name`}
82 | * of this strategy and any options.
83 | *
84 | * @protected
85 | * @param {http.IncomingMessage} req - The Node.js {@link https://nodejs.org/api/http.html#class-httpincomingmessage `IncomingMessage`}
86 | * object.
87 | * @param {Object} [options]
88 | * @param {string} [options.badRequestMessage='Missing credentials'] - Message
89 | * to display when a request does not include a username or password.
90 | * Used in conjunction with `failureMessage` or `failureFlash` options.
91 | *
92 | * @example
93 | * passport.authenticate('local');
94 | */
95 | Strategy.prototype.authenticate = function(req, options) {
96 | options = options || {};
97 | var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField);
98 | var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField);
99 |
100 | if (!username || !password) {
101 | return this.fail({ message: options.badRequestMessage || 'Missing credentials' }, 400);
102 | }
103 |
104 | var self = this;
105 |
106 | function verified(err, user, info) {
107 | if (err) { return self.error(err); }
108 | if (!user) { return self.fail(info); }
109 | self.success(user, info);
110 | }
111 |
112 | try {
113 | if (self._passReqToCallback) {
114 | this._verify(req, username, password, verified);
115 | } else {
116 | this._verify(username, password, verified);
117 | }
118 | } catch (ex) {
119 | return self.error(ex);
120 | }
121 | };
122 |
123 | // Export `Strategy`.
124 | module.exports = Strategy;
125 |
126 |
127 | /**
128 | * Verifies `username` and `password` and yields authenticated user.
129 | *
130 | * This function is called by `{@link Strategy}` to verify a username and
131 | * password, and must invoke `cb` to yield the result.
132 | *
133 | * @callback Strategy~verifyFn
134 | * @param {string} username - The username received in the request.
135 | * @param {string} password - The passport received in the request.
136 | * @param {function} cb
137 | * @param {?Error} cb.err - An `Error` if an error occured; otherwise `null`.
138 | * @param {Object|boolean} cb.user - An `Object` representing the authenticated
139 | * user if verification was successful; otherwise `false`.
140 | * @param {Object} cb.info - Additional application-specific context that will be
141 | * passed through for further request processing.
142 | */
143 |
144 | /**
145 | * Verifies `username` and `password` and yields authenticated user.
146 | *
147 | * This function is called by `{@link Strategy}` to verify a username and
148 | * password when the `passReqToCallback` option is set, and must invoke `cb` to
149 | * yield the result.
150 | *
151 | * @callback Strategy~verifyWithReqFn
152 | * @param {http.IncomingMessage} req - The Node.js {@link https://nodejs.org/api/http.html#class-httpincomingmessage `IncomingMessage`}
153 | * object.
154 | * @param {string} username - The username received in the request.
155 | * @param {string} password - The passport received in the request.
156 | * @param {function} cb
157 | * @param {?Error} cb.err - An `Error` if an error occured; otherwise `null`.
158 | * @param {Object|boolean} cb.user - An `Object` representing the authenticated
159 | * user if verification was successful; otherwise `false`.
160 | * @param {Object} cb.info - Additional application-specific context that will be
161 | * passed through for further request processing.
162 | */
163 |
--------------------------------------------------------------------------------
/lib/utils.js:
--------------------------------------------------------------------------------
1 | exports.lookup = function(obj, field) {
2 | if (!obj) { return null; }
3 | var chain = field.split(']').join('').split('[');
4 | for (var i = 0, len = chain.length; i < len; i++) {
5 | var prop = obj[chain[i]];
6 | if (typeof(prop) === 'undefined') { return null; }
7 | if (typeof(prop) !== 'object') { return prop; }
8 | obj = prop;
9 | }
10 | return null;
11 | };
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "passport-local",
3 | "version": "1.0.0",
4 | "description": "Local username and password authentication strategy for Passport.",
5 | "keywords": [
6 | "passport",
7 | "local",
8 | "auth",
9 | "authn",
10 | "authentication",
11 | "username",
12 | "password"
13 | ],
14 | "author": {
15 | "name": "Jared Hanson",
16 | "email": "jaredhanson@gmail.com",
17 | "url": "http://www.jaredhanson.net/"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git://github.com/jaredhanson/passport-local.git"
22 | },
23 | "bugs": {
24 | "url": "http://github.com/jaredhanson/passport-local/issues"
25 | },
26 | "funding": {
27 | "type": "github",
28 | "url": "https://github.com/sponsors/jaredhanson"
29 | },
30 | "license": "MIT",
31 | "licenses": [
32 | {
33 | "type": "MIT",
34 | "url": "http://www.opensource.org/licenses/MIT"
35 | }
36 | ],
37 | "main": "./lib",
38 | "dependencies": {
39 | "passport-strategy": "1.x.x"
40 | },
41 | "devDependencies": {
42 | "make-node": "0.4.6",
43 | "mocha": "2.x.x",
44 | "chai": "2.x.x",
45 | "chai-passport-strategy": "0.1.x"
46 | },
47 | "engines": {
48 | "node": ">= 0.4.0"
49 | },
50 | "scripts": {
51 | "test": "make test"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/test/bootstrap/node.js:
--------------------------------------------------------------------------------
1 | var chai = require('chai');
2 |
3 | chai.use(require('chai-passport-strategy'));
4 |
5 | global.expect = chai.expect;
6 |
--------------------------------------------------------------------------------
/test/package.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect */
2 |
3 | var strategy = require('..');
4 |
5 | describe('passport-local', 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 | });
13 |
--------------------------------------------------------------------------------
/test/strategy.error.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect, before */
2 |
3 | var chai = require('chai')
4 | , Strategy = require('../lib/strategy');
5 |
6 |
7 | describe('Strategy', function() {
8 |
9 | describe('encountering an error during verification', function() {
10 | var strategy = new Strategy(function(username, password, done) {
11 | done(new Error('something went wrong'));
12 | });
13 |
14 | var err;
15 |
16 | before(function(done) {
17 | chai.passport(strategy)
18 | .error(function(e) {
19 | err = e;
20 | done();
21 | })
22 | .req(function(req) {
23 | req.body = {};
24 | req.body.username = 'johndoe';
25 | req.body.password = 'secret';
26 | })
27 | .authenticate();
28 | });
29 |
30 | it('should error', function() {
31 | expect(err).to.be.an.instanceof(Error);
32 | expect(err.message).to.equal('something went wrong');
33 | });
34 | });
35 |
36 | describe('encountering an exception during verification', function() {
37 | var strategy = new Strategy(function(username, password, done) {
38 | throw new Error('something went horribly wrong');
39 | });
40 |
41 | var err;
42 |
43 | before(function(done) {
44 | chai.passport(strategy)
45 | .error(function(e) {
46 | err = e;
47 | done();
48 | })
49 | .req(function(req) {
50 | req.body = {};
51 | req.body.username = 'johndoe';
52 | req.body.password = 'secret';
53 | })
54 | .authenticate();
55 | });
56 |
57 | it('should error', function() {
58 | expect(err).to.be.an.instanceof(Error);
59 | expect(err.message).to.equal('something went horribly wrong');
60 | });
61 | });
62 |
63 | });
64 |
--------------------------------------------------------------------------------
/test/strategy.fail.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect, before */
2 | /* jshint expr: true */
3 |
4 | var chai = require('chai')
5 | , Strategy = require('../lib/strategy');
6 |
7 |
8 | describe('Strategy', function() {
9 |
10 | describe('failing authentication', function() {
11 | var strategy = new Strategy(function(username, password, done) {
12 | return done(null, false);
13 | });
14 |
15 | var info;
16 |
17 | before(function(done) {
18 | chai.passport(strategy)
19 | .fail(function(i) {
20 | info = i;
21 | done();
22 | })
23 | .req(function(req) {
24 | req.body = {};
25 | req.body.username = 'johndoe';
26 | req.body.password = 'secret';
27 | })
28 | .authenticate();
29 | });
30 |
31 | it('should fail', function() {
32 | expect(info).to.be.undefined;
33 | });
34 | });
35 |
36 | describe('failing authentication with info', function() {
37 | var strategy = new Strategy(function(username, password, done) {
38 | return done(null, false, { message: 'authentication failed' });
39 | });
40 |
41 | var info;
42 |
43 | before(function(done) {
44 | chai.passport(strategy)
45 | .fail(function(i) {
46 | info = i;
47 | done();
48 | })
49 | .req(function(req) {
50 | req.body = {};
51 | req.body.username = 'johndoe';
52 | req.body.password = 'secret';
53 | })
54 | .authenticate();
55 | });
56 |
57 | it('should fail', function() {
58 | expect(info).to.be.an('object');
59 | expect(info.message).to.equal('authentication failed');
60 | });
61 | });
62 |
63 | });
64 |
--------------------------------------------------------------------------------
/test/strategy.fields.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect, before */
2 | /* jshint expr: true */
3 |
4 | var chai = require('chai')
5 | , Strategy = require('../lib/strategy');
6 |
7 |
8 | describe('Strategy', function() {
9 |
10 | describe('handling a request with valid credentials in body using custom field names', function() {
11 | var strategy = new Strategy({ usernameField: 'userid', passwordField: 'passwd' }, function(username, password, done) {
12 | if (username == 'johndoe' && password == 'secret') {
13 | return done(null, { id: '1234' }, { scope: 'read' });
14 | }
15 | return done(null, false);
16 | });
17 |
18 | var user
19 | , info;
20 |
21 | before(function(done) {
22 | chai.passport(strategy)
23 | .success(function(u, i) {
24 | user = u;
25 | info = i;
26 | done();
27 | })
28 | .req(function(req) {
29 | req.body = {};
30 | req.body.userid = 'johndoe';
31 | req.body.passwd = 'secret';
32 | })
33 | .authenticate();
34 | });
35 |
36 | it('should supply user', function() {
37 | expect(user).to.be.an.object;
38 | expect(user.id).to.equal('1234');
39 | });
40 |
41 | it('should supply info', function() {
42 | expect(info).to.be.an.object;
43 | expect(info.scope).to.equal('read');
44 | });
45 | });
46 |
47 | describe('handling a request with valid credentials in body using custom field names with object notation', function() {
48 | var strategy = new Strategy({ usernameField: 'user[username]', passwordField: 'user[password]' }, function(username, password, done) {
49 | if (username == 'johndoe' && password == 'secret') {
50 | return done(null, { id: '1234' }, { scope: 'read' });
51 | }
52 | return done(null, false);
53 | });
54 |
55 | var user
56 | , info;
57 |
58 | before(function(done) {
59 | chai.passport(strategy)
60 | .success(function(u, i) {
61 | user = u;
62 | info = i;
63 | done();
64 | })
65 | .req(function(req) {
66 | req.body = {};
67 | req.body.user = {};
68 | req.body.user.username = 'johndoe';
69 | req.body.user.password = 'secret';
70 | })
71 | .authenticate();
72 | });
73 |
74 | it('should supply user', function() {
75 | expect(user).to.be.an.object;
76 | expect(user.id).to.equal('1234');
77 | });
78 |
79 | it('should supply info', function() {
80 | expect(info).to.be.an.object;
81 | expect(info.scope).to.equal('read');
82 | });
83 | });
84 |
85 | });
86 |
--------------------------------------------------------------------------------
/test/strategy.normal.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect, before */
2 | /* jshint expr: true */
3 |
4 | var chai = require('chai')
5 | , Strategy = require('../lib/strategy');
6 |
7 |
8 | describe('Strategy', function() {
9 |
10 | describe('handling a request with valid credentials in body', function() {
11 | var strategy = new Strategy(function(username, password, done) {
12 | if (username == 'johndoe' && password == 'secret') {
13 | return done(null, { id: '1234' }, { scope: 'read' });
14 | }
15 | return done(null, false);
16 | });
17 |
18 | var user
19 | , info;
20 |
21 | before(function(done) {
22 | chai.passport(strategy)
23 | .success(function(u, i) {
24 | user = u;
25 | info = i;
26 | done();
27 | })
28 | .req(function(req) {
29 | req.body = {};
30 | req.body.username = 'johndoe';
31 | req.body.password = 'secret';
32 | })
33 | .authenticate();
34 | });
35 |
36 | it('should supply user', function() {
37 | expect(user).to.be.an.object;
38 | expect(user.id).to.equal('1234');
39 | });
40 |
41 | it('should supply info', function() {
42 | expect(info).to.be.an.object;
43 | expect(info.scope).to.equal('read');
44 | });
45 | });
46 |
47 | describe('handling a request with valid credentials in query', function() {
48 | var strategy = new Strategy(function(username, password, done) {
49 | if (username == 'johndoe' && password == 'secret') {
50 | return done(null, { id: '1234' }, { scope: 'read' });
51 | }
52 | return done(null, false);
53 | });
54 |
55 | var user
56 | , info;
57 |
58 | before(function(done) {
59 | chai.passport(strategy)
60 | .success(function(u, i) {
61 | user = u;
62 | info = i;
63 | done();
64 | })
65 | .req(function(req) {
66 | req.query = {};
67 | req.query.username = 'johndoe';
68 | req.query.password = 'secret';
69 | })
70 | .authenticate();
71 | });
72 |
73 | it('should supply user', function() {
74 | expect(user).to.be.an.object;
75 | expect(user.id).to.equal('1234');
76 | });
77 |
78 | it('should supply info', function() {
79 | expect(info).to.be.an.object;
80 | expect(info.scope).to.equal('read');
81 | });
82 | });
83 |
84 | describe('handling a request without a body', function() {
85 | var strategy = new Strategy(function(username, password, done) {
86 | throw new Error('should not be called');
87 | });
88 |
89 | var info, status;
90 |
91 | before(function(done) {
92 | chai.passport(strategy)
93 | .fail(function(i, s) {
94 | info = i;
95 | status = s;
96 | done();
97 | })
98 | .authenticate();
99 | });
100 |
101 | it('should fail with info and status', function() {
102 | expect(info).to.be.an.object;
103 | expect(info.message).to.equal('Missing credentials');
104 | expect(status).to.equal(400);
105 | });
106 | });
107 |
108 | describe('handling a request without a body, but no username and password', function() {
109 | var strategy = new Strategy(function(username, password, done) {
110 | throw new Error('should not be called');
111 | });
112 |
113 | var info, status;
114 |
115 | before(function(done) {
116 | chai.passport(strategy)
117 | .fail(function(i, s) {
118 | info = i;
119 | status = s;
120 | done();
121 | })
122 | .req(function(req) {
123 | req.body = {};
124 | })
125 | .authenticate();
126 | });
127 |
128 | it('should fail with info and status', function() {
129 | expect(info).to.be.an.object;
130 | expect(info.message).to.equal('Missing credentials');
131 | expect(status).to.equal(400);
132 | });
133 | });
134 |
135 | describe('handling a request without a body, but no password', function() {
136 | var strategy = new Strategy(function(username, password, done) {
137 | throw new Error('should not be called');
138 | });
139 |
140 | var info, status;
141 |
142 | before(function(done) {
143 | chai.passport(strategy)
144 | .fail(function(i, s) {
145 | info = i;
146 | status = s;
147 | done();
148 | })
149 | .req(function(req) {
150 | req.body = {};
151 | req.body.username = 'johndoe';
152 | })
153 | .authenticate();
154 | });
155 |
156 | it('should fail with info and status', function() {
157 | expect(info).to.be.an.object;
158 | expect(info.message).to.equal('Missing credentials');
159 | expect(status).to.equal(400);
160 | });
161 | });
162 |
163 | describe('handling a request without a body, but no username', function() {
164 | var strategy = new Strategy(function(username, password, done) {
165 | throw new Error('should not be called');
166 | });
167 |
168 | var info, status;
169 |
170 | before(function(done) {
171 | chai.passport(strategy)
172 | .fail(function(i, s) {
173 | info = i;
174 | status = s;
175 | done();
176 | })
177 | .req(function(req) {
178 | req.body = {};
179 | req.body.password = 'secret';
180 | })
181 | .authenticate();
182 | });
183 |
184 | it('should fail with info and status', function() {
185 | expect(info).to.be.an.object;
186 | expect(info.message).to.equal('Missing credentials');
187 | expect(status).to.equal(400);
188 | });
189 | });
190 |
191 | });
192 |
--------------------------------------------------------------------------------
/test/strategy.options.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect, before */
2 | /* jshint expr: true */
3 |
4 | var chai = require('chai')
5 | , Strategy = require('../lib/strategy');
6 |
7 |
8 | describe('Strategy', function() {
9 |
10 | describe('handling a request without a body, but no username and password, with message option to authenticate', function() {
11 | var strategy = new Strategy(function(username, password, done) {
12 | throw new Error('should not be called');
13 | });
14 |
15 | var info, status;
16 |
17 | before(function(done) {
18 | chai.passport(strategy)
19 | .fail(function(i, s) {
20 | info = i;
21 | status = s;
22 | done();
23 | })
24 | .req(function(req) {
25 | req.body = {};
26 | })
27 | .authenticate({ badRequestMessage: 'Something is wrong with this request' });
28 | });
29 |
30 | it('should fail with info and status', function() {
31 | expect(info).to.be.an.object;
32 | expect(info.message).to.equal('Something is wrong with this request');
33 | expect(status).to.equal(400);
34 | });
35 | });
36 |
37 | });
38 |
--------------------------------------------------------------------------------
/test/strategy.passreq.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect, before */
2 | /* jshint expr: true */
3 |
4 | var chai = require('chai')
5 | , Strategy = require('../lib/strategy');
6 |
7 |
8 | describe('Strategy', function() {
9 |
10 | describe('passing request to verify callback', function() {
11 | var strategy = new Strategy({passReqToCallback: true}, function(req, username, password, done) {
12 | if (username == 'johndoe' && password == 'secret') {
13 | return done(null, { id: '1234' }, { scope: 'read', foo: req.headers['x-foo'] });
14 | }
15 | return done(null, false);
16 | });
17 |
18 | var user
19 | , info;
20 |
21 | before(function(done) {
22 | chai.passport(strategy)
23 | .success(function(u, i) {
24 | user = u;
25 | info = i;
26 | done();
27 | })
28 | .req(function(req) {
29 | req.headers['x-foo'] = 'hello';
30 |
31 | req.body = {};
32 | req.body.username = 'johndoe';
33 | req.body.password = 'secret';
34 | })
35 | .authenticate();
36 | });
37 |
38 | it('should supply user', function() {
39 | expect(user).to.be.an.object;
40 | expect(user.id).to.equal('1234');
41 | });
42 |
43 | it('should supply info', function() {
44 | expect(info).to.be.an.object;
45 | expect(info.scope).to.equal('read');
46 | });
47 |
48 | it('should supply request header in info', function() {
49 | expect(info.foo).to.equal('hello');
50 | });
51 | });
52 |
53 | });
54 |
--------------------------------------------------------------------------------
/test/strategy.test.js:
--------------------------------------------------------------------------------
1 | /* global describe, it, expect */
2 |
3 | var Strategy = require('../lib/strategy');
4 |
5 |
6 | describe('Strategy', function() {
7 |
8 | var strategy = new Strategy(function(){});
9 |
10 | it('should be named local', function() {
11 | expect(strategy.name).to.equal('local');
12 | });
13 |
14 | it('should throw if constructed without a verify callback', function() {
15 | expect(function() {
16 | var s = new Strategy();
17 | }).to.throw(TypeError, 'LocalStrategy requires a verify callback');
18 | });
19 |
20 | });
21 |
--------------------------------------------------------------------------------