/
strategy.js
120 lines (105 loc) · 3.99 KB
/
strategy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
* Module dependencies.
*/
var passport = require('passport')
, util = require('util')
, BadRequestError = require('./errors/badrequesterror');
/**
* `Strategy` constructor.
*
* The token authentication strategy authenticates requests based on the
* credentials submitted through standard request headers or body.
*
* Applications must supply a `verify` callback which accepts `username` and
* `token` credentials, and then calls the `done` callback supplying a
* `user`, which should be set to `false` if the credentials are not valid.
* If an exception occured, `err` should be set.
*
* Optionally, `options` can be used to change the fields in which the
* credentials are found.
*
* Options:
*
* - `usernameHeader` header name where the username is found, defaults to 'x-username'
* - `tokenHeader` header name where the token is found, defaults to 'x-token'
* - `usernameField` field name where the username is found, defaults to 'username'
* - `tokenField` field name where the password is found, defaults to 'password'
* - `usernameQuery` query string name where the username is found, defaults to 'username'
* - `tokenQuery` query string name where the password is found, defaults to 'password'
* - `passReqToCallback` when `true`, `req` is the first argument to the verify callback (default: `false`)
*
* Examples:
*
* passport.use(new TokenStrategy(
* function(username, token, done) {
* User.findOne({ username: username, token: token }, function (err, user) {
* done(err, user);
* });
* }
* ));
*
* @param {Object} options
* @param {Function} verify
* @api public
*/
function Strategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = {};
}
if (!verify) throw new Error('token authentication strategy requires a verify function');
this._usernameHeader = options.usernameHeader ? options.usernameHeader.toLowerCase() : 'x-username';
this._tokenHeader = options.tokenHeader ? options.tokenHeader.toLowerCase() : 'x-token';
this._usernameField = options.usernameField ? options.usernameField.toLowerCase() : 'username';
this._tokenField = options.tokenField ? options.tokenField.toLowerCase() : 'token';
this._usernameQuery = options.usernameQuery ? options.usernameQuery.toLowerCase() : this._usernameField;
this._tokenQuery = options.tokenQuery ? options.tokenQuery.toLowerCase() : this._tokenField;
passport.Strategy.call(this);
this.name = 'token';
this._verify = verify;
this._passReqToCallback = options.passReqToCallback;
}
/**
* Inherit from `passport.Strategy`.
*/
util.inherits(Strategy, passport.Strategy);
/**
* Authenticate request based on the contents of a form submission.
*
* @param {Object} req
* @api protected
*/
Strategy.prototype.authenticate = function(req, options) {
options = options || {};
var self = this;
var username = req.headers[this._usernameHeader] || lookup(req.body, this._usernameField) || lookup(req.query, this._usernameQuery);
var token = req.headers[this._tokenHeader] || lookup(req.body, this._tokenField) || lookup(req.query, this._tokenQuery);
if (!username || !token) {
return this.fail(new BadRequestError(options.badRequestMessage || 'Missing credentials'));
}
function verified(err, user, info) {
if (err) { return self.error(err); }
if (!user) { return self.fail(info); }
self.success(user, info);
}
if (self._passReqToCallback) {
this._verify(req, username, token, verified);
} else {
this._verify(username, token, verified);
}
function lookup(obj, field) {
if (!obj) { return null; }
var chain = field.split(']').join('').split('[');
for (var i = 0, len = chain.length; i < len; i++) {
var prop = obj[chain[i]];
if (typeof(prop) === 'undefined') { return null; }
if (typeof(prop) !== 'object') { return prop; }
obj = prop;
}
return null;
}
}
/**
* Expose `Strategy`.
*/
module.exports = Strategy;