/// <summary> /// An authentication response have been received from the web browser. /// Check if it's correct /// </summary> /// <param name="header">Contents from the Authorization header</param> /// <param name="realm">Realm that should be authenticated</param> /// <param name="httpVerb">GET/POST/PUT/DELETE etc.</param> /// <returns> /// Authentication object that is stored for the request. A user class or something like that. /// </returns> /// <exception cref="ArgumentException">if authenticationHeader is invalid</exception> /// <exception cref="ArgumentNullException">If any of the parameters is empty or null.</exception> public IAuthenticationUser Authenticate(AuthorizationHeader header, string realm, string httpVerb) { if (header == null) throw new ArgumentNullException("header"); lock (_nonces) { if (_timer == null) _timer = new Timer(ManageNonces, null, 15000, 15000); } if (!header.Scheme.Equals("digest", StringComparison.OrdinalIgnoreCase)) return null; var parameters = HeaderParameterCollection.Parse(new StringReader(header.Data), ','); if (!IsValidNonce(parameters["nonce"]) && !DisableNonceCheck) return null; // request authentication information string username = parameters["username"]; var user = _userProvider.Lookup(username, realm); if (user == null) return null; // Encode authentication info string HA1 = string.IsNullOrEmpty(user.HA1) ? GetHA1(realm, username, user.Password) : user.HA1; // encode challenge info string A2 = String.Format("{0}:{1}", httpVerb, parameters["uri"]); string HA2 = GetMD5HashBinHex2(A2); string hashedDigest = Encrypt(HA1, HA2, parameters["qop"], parameters["nonce"], parameters["nc"], parameters["cnonce"]); //validate if (parameters["response"] == hashedDigest) return user; return null; }
/// <summary> /// An authentication response have been received from the web browser. /// Check if it's correct /// </summary> /// <param name="header">Authorization header</param> /// <param name="realm">Realm that should be authenticated</param> /// <param name="httpVerb">GET/POST/PUT/DELETE etc.</param> /// <returns>Authentication object that is stored for the request. A user class or something like that.</returns> /// <exception cref="ArgumentException">if authenticationHeader is invalid</exception> /// <exception cref="ArgumentNullException">If any of the paramters is empty or null.</exception> public IAuthenticationUser Authenticate(AuthorizationHeader header, string realm, string httpVerb) { if (header == null) throw new ArgumentNullException("realm"); if (string.IsNullOrEmpty(realm)) throw new ArgumentNullException("realm"); if (string.IsNullOrEmpty(httpVerb)) throw new ArgumentNullException("httpVerb"); /* * To receive authorization, the client sends the userid and password, separated by a single colon (":") character, within a base64 [7] encoded string in the credentials.*/ string decoded = Encoding.UTF8.GetString(Convert.FromBase64String(header.Data)); int pos = decoded.IndexOf(':'); if (pos == -1) throw new BadRequestException("Invalid basic authentication header, failed to find colon."); string password = decoded.Substring(pos + 1, decoded.Length - pos - 1); string userName = decoded.Substring(0, pos); var user = _userProvider.Lookup(userName, realm); if (user == null) return null; if (user.Password == null) { var ha1 = DigestAuthentication.GetHA1(realm, userName, password); if (ha1 != user.HA1) return null; } else { if (password != user.Password) return null; } return user; }