Skip to content

Commit 3e8e581

Browse files
committed
Allow to overwrite implementation details based on the request.connection
This commit introduces three new methods to the options, providing the developer using the middleware with the ability to modify how the NTLM user data and proxy cache ID are stored. This enhancement enables the middleware to be used with a (reverse) proxy if the application can supply a unique identifier for the user. The default behavior of storing the user data and proxy cache ID on the request.connection is maintained as the default value for the new options.
1 parent 89fee6a commit 3e8e581

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ It's not recommended, but it's possible to add NTLM-Authentication without valid
9898
| `domaincontroller` | `null` / `string` / `array` | `null` | One or more domaincontroller(s) to handle the authentication. If `null` is specified the user is not validated. Active Directory is supported. |
9999
| `tlsOptions` | `object` | `undefined` | An options object that will be passed to [tls.connect](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) and [tls.createSecureContext](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options). __Only required when using ldaps and the server's certificate is signed by a certificate authority not in Node's default list of CAs.__ (or use [NODE_EXTRA_CA_CERTS](https://nodejs.org/api/cli.html#cli_node_extra_ca_certs_file) environment variable)|
100100
| `tlsOptions.ca` | `string` / `array` / `Buffer` | `undefined` | Override the trusted CA certificates provided by Node. Refer to [tls.createSecureContext](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) |
101-
| `getConnectionId` | `function` | `function(request, response) { return utils.uuidv4(); }` | Function to generate custom connection IDs, based optionally on the request and response objects. |
101+
| `getConnectionId` | `function` | `function(request, response) { return utils.uuidv4(); }` | Function to generate custom connection IDs, based optionally on the request and response objects. Used by the default implementation of `getProxyId` to keep backwards compatibility. *deprecated* |
102+
| `getProxyId` | `function` | `function(request, response) { if (!request.connection.id) { request.connection.id = options.getConnectionId(request, response); } return request.connection.id; }` | Function to generate custom proxy cache IDs, based optionally on the request and response objects. |
103+
| `getCachedUserData` | `function` | `function(request, response) { return request.connection.ntlm; }` | Function to return the cached NTLM user data. |
104+
| `addCachedUserData` | `function` | `function(request, response, userData) { request.connection.ntlm = userData; }` | Function to cache the NTLM user data. |
102105

103106
## logging (examples)
104107
<a name="logging" />

lib/express-ntlm.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ module.exports = function(options) {
4343

4444
getConnectionId(request, response) {
4545
return utils.uuidv4();
46+
},
47+
48+
getProxyId(request, response) {
49+
if (!request.connection.id) {
50+
request.connection.id = options.getConnectionId(request, response);
51+
}
52+
53+
return request.connection.id;
54+
},
55+
56+
getCachedUserData(request, response) {
57+
return request.connection.ntlm;
58+
},
59+
addCachedUserData(request, response, userData) {
60+
request.connection.ntlm = userData;
4661
}
4762
}, options);
4863

@@ -137,7 +152,9 @@ module.exports = function(options) {
137152
}
138153

139154
function handle_type1(request, response, next, ntlm_message, callback) {
140-
cache.remove(request.connection.id);
155+
var proxyId = options.getProxyId(request, response);
156+
157+
cache.remove(proxyId);
141158
cache.clean();
142159

143160
connect_to_proxy(ntlm_message, function(error, proxy, challenge) {
@@ -147,14 +164,15 @@ module.exports = function(options) {
147164
response.setHeader('WWW-Authenticate', 'NTLM ' + challenge.toString('base64'));
148165
response.end();
149166

150-
cache.add(request.connection.id, proxy);
167+
cache.add(proxyId, proxy);
151168

152169
return callback();
153170
});
154171
}
155172

156173
function handle_type3(request, response, next, ntlm_message, callback) {
157-
var proxy = cache.get_proxy(request.connection.id);
174+
var proxyId = options.getProxyId(request, response),
175+
proxy = cache.get_proxy(proxyId);
158176

159177
var userDomainWorkstation = parse_ntlm_authenticate(ntlm_message),
160178
user = userDomainWorkstation[0],
@@ -176,10 +194,10 @@ module.exports = function(options) {
176194

177195
request.ntlm = userData;
178196
response.locals.ntlm = userData;
179-
request.connection.ntlm = userData;
197+
options.addCachedUserData(request, response, userData);
180198

181199
if (!result) {
182-
cache.remove(request.connection.id);
200+
cache.remove(proxyId);
183201
options.debug(options.prefix, 'User ' + domain + '/' + user + ' authentication for URI ' + request.protocol + '://' + request.get('host') + request.originalUrl);
184202
return options.forbidden(request, response, next);
185203
} else {
@@ -190,13 +208,9 @@ module.exports = function(options) {
190208
}
191209

192210
return function(request, response, next) {
193-
if (!request.connection.id) {
194-
request.connection.id = options.getConnectionId(request, response);
195-
}
196-
197211
var auth_headers = request.headers.authorization;
198212

199-
var user = request.connection.ntlm;
213+
var user = options.getCachedUserData(request, response);
200214
if (user && user.Authenticated) {
201215
options.debug(options.prefix, 'Connection already authenticated ' + user.DomainName + '/' + user.UserName);
202216
if (auth_headers) {
@@ -241,7 +255,7 @@ module.exports = function(options) {
241255
}
242256

243257
if (ntlm_version === 3) {
244-
if (cache.get_proxy(request.connection.id) !== null) {
258+
if (cache.get_proxy(options.getProxyId(request, response)) !== null) {
245259
return handle_type3(request, response, next, ah_data[1], function(error) {
246260
if (error) {
247261
options.debug(options.prefix, error.stack);

0 commit comments

Comments
 (0)