gevorg / http-auth Goto Github PK
View Code? Open in Web Editor NEWNode.js package for HTTP basic and digest access authentication.
License: MIT License
Node.js package for HTTP basic and digest access authentication.
License: MIT License
After adding the http-auth
module to a project which uses http-proxy
, all existing calls to httpProxy.createProxyServer
are now failing during requests with TypeError: Cannot read property 'target' of undefined
. This occurs because the modified version provided by http-auth
passes the second argument to httpProxy.createProxyServer
as the only argument to the original function.
Although I understand it is possible to use http-auth
with http-proxy
and to pass the authentication mechanism as the first argument, I don't plan to do so because my current use case does not require proxied requests to be authenticated.
From the code, I assume the breakage for existing users of http-proxy
was unintentional and that the line at proxy.coffee:15 was intended to shift the arguments (it currently only removes argument 0, but doesn't renumber higher-numbered arguments).
Unfortunately, both fixing the issue and maintaining backwards compatibility with code which now passes a dummy first argument to the modified createProxyServer
may be a little tricky. Checking the number of arguments is probably workable, but is not perfect for users who may be passing extra arguments which currently have no effect or if a future version of http-proxy
introduces an additional argument (unlikely).
Thanks for considering,
Kevin
Why is this feature gone? Also basic.apply
is gone and it's a pain to create you're custom middleware.
For instance:
app.use(function(req, res, next) {
if(req.path == "/") return next();
auth.apply(req, res, function(username) {
return next();
});
});
I updated to the latest version and .apply is no longer available. This was very important to my app. Any way to get it back ?
Hey there,
Any chance you could expose the req object in the custom authenticate function? Currently I define the function as: function(username, password, callback).
It would be great if you could change it to: function(username, password, callback, req). This shouldn't break any previous versions.
The reason why I need access to the req object is because req.user being a string isn't good enough for my implementation. I need req.user to be a custom object. So whenever I enable skipUser in the config, I'd like to be able to manually define what req.user should be.
Is this something you could implement please? Or if I tried it myself (I've never used coffee script before), would you consider to merge it in?
Thanks
Hi,
Thanks for the very useful addition. I am trying to get the following to work. Any ideas on how to use http-auth and http-proxy together.
httpProxy.createServer(function (req, res, proxy) {
console.log("Here");
digest.apply(req, res, function() {
res.end("Welcome to private area!");
});
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 5984
});
}).listen(8000);
I get the following:
Express server listening on port 8081 in development mode
Here
http.js:573
throw new Error("Can't render headers after they are sent to the client.")
^
Error: Can't render headers after they are sent to the client.
at ServerResponse. (http.js:573:11)
at ServerResponse._renderHeaders (/opt/maxwell/admin/node_modules/express/node_modules/connect/lib/patch.js:76:25)
at ServerResponse.writeHead (http.js:816:20)
at ClientRequest. (/opt/maxwell/admin/node_modules/http-proxy/lib/node-http-proxy/http-proxy.js:214:9)
at ClientRequest.emit (events.js:67:17)
at HTTPParser.onIncoming (http.js:1217:11)
at HTTPParser.onHeadersComplete (http.js:102:31)
at Socket.ondata (http.js:1116:24)
at TCP.onread (net.js:314:27)
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area."
}, function (username, password, callback) { // Custom authentication
callback(username === "Tina" && password === "Bullock");
}
);
Such a callback function returns nothing but undefined
always. It cannot work.
Hi,
I've been following the example "http-proxy integration" and it works when manually inputting username and password upon opening a page! However, when I input a username and password for the proxy into iOS settings it just doesn't work. The idea will be to input the username & password only once. Any clue how to read this username & password? I've tried with basic and digest and couldn't get it to work. It just keeps asking for username and password.
Here's an example of the iOS proxy page
Thanks!
this is a great way to get an app quickly password protected.
But is there a way to use this to only protect some parts of the app?
eg we have an admin area we want locked down, but the rest of the app open to the public.
Alternatively could I create a proxy server that can add the needed auth headers, and proxy requests to an API that is protected by this?
tx
Cutting and pasting the example for http-proxy does not result in the ability to log into the server. Instead error messages gets displayed:
Chrome returns "Error 323 (net::ERR_UNEXPECTED_PROXY_AUTH): Unknown error."
Firefox returns "HTTP Error 407 Proxy authentication required"
I expected to see the browser pop up a login window asking for username and password, like what happens when I cut and paste the very first example.
My environment:
Node v0.8.20
http-proxy v0.10.2
http-auth v1.2.7
Basic authentication works fine but I don't get digest to work. My code looks like this (i'm calling both digest for convenience):
auth = require 'http-auth'
# basic
digest = auth(
authRealm: 'admin'
authType: 'basic'
authList: ['alfred:{SHA}x511ncXd+4fOnYAotcGPFD0peYo=']
)
# digest
digest = auth(
authRealm: 'admin'
authType: 'digest'
authList: ['alfred:admin:{SHA}x511ncXd+4fOnYAotcGPFD0peYo=']
)
# routes
app.get "/admin", digest.apply, admin.index
When I try digest the dialog just pops up again and again after filling in the details. Any idea as to why?
Thanks!
Hello,
Not so much an issue, but a request.
I would prefer to authenticate the digest against the database, is this possible?
Hi,
I just can find any documentation about the HTTP POST Method support.
Is it possible to use this plugin with POST method? (For me it seems to be not working.)
Thanks,
Gyula
env:
├── [email protected]
└── [email protected]
I tried getting digest to work based on the password generated with htdigest. My htpasswd file contains
[email protected]:$apr1$H4tbOI8z$pQmPE6KQJZxNVtK07t4sQ0
digestUser:Private area:357e30c93978ac34f7de39f152d38e3a
I was able to get basic authentication to work but not the digest authentication. I keep getting the same username password repeatedly.
I have added a script to show what works and what doesn't.
//Doesnt work
// based on http://www.sitepoint.com/http-authentication-in-node-js/
require('coffee-script-redux/register');
var auth = require('http-auth'),
http = require('http');
console.dir(auth);
var digest = auth.digest({
authRealm: "Private area",
authFile: __dirname + "/htpasswd"
});
var server = http.createServer( digest, function(req, res){
res.end("Welcome to private area - " + req.user + "!");
});
server.listen(1337);
console.log("Server is listening on 1337");
// Works
// var auth = require('http-auth'),
// http = require('http');
// var basic = auth.basic({
// realm: "Private Area.",
// file: __dirname + "/htpasswd"
// });
// // Creating new HTTP server.
// http.createServer(basic, function(req, res) {
// res.end("Welcome to private area - " + req.user + "!");
// }).listen(1337);
Hi and thanks for this module. I'm having trouble where it seems this module is using the same req.user as is the passport module for expressjs. Any ideas on how to get around this clashing? For example, I use this module to hide my site from the public while I'm working on it. I log in using the http auth, but now my site is confused cause it uses passport which reads from [i think] req.user also, so it thinks a user is logged into the website and tries to show their profile, etc.
When using the basic authentication method, the username seems to be ignored.
(Whitespace added for readability.)
http-auth$ node examples/example.js &
Server running at http://127.0.0.1:1337/
http-auth$ curl -u mia:supergirl http://localhost:1337/
Welcome to private area!
http-auth$ curl -u mia:upergirl http://localhost:1337/
<!DOCTYPE html>
<html><head><title>401 Unauthorized</title></head><body><h1>401 Unauthorized</h1><p>This page requires authorization.</p></body></html>
http-auth$ curl -u mi:supergirl http://localhost:1337/
Welcome to private area!
Add example documentation for route specific authentication in Express 4 to README. i.e. An example of using authentication in routes.js
RFC 2617 defines the "stale" server option that indicates to clients that the nonce was stale, and that the client should just re-encrypt the password with the new nonce. This should be done when the nonce was found to be missing, so that a restart doesn't cause all users to be challenged again.
If I use POST method for a route, URL always send 401 Unauthorized.
var app = require('express').createServer();
app.post('/request', function(req, res) {
expressAuth.apply(req, res, function(username) {
res.contentType('json');
res.send(JSON.stringify({'msg':'ok'}));
});
});
And it is the same, when I have a query in URL like http://url.com/request?var=value
var app = require('express').createServer();
app.get('/request', function(req, res) {
expressAuth.apply(req, res, function(username) {
res.contentType('json');
res.send(JSON.stringify({'msg':'ok'}));
});
});
So I want a secure route to send data, and I don't arrive to do this.
In digest.coffee, you initialize clientOptions to an empty array. Then do this:
clientOptions[name] = value;
Since clientOptions is initialized as an array, the array is just always returned as empty. I imagine you intend to initialize clientOptions as an object {}, but then i can't figure out how the rest of your app is suppose to work. "I'm also not particularly familiar with coffee script, so am struggling to follow it a little"
This is of course breaking any attempt to validate using an authentication header.
/home/jann/tmp/node_modules/http-auth/lib/util.js:25
hash.update(str);
^
TypeError: Not a string or buffer
at Object.md5 (/home/jann/tmp/node_modules/http-auth/lib/util.js:25:8)
at Digest.isAuthenticated (/home/jann/tmp/node_modules/http-auth/lib/auth/digest.js:95:19)
at IncomingMessage. (/home/jann/tmp/node_modules/http-auth/lib/auth/digest.js:58:29)
at IncomingMessage.emit (events.js:61:17)
at HTTPParser.onMessageComplete (http.js:133:23)
at Socket.ondata (http.js:1029:22)
at Socket._onReadable (net.js:683:27)
at IOWatcher.onReadable as callback
There is an error in Digest.prototype.parseAuthHeader:
var tokens = searchHeader.match(/(\w+)="([^"]+)"/g);
means that auth parameter values can't be empty but client actually might send empty cnonce which will result in undefined (instead of being empty) cnonce variable on server side.
Copying the example for http-proxy does not work as expected. It only shows this TypeError:
C:\Users\tester\node_modules\http-auth\lib\server\proxy.coffee:19
oldProxyRequest = server.proxy.proxyRequest;
^
TypeError: Cannot read property 'proxyRequest' of undefined
at Function.httpProxy.createServer (C:\Users\tester\node_modules\http-auth\lib\server\proxy.coffee:19:37)
at Object. (C:\Users\tester\Documents\Aptana Studio 3 Workspace\Proxy\test.js:15:11)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
Both, http-auth and node-http-proxy installed yesterday using npm.
What am I doing wrong?
After the authentification I get this error:
Express
500 TypeError: Cannot call method 'substr' of undefined
at Object.validate (/node_modules/http-auth/node_modules/htpasswd/lib/htpasswd.js:57:15)
at Basic.isAuthenticated (/node_modules/http-auth/lib/auth/basic.js:73:17)
at /node_modules/http-auth/lib/auth/basic.js:44:28
at callbacks (/root/local/node/lib/node_modules/express/lib/router/index.js:272:11)
at param (/root/local/node/lib/node_modules/express/lib/router/index.js:246:11)
at pass (/root/local/node/lib/node_modules/express/lib/router/index.js:253:5)
at Router._dispatch (/root/local/node/lib/node_modules/express/lib/router/index.js:280:4)
at Object.handle (/root/local/node/lib/node_modules/express/lib/router/index.js:45:10)
at next (/root/local/node/lib/node_modules/express/node_modules/connect/lib/http.js:201:15)
at Object.handle (/node_modules/stylus/lib/middleware.js:188:7)
In digest.coffee, in the parseAuthorization function, the line
[name, value] = token.split "=", 2
doesn't do the right thing when the value itself might contain the character =
. For example, if the request URI is
/javascript/hates?me=true
then the authorization header will contain
..., uri="/javascript/hates?me=true", ...
and the result will be to set name
to uri
and value
to "/javascript/hates?me
, truncating the URI.
This file was generated with htpasswd
, user "admin", password "foobar":
admin:$apr1$Y.zMz2n3$6Xll.Te9q6GYig6HHpPgW/
http-auth refuses to accept "foobar", but when you paste the MD5 string, it let's you in.
This works if you use SHA1 instead of MD5, but MD5 is default for htpasswd
from the ubuntu repos.
I try to exclude http-auth
for specific route. Here is the code.
var auth = require('http-auth');
var basic = auth.basic({
realm: "MyApp",
file: __dirname + "/config/auth.basic"
});
app.use(function(req, res, next) {
if ('/specific/path' === req.path) {
next();
return;
}
return auth.connect(basic);
});
However, when I hit /specific/path
, got { "message": "auth.connect is not a function", "error": {}}
. Anything I am doing wrong?
Hi, how can i use it from CLient side like jQuery ajax ?
$.ajax({
...
...
});
We need some mechanism to reload htpasswd/htdigest files if there were changed during application run.
I am in the process of packaging http-auth for Fedora. In package.json, your dependencies are on exact versions of libraries; where possible, it's generally better to specify ranges instead (e.g., "^1.8.0" instead of "1.8.0" using semver). I wanted to alert you that I'll be changing the flat versions to caret versions in the course of packaging, unless you think something different should be done.
Thanks!
Hi @gevorg
I have observed an issue which passing a JSON object as request parameter to http server. When the comma isn't encoded, the auth fails!
Example: Running https://github.com/gevorg/http-auth/blob/master/examples/digest.js
http://127.0.0.1:1337/asd?test="sa,Casd" - Fails to authenticate
http://127.0.0.1:1337/asd?test="sa%2CCasd" - Succeed to authenticate
I am not sure if this is an issue, but I expect the URL to work even without encoding for comma...
Hi!
I use custom authentication with http-auth. I call a 3rd party authentication
service to check if a given user and password is correct, like this:
const basicAuth = auth.basic({
msg401: JSON.stringify({error: 'invalid_client'}),
contentType: 'application/json'
},
function (username, password, callback) {
clientAuthService
.authenticate(username, password)
.then(authenticated => {
callback(authenticated)
})
.catch(error => {
callback(false) //FIXME: throw error
})
}
)
The authentication is used for protecting an express route:
router.route('/dummy').post(
auth.connect(basicAuth), // HTTP Basic auth
function(req, res) {
....
}
)
My problem is that the callback accepts only a boolean, that tells whether
the user is authenticated or not. There is no way to signal that there was an error
so that the client should get an HTTP 500 response instead of HTTP 401.
I tried to rethrow the error, but in that case no response was sent to the client.
How can I solve this?
can we use this for basic ACL?
eg to have admin users in one httpasswd file and access to all paths
and editors
in another htpasswd and protect only some other custom paths?
Hi,
Thanks for the http-auth module.
In the project I'm working on, it is not possible to store the plaintext password or unencrypted md5 in the database/file (due to security reasons). Is there a way I can authenticate the digest against an encrypted md5 stored in the database through the auth helper?
Ashima
I am working on a proxy witch allow HTTP Tunneling.
The http-auth
module return the authentication result using http.ServerResponse.setHeader
on the response object (normally given by a http.createServer
).
However, using an http tunnel the response object is not a http.ServerResponse
but only a stream
.
The solution is to write back full headers using stream.write
instead of http.ServerResponse.setHeader
.
I could make a pull request for implementing the trick if you want.
Koa expects middleware to be generator functions
Hello,
I am using this module for my personal website and I encountered an error while setting it up for Linux.
It works pretty fine on Windows but doesn't even install on my Debian 7 dedicated server.
Here is a pastebin of the error : http://pastebin.com/kH1ufqEP
Authentication is asked only once, I guess the CacheControl should be set to 'no-cache'.
we were using this package on a site, but noticed huge slowdowns of 60s or more on various URLs.
is there some known problem with it perhaps? using:
"http-auth": "^2.2.9",
we had a setup where webpages opened by the user
also used XHR ajax requests to load data. these were what were slowing down.
i assume they have the same auth headers added as they are part of the same browser session?
realm
is not used at all when in Basic Authentication so, why do all the example include it?
It's great that http-auth supports http-proxy, but I'm not sure it should be a mandatory dependency. I currently get:
Error: Cannot find module 'http-proxy'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/Users/ahellesoy/github/express-bootstrap/node_modules/http-auth/lib/server/proxy.coffee:4:15)
at Object.<anonymous> (/Users/ahellesoy/github/express-bootstrap/node_modules/http-auth/lib/server/proxy.coffee:31:4)
at Module._compile (module.js:456:26)
at Object.loadFile (/Users/ahellesoy/github/express-bootstrap/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:182:19)
at Module.load (/Users/ahellesoy/github/express-bootstrap/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
I worked around it by installing http-proxy, but that seems a bit weird since I'm not using it.
Could you make it optional or move http-proxy from devDependencies
to dependencies
please?
When I add http-auth 2.1.9 to my project and run it I get:
module.js:340
throw err;
^
Error: Cannot find module 'coffee-script'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/home/pi/thermostat/thermodata.js/node_modules/http-auth/lib/http-auth.js:2:1)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
Hi,
After installing http-auth my web server failed to start due an outdent error, this didn't occur before installing the http-auth package.
My project contains the coffee-script npm module version 1.8.0.
However it seems that for some reason it loads the coffee-script from the http-auth package (which uses coffee-script 1.6.3).
My guess is that there is a parsing bug with coffee-script 1.6.3 and this why it throws the OUTDENT error even though no parsing error exists.
I've marked with asteriks two lines in the stack trace below, the first one is at the top showing the use of the coffee-script version in http-auth, and the second line is near the bottom showing the project using the coffee-script version in my project (as it should do).
So it seems that at a certain step the coffee-script version from http-auth overrides the one I specified in my project, causing the issue.
/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/helpers.js:199
throw error;
^
SyntaxError: unmatched OUTDENT
*****at exports.throwSyntaxError (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/helpers.js:197:13)*****
at Lexer.exports.Lexer.Lexer.error (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/lexer.js:778:14)
at Lexer.exports.Lexer.Lexer.pair (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/lexer.js:690:16)
at Lexer.exports.Lexer.Lexer.outdentToken (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/lexer.js:378:16)
at Lexer.exports.Lexer.Lexer.lineToken (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/lexer.js:356:14)
at Lexer.exports.Lexer.Lexer.tokenize (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/lexer.js:30:100)
at exports.compile.compile (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:35:36)
at Object.loadFile (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:176:14)
at Module.load (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at [object Object].module.exports.Sequelize.import (/Users/ifeins/Development/vision/node_modules/sequelize/lib/sequelize.js:297:63)
at fs.readdirSync.filter.map.forEach.db.(anonymous function) (/Users/ifeins/Development/vision/app/models/index.coffee:17:5)
at Array.map (native)
at Object.<anonymous> (/Users/ifeins/Development/vision/app/models/index.coffee:15:5)
at Object.<anonymous> (/Users/ifeins/Development/vision/app/models/index.coffee:1:1)
at Module._compile (module.js:456:26)
at Object.loadFile (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:182:19)
at Module.load (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at GLOBAL.requireApp (/Users/ifeins/Development/vision/config/application.coffee:8:11)
at Object.<anonymous> (/Users/ifeins/Development/vision/app/filters/auth_filters.coffee:1:10)
at Object.<anonymous> (/Users/ifeins/Development/vision/app/filters/auth_filters.coffee:1:1)
at Module._compile (module.js:456:26)
at Object.loadFile (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:182:19)
at Module.load (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/Users/ifeins/Development/vision/app/routes/performance.coffee:1:15)
at Object.<anonymous> (/Users/ifeins/Development/vision/app/routes/performance.coffee:1:1)
at Module._compile (module.js:456:26)
at Object.loadFile (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:182:19)
at Module.load (/Users/ifeins/Development/vision/node_modules/http-auth/node_modules/coffee-script/lib/coffee-script/coffee-script.js:211:36)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at GLOBAL.requireApp (/Users/ifeins/Development/vision/config/application.coffee:8:11)
at Object.<anonymous> (/Users/ifeins/Development/vision/config/middleware.coffee:19:21)
at Object.<anonymous> (/Users/ifeins/Development/vision/config/middleware.coffee:1:1)
at Module._compile (module.js:456:26)
at Object.loadFile (/Users/ifeins/Development/vision/node_modules/coffee-script/lib/coffee-script/register.js:16:19)
at Module.load (/Users/ifeins/Development/vision/node_modules/coffee-script/lib/coffee-script/register.js:45:36)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/Users/ifeins/Development/vision/app.coffee:19:1)
at Object.<anonymous> (/Users/ifeins/Development/vision/app.coffee:1:1)
at Module._compile (module.js:456:26)
at Object.loadFile (/Users/ifeins/Development/vision/node_modules/coffee-script/lib/coffee-script/register.js:16:19)
*****at Module.load (/Users/ifeins/Development/vision/node_modules/coffee-script/lib/coffee-script/register.js:45:36)*****
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/Users/ifeins/Development/vision/app.js:2:11)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/Users/ifeins/Development/vision/bin/www:3:11)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
I'm not 100% sure but sometimes, with server and client on the same machine, I get log-in dialog boxes. I traced the problem (possibly) to out-of-order nonces when requests were fired by the browser in quick succession (simply an HTML page with elements).
I can trigger the problem by having a web page and associated images (3 images is enough to trigger it) that are digest protected, and using a browser to access the web page.
If I add latency of 100ms or so between the new requests (using javascript), then all requests work fine.
I'm not sure if this is really the case (out-of-order nonces) since I've seen seeminlgy in-order nonces (from the browser's point of view) fail. When I add a console.log of req.header.authorization, I see that when the nc are in-order, everything is good, and that when the nc are out-of-order, I get the 401 login prompt.
Try logging in with __defineGetter__
as user and an arbitrary password.
From digest.coffee parseAuthorization
for token in tokens # Looping tokens.
[name, value] = token.split "=", 2
console.log 'name ['+name+']; value ['+value+']'
if (value.indexOf "\"") != -1
value = value.substr 1, (value.length - 2) # Strip quotes.
# Add option.
clientOptions[name] = value;
When input is something like this:
'Digest username="superuser", realm="WO DMP", nonce="9e19324da680fa72344e47d80463eb74", uri="/admin/sync/ris_ratingsbooklist?marketcodes=425", algorithm=MD5, response="9f283ca4b24d96a0469ae3933e3332d1", qop=auth, nc=00000001, cnonce="21acaa9c1ec694c8"'
the ClientOptions are parsed incorrectly as:
name [username]; value ["superuser"]
name [realm]; value ["WO DMP"]
name [nonce]; value ["9e19324da680fa72344e47d80463eb74"]
name [uri]; value ["/admin/sync/ris_ratingsbooklist?marketcodes]
name [algorithm]; value [MD5]
name [response]; value ["9f283ca4b24d96a0469ae3933e3332d1"]
name [qop]; value [auth]
name [nc]; value [00000001]
name [cnonce]; value ["21acaa9c1ec694c8"]
Notice uri name,value pair.
As a result the hash is generated incorrectly and the browser will refuse to authenticate.
Please! Don't use 'for in' for arrays, it brokes my project cause I customise Array.prototype
It's mdn recomendation too: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
Hi Gevorg,
I've been having some issues including both HTTP and HTTPS in the same server. I have set up a transparent proxy that just passes through all requests, but when I include the basic authentication it stops working. How should I do it? Here's the code I am using:
var auth = require('http-auth');
var http = require('http');
var net = require('net');
var basic = auth.basic({
realm: "Access area",
file: __dirname + "/users"
});
var server = http.createServer(function(request, response) {
var options = {
'hostname': request.headers.host,
'path' : request.url,
'method':request.method,
'headers': request.headers
};
var proxy = http.request(options,function(proxy_response){
proxy_response.on('data', function (chunk) {
response.write(chunk);
});
proxy_response.on('end', function() {
response.end();
});
response.writeHead(proxy_response.statusCode, proxy_response.headers);
});
proxy.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
proxy.end();
}).listen(8888);
server.addListener('connect', function ( request, socketRequest, bodyhead ) {
var proxySocket = new net.Socket();
proxySocket.connect(/[^:]+$/.exec(request.url)[0],/[^:]+/.exec(request.url)[0],function () {
proxySocket.write( bodyhead );
socketRequest.write( "HTTP/" + request.httpVersion + " 200 Connection established\r\n\r\n" );
}
);
proxySocket.on('data', function (chunk) {
socketRequest.write(chunk, 'binary');
});
proxySocket.on('end', function() {
socketRequest.end();
});
proxySocket.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
socketRequest.on('data', function (chunk) {
proxySocket.write(chunk, 'binary');
});
socketRequest.on('end', function() {
proxySocket.end();
});
socketRequest.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
}
);
Thank you!
I believe the way nonces are cached within the server causes the client and server to have shared state, which is unfortunate. I haven't tested myself, but I think it wouldn't work to have two instances of a digest server loadbalanced, since the 401 response from server A would include nonce X, and then when the client sends the correct request with username and hashed password, the request might reach server B (which would not recognise A's nonce) and reject it with 401 again...
As I said, I haven't tested it, but the same thing happens if you restart the server, everyone needs to log in again...
I might have a stab at introducing cryptographically timestamped and signed nonce, which would make the conversation stateless.
And then continues as normal. I'm no security expert, so I asked on StackExchange:
http://security.stackexchange.com/questions/11135/is-it-possible-to-have-stateless-server-nonces-in-http-digest
Different nonces with different expiry times could be used for e.g. safe vs unsafe methods, to make it harder to perform replay attacks; an attacker would have to capture a POST request and be able to exploit it within the (short timeframe of the) POST nonces.
in htpasswd the SHA1 comparison validate is not working due to wrong order of parameters:
'validate' : function( password,passHash) {
console.log("SHA VAlidate "+passHash +" = "+password);
Therefore alls SHA1 passwords, even MIA from the example is not working.
Great work. the only thing I couldnt figure out so far, is how to get the authenticated username in socket.io, ...
Do you have any hints maybe?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.