Skip to content
Browse files

Moving digest authenticated into async callback.

  • Loading branch information...
1 parent f6abdc5 commit 4a5ce26ff1531d6b9c719a9478970fbf32d53a7f @gevorg committed
View
BIN lib/auth/.digest.js.swp
Binary file not shown.
View
104 lib/auth/digest.js
@@ -45,8 +45,8 @@ function Digest(authRealm, authUsers, algorithm) {
// Used for async callback.
var self = this;
- // Stale state.
- this.STALE = new State("stale");
+ // Stale state.
+ this.STALE = new State("stale");
/**
* Applies digest authentication and calls next after user is authenticated.
@@ -57,22 +57,23 @@ function Digest(authRealm, authUsers, algorithm) {
*/
this.apply = function(request, response, next) {
// Processing authentication part.
- var authenticated = self.isAuthenticated(request);
- if(!authenticated || authenticated === this.STALE) {
- self.ask(response, authenticated === this.STALE);
- } else {
- next(authenticated);
- }
- };
+ self.isAuthenticated(request, function(authenticated) {
+ if(!authenticated || authenticated === self.STALE) {
+ self.ask(response, authenticated === self.STALE);
+ } else {
+ next(authenticated);
+ }
+ });
+ };
};
/**
* Checks authorization header in request.
*
* @param {Request} request HTTP request object.
- * @return {String} the authenticated user ID, if authenticated, else undefined.
+ * @param {Function} callback after authentication is finished.
*/
-Digest.prototype.isAuthenticated = function(request) {
+Digest.prototype.isAuthenticated = function(request, callback) {
var authenticated = undefined;
// If header exists.
@@ -83,46 +84,63 @@ Digest.prototype.isAuthenticated = function(request) {
// Check for expiration.
if(co.nonce in this.nonces) {
// Second hash in digest access authentication.
- // Calculating second hash.
+ // Calculating second hash.
var ha2 = utils.md5(request.method + ":" + request.url);
// Checking response for username.
var userHash = this.users[co.username];
- // Username is correct.
- if(userHash && typeof userHash === 'string') {
- var ha1 = this.users[co.username].split(":")[2];
-
- // If algorithm is MD5-sess.
- if(co.algorithm == 'MD5-sess') {
- ha1 = utils.md5(ha1 + ":" + co.nonce + ":" + co.cnonce);
- }
-
- // If qop is specified.
- if(co.qop) {
- if(co.nc > this.nonces[co.nonce]) {
- // Updating nonce count.
- this.nonces[co.nonce] = co.nc;
-
- // Evaluating final authentication response.
- var authRes = utils.md5(ha1 + ":" + co.nonce + ":" + co.nc + ":" +
- co.cnonce + ":" + co.qop + ":" + ha2);
- authenticated = (authRes == co.response) ? co.username : undefined;
- } else {
- authenticated = this.STALE;
- }
- } else {
- // Evaluating final authentication response.
- var authRes = utils.md5(ha1 + ":" + co.nonce + ":" + ha2);
- authenticated = (authRes == co.response) ? co.username : undefined;
- }
- }
- } else {
+ // Validates client options.
+ callback(this.validateClientOptions(ha2, co, userHash));
+ } else {
+ callback(this.STALE);
+ }
+ } else {
+ callback();
+ }
+};
+
+/**
+ * Validates client options.
+ *
+ * @param {String} second hash in digest authentication mechanism.
+ * @param {Object} object with client options.
+ * @param {String} user hash from server.
+ * @return {String} the authenticated user ID, if authentication is successful, else undefined.
+ */
+Digest.prototype.validateClientOptions = function(ha2, co, userHash) {
+ var authenticated = undefined;
+
+ // Username is correct.
+ if(userHash && typeof userHash === 'string') {
+ var ha1 = userHash.split(":")[2];
+
+ // If algorithm is MD5-sess.
+ if(co.algorithm == 'MD5-sess') {
+ ha1 = utils.md5(ha1 + ":" + co.nonce + ":" + co.cnonce);
+ }
+
+ // If qop is specified.
+ if(co.qop) {
+ if(co.nc > this.nonces[co.nonce]) {
+ // Updating nonce count.
+ this.nonces[co.nonce] = co.nc;
+
+ // Evaluating final authentication response.
+ var authRes = utils.md5(ha1 + ":" + co.nonce + ":" + co.nc + ":" +
+ co.cnonce + ":" + co.qop + ":" + ha2);
+ authenticated = (authRes == co.response) ? co.username : undefined;
+ } else {
authenticated = this.STALE;
- }
+ }
+ } else {
+ // Evaluating final authentication response.
+ var authRes = utils.md5(ha1 + ":" + co.nonce + ":" + ha2);
+ authenticated = (authRes == co.response) ? co.username : undefined;
+ }
}
- return authenticated;
+ return authenticated;
};
/**
* Asks client for authentication.
View
BIN tests/auth/.test-digest.js.swp
Binary file not shown.
View
49 tests/auth/test-digest.js
@@ -118,11 +118,12 @@ exports['testIsAuthenticatedEmptyCnonce'] = function(test) {
// Initiates input request.
var request = {headers : {authorization : header}};
- // Source method call, that must return username.
- test.equals(source.isAuthenticated(request), "mia", "User must be valid!");
-
- // Test is done.
- test.done();
+
+ // Source method call, that must return username.
+ source.isAuthenticated(request, function(authenticated) {
+ test.equals(authenticated, "mia", "User must be valid!");
+ test.done();
+ });
};
/**
@@ -139,12 +140,12 @@ exports['testIsAuthenticatedTrue'] = function(test) {
// Initiates input request.
var request = {headers : {authorization : header}};
-
- // Source method call, that must return username.
- test.equals(source.isAuthenticated(request), "mia", "User must be valid!");
- // Test is done.
- test.done();
+ // Source method call, that must return username.
+ source.isAuthenticated(request, function(authenticated) {
+ test.equals(authenticated, "mia", "User must be valid!");
+ test.done();
+ });
};
/**
@@ -160,11 +161,13 @@ exports['testIsAuthenticatedFalseHeader'] = function(test) {
// Initiates input request.
var request = {headers : {authorizationWrong : header}};
+
// Source method call, that must return false.
- test.ok(!source.isAuthenticated(request), "User must be invalid!");
+ source.isAuthenticated(request, function(authenticated) {
+ test.ok(!authenticated, "User must be invalid!");
+ test.done();
+ });
- // Test is done.
- test.done();
};
/**
* Test for isAuthenticated, false nc case.
@@ -178,12 +181,12 @@ exports['testIsAuthenticatedFalseNC'] = function(test) {
// Initiates input request.
var request = {headers : {authorization : header}};
-
+
// Source method call, that must return 'stale'.
- test.equals(source.isAuthenticated(request), source.STALE, "User must be invalid!");
-
- // Test is done.
- test.done();
+ source.isAuthenticated(request, function(authenticated) {
+ test.equals(authenticated, source.STALE, "User must be invalid!");
+ test.done();
+ });
};
/**
* Test for isAuthenticated, false response case.
@@ -201,10 +204,10 @@ exports['testIsAuthenticatedFalseRes'] = function(test) {
var request = {headers : {authorization : header}};
// Source method call, that must return false.
- test.ok(!source.isAuthenticated(request), "User must be invalid!");
-
- // Test is done.
- test.done();
+ source.isAuthenticated(request, function(authenticated) {
+ test.ok(!authenticated, "User must be invalid!");
+ test.done();
+ });
};
/**
* Test for apply, pass case.
@@ -255,7 +258,7 @@ exports['testApplyAuth'] = function(test) {
response.mock("end").takes(defaults.HTML_401);
// Source method call.
- source.apply(request, response, function() {
+ source.apply(request, response, function(user) {
test.ok(false, "Callback should not be called!");
});

0 comments on commit 4a5ce26

Please sign in to comment.
Something went wrong with that request. Please try again.