Skip to content

Loading…

Support for Digest Authentication #84

Open
wants to merge 2 commits into from

1 participant

@aledbf

Example:

rest.post('URL',{
    auth: 'digest',
    username: 'USERNAME',
    password: 'PASSWORD',
    realm: "Digest REALM",
    key: 'Digest key',
    nonceTtl: 10
}).on('complete', function(data, response) {
});

This patch require new options:

  • auth: can be basic or digest (just to not change unrelated source code in restler)
  • realm: digest realm
  • key: digest key
  • nonceTtl: nonce time to live (in seconds)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 8, 2012
  1. @aledbf
  2. @aledbf
Showing with 30 additions and 3 deletions.
  1. +30 −3 lib/restler.js
View
33 lib/restler.js
@@ -6,6 +6,7 @@ var qs = require('querystring');
var multipart = require('./multipartform');
var zlib = null;
var Iconv = null;
+var hashlib = require("hashlib");
try {
zlib = require('zlib');
@@ -38,7 +39,7 @@ function Request(uri, options) {
}
mixin(this.headers, options.headers || {});
-
+
// set port and method defaults
if (!this.url.port) this.url.port = (this.url.protocol == 'https:') ? '443' : '80';
if (!this.options.method) this.options.method = (this.options.data) ? 'POST' : 'GET';
@@ -52,6 +53,8 @@ function Request(uri, options) {
}
this._applyBasicAuth();
+
+ this._applyDigestAuth();
if (this.options.multipart) {
this.headers['Content-Type'] = 'multipart/form-data; boundary=' + multipart.defaultBoundary;
@@ -103,7 +106,7 @@ mixin(Request.prototype, {
_applyBasicAuth: function() {
var authParts;
- if (this.url.auth) {
+ if (this.options.auth === 'basic' && this.url.auth) {
authParts = this.url.auth.split(':');
this.options.username = authParts[0];
this.options.password = authParts[1];
@@ -114,6 +117,30 @@ mixin(Request.prototype, {
this.headers['Authorization'] = "Basic " + b.toString('base64');
}
},
+ _applyDigestAuth: function() {
+ var authParts;
+
+ if (this.options.auth === 'digest' && this.url.auth) {
+ authParts = this.url.auth.split(':');
+
+ this.options.username = authParts[0];
+ this.options.password = authParts[1];
+ }
+
+ if (this.options.username && this.options.password) {
+ var nonce = (new Date()).getTime() + (this.options.nonceTtl * 1000);
+
+ var computedNonce = nonce + ':' + this.options.key;
+ computedNonce = new Buffer(nonce + ':' + hashlib.md5(computedNonce)).toString('base64');
+
+ var ha1 = hashlib.md5(this.options.username + ":" + this.options.realm + ":" + this.options.password);
+ var ha2 = hashlib.md5(this.options.method + ":" + this.url.pathname);
+
+ var response = hashlib.md5(ha1 + ":" + computedNonce + ":" + ha2);
+
+ this.headers['Authorization'] = "Digest realm=\"" + this.options.realm + "\", username=\"" + this.options.username + "\", nonce=\"" + computedNonce + "\", uri=\"" + this.url.pathname + "\" , response=\"" + response + '"';
+ }
+ },
_responseHandler: function(response) {
var self = this;
@@ -225,7 +252,7 @@ mixin(Request.prototype, {
this.request.abort();
}
Request.call(this, this.url.href, this.options); // reusing request object to handle recursive calls and remember listeners
- this.run();
+ this.run();
},
run: function() {
var self = this;
Something went wrong with that request. Please try again.