-
Notifications
You must be signed in to change notification settings - Fork 0
/
authenticator.js
111 lines (93 loc) · 2.78 KB
/
authenticator.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
'use strict'
/**
* Abstract base class implementing the common http authentication logic.
*
* @constructs Authenticator
* @param {Function} identify - A function performing the password lookup.
*/
var Authenticator = function (identify) {
this.identify = identify;
};
/**
* Authenticate a request.
*
* @description This function expects additional `success` and `fail` callbacks
* to be defined on the `this` object. It will call the first one in case of a
* succesful authentication, otherwise the second one will be called.
*
* @param {http.IncomingMessage} req - The request to be authenticated.
* @param {Object} options - An object defining authentication options.
*/
Authenticator.prototype.authenticate = function (req, options) {
var that = this;
var fields;
var realm;
options = options || {};
realm = options.realm || '';
var done = function (error, password) {
if (that.check(fields, realm, password, req.method) !== true) {
that.fail(that.header(realm));
} else {
that.success(fields.username);
}
};
if (req.headers.authorization === undefined) {
// No authorization header was found in the request.
this.fail(this.header(realm));
} else {
fields = this.parse(req.headers.authorization);
if (fields.username === undefined) {
// Username is missing.
this.fail(this.header(realm));
} else {
// Call the user provided callback to get the password.
this.identify(fields.username, done);
}
}
};
/**
* Construct a function that can be used as a `http.Server` listener.
*
* @param {Object} options - An object defining authentication options.
* @param {Function} callback - An optional callback to be called after a
* succesful authentication.
* @returns {Function} A function accepting a request/response pair.
*/
Authenticator.prototype.listener = function (options, callback) {
var that = this;
if (options instanceof Function) {
callback = options;
options = undefined;
}
options = options || {};
return function (req, res) {
var local = Object.create(that);
local.success = function (user) {
callback(req, res);
};
local.fail = function (header) {
res.writeHead(401, {
'WWW-Authenticate': header
});
res.end('Unauthorized');
};
local.authenticate(req, options);
};
};
/**
* Construct a connect middleware.
*
* @param {Object} options - An object defining authentication options.
* @returns {Function} A connect middleware callback.
*/
Authenticator.prototype.connect = function (options) {
var that = this;
return function (req, res, next) {
var listener = that.listener(options, function () {
// Call next without arguments.
next();
});
listener(req, res);
}
};
module.exports = Authenticator;