diff --git a/lib/user/v2/authentication/HTTPDigestAuthentication.js b/lib/user/v2/authentication/HTTPDigestAuthentication.js index 4b0277ea..d3e0ae3c 100644 --- a/lib/user/v2/authentication/HTTPDigestAuthentication.js +++ b/lib/user/v2/authentication/HTTPDigestAuthentication.js @@ -21,7 +21,7 @@ var HTTPDigestAuthentication = (function () { }; HTTPDigestAuthentication.prototype.askForAuthentication = function () { return { - 'WWW-Authenticate': 'Digest realm="' + this.realm + '", qop="auth,auth-int", nonce="' + this.generateNonce() + '", opaque="' + this.generateNonce() + '"' + 'WWW-Authenticate': 'Digest realm="' + this.realm + '", qop="auth", nonce="' + this.generateNonce() + '", opaque="' + this.generateNonce() + '"' }; }; HTTPDigestAuthentication.prototype.getUser = function (arg, callback) { @@ -32,14 +32,10 @@ var HTTPDigestAuthentication = (function () { }); }; var authHeader = arg.headers.find('Authorization'); - if (!authHeader) { - onError(Errors_1.Errors.MissingAuthorisationHeader); - return; - } - if (!/^Digest (\s*[a-zA-Z]+\s*=\s*(("(\\"|[^"])+")|([^,\s]+))\s*(,|$))+$/.test(authHeader)) { - onError(Errors_1.Errors.WrongHeaderFormat); - return; - } + if (!authHeader) + return onError(Errors_1.Errors.MissingAuthorisationHeader); + if (!/^Digest (\s*[a-zA-Z]+\s*=\s*(("(\\"|[^"])+")|([^,\s]+))?\s*(,|$))+$/.test(authHeader)) + return onError(Errors_1.Errors.WrongHeaderFormat); authHeader = authHeader.substring(authHeader.indexOf(' ') + 1); // remove the authentication type from the string var authProps = {}; var rex = /([a-zA-Z]+)\s*=\s*(?:(?:"((?:\\"|[^"])+)")|([^,\s]+))/g; @@ -48,18 +44,26 @@ var HTTPDigestAuthentication = (function () { authProps[match[1]] = match[3] ? match[3] : match[2]; match = rex.exec(authHeader); } - if (!(authProps.username && authProps.nonce && authProps.nc && authProps.cnonce && authProps.qop && authProps.response)) { - onError(Errors_1.Errors.AuenticationPropertyMissing); - return; - } + if (!(authProps.username && authProps.nonce && authProps.nc && authProps.cnonce && authProps.response)) + return onError(Errors_1.Errors.AuenticationPropertyMissing); + if (!authProps.algorithm) + authProps.algorithm = 'MD5'; this.userManager.getUserByName(authProps.username, function (e, user) { - if (e) { - onError(e); - return; - } + if (e) + return onError(e); var ha1 = md5(authProps.username + ':' + _this.realm + ':' + (user.password ? user.password : '')); - var ha2 = md5(arg.request.method.toString().toUpperCase() + ':' + arg.requested.uri); - var result = md5(ha1 + ':' + authProps.nonce + ':' + authProps.nc + ':' + authProps.cnonce + ':' + authProps.qop + ':' + ha2); + if (authProps.algorithm === 'MD5-sess') + ha1 = md5(ha1 + ':' + authProps.nonce + ':' + authProps.cnonce); + var ha2; + if (authProps.qop === 'auth-int') + return onError(Errors_1.Errors.WrongHeaderFormat); // ha2 = md5(arg.request.method.toString().toUpperCase() + ':' + arg.requested.uri + ':' + md5(...)); + else + ha2 = md5(arg.request.method.toString().toUpperCase() + ':' + arg.requested.uri); + var result; + if (authProps.qop === 'auth-int' || authProps.qop === 'auth') + result = md5(ha1 + ':' + authProps.nonce + ':' + authProps.nc + ':' + authProps.cnonce + ':' + authProps.qop + ':' + ha2); + else + result = md5(ha1 + ':' + authProps.nonce + ':' + ha2); if (result.toLowerCase() === authProps.response.toLowerCase()) callback(Errors_1.Errors.None, user); else diff --git a/src/user/v2/authentication/HTTPDigestAuthentication.ts b/src/user/v2/authentication/HTTPDigestAuthentication.ts index 74f98521..aa24aa0c 100644 --- a/src/user/v2/authentication/HTTPDigestAuthentication.ts +++ b/src/user/v2/authentication/HTTPDigestAuthentication.ts @@ -27,7 +27,7 @@ export class HTTPDigestAuthentication implements HTTPAuthentication askForAuthentication() { return { - 'WWW-Authenticate': 'Digest realm="' + this.realm + '", qop="auth,auth-int", nonce="' + this.generateNonce() + '", opaque="' + this.generateNonce() + '"' + 'WWW-Authenticate': 'Digest realm="' + this.realm + '", qop="auth", nonce="' + this.generateNonce() + '", opaque="' + this.generateNonce() + '"' } } @@ -42,15 +42,9 @@ export class HTTPDigestAuthentication implements HTTPAuthentication let authHeader = arg.headers.find('Authorization') if(!authHeader) - { - onError(Errors.MissingAuthorisationHeader) - return; - } - if(!/^Digest (\s*[a-zA-Z]+\s*=\s*(("(\\"|[^"])+")|([^,\s]+))\s*(,|$))+$/.test(authHeader)) - { - onError(Errors.WrongHeaderFormat); - return; - } + return onError(Errors.MissingAuthorisationHeader); + if(!/^Digest (\s*[a-zA-Z]+\s*=\s*(("(\\"|[^"])+")|([^,\s]+))?\s*(,|$))+$/.test(authHeader)) + return onError(Errors.WrongHeaderFormat); authHeader = authHeader.substring(authHeader.indexOf(' ') + 1); // remove the authentication type from the string @@ -64,22 +58,30 @@ export class HTTPDigestAuthentication implements HTTPAuthentication match = rex.exec(authHeader); } - if(!(authProps.username && authProps.nonce && authProps.nc && authProps.cnonce && authProps.qop && authProps.response)) - { - onError(Errors.AuenticationPropertyMissing); - return; - } + if(!(authProps.username && authProps.nonce && authProps.nc && authProps.cnonce && authProps.response)) + return onError(Errors.AuenticationPropertyMissing); + if(!authProps.algorithm) + authProps.algorithm = 'MD5'; this.userManager.getUserByName(authProps.username, (e, user) => { if(e) - { - onError(e); - return; - } + return onError(e); - const ha1 = md5(authProps.username + ':' + this.realm + ':' + (user.password ? user.password : '')); - const ha2 = md5(arg.request.method.toString().toUpperCase() + ':' + arg.requested.uri); - const result = md5(ha1 + ':' + authProps.nonce + ':' + authProps.nc + ':' + authProps.cnonce + ':' + authProps.qop + ':' + ha2); + let ha1 = md5(authProps.username + ':' + this.realm + ':' + (user.password ? user.password : '')); + if(authProps.algorithm === 'MD5-sess') + ha1 = md5(ha1 + ':' + authProps.nonce + ':' + authProps.cnonce); + + let ha2; + if(authProps.qop === 'auth-int') + return onError(Errors.WrongHeaderFormat); // ha2 = md5(arg.request.method.toString().toUpperCase() + ':' + arg.requested.uri + ':' + md5(...)); + else + ha2 = md5(arg.request.method.toString().toUpperCase() + ':' + arg.requested.uri); + + let result; + if(authProps.qop === 'auth-int' || authProps.qop === 'auth') + result = md5(ha1 + ':' + authProps.nonce + ':' + authProps.nc + ':' + authProps.cnonce + ':' + authProps.qop + ':' + ha2); + else + result = md5(ha1 + ':' + authProps.nonce + ':' + ha2); if(result.toLowerCase() === authProps.response.toLowerCase()) callback(Errors.None, user);