"password1", "username2" => "password2"); //message to show $realm = "Please enter your credentials"; //send needed digest auth headers if (empty($_SERVER["PHP_AUTH_DIGEST"])) { header("HTTP/1.1 401 Unauthorized"); header("WWW-Authenticate: Digest realm=\"".$realm."\",qop=\"auth\",nonce=\"".uniqid(mt_rand(), true)."\",opaque=\"".md5($realm."salt-for-opaque")."\""); die("unauthorized access"); } //parse http digest (inspired through http://www.php.net/manual/features.http-auth.php#93427) $mandatory = array("nonce" => true, "nc" => true, "cnonce" => true, "qop" => true, "username" => true, "uri" => true, "response" => true); $data = array(); preg_match_all('@(\w+)=(?:(?:\'([^\']+)\'|"([^"]+)")|([^\s,]+))@', $_SERVER["PHP_AUTH_DIGEST"], $matches, PREG_SET_ORDER); foreach ($matches as $m) { $data[$m[1]] = $m[2] ? $m[2] : ($m[3] ? $m[3] : $m[4]); unset($mandatory[$m[1]]); //mandatory part was found, kick it out of the "to do" list (=$mandatory array) } //create valid digest to validate the credentials $digest = ""; if (isset($users[$data["username"]])) { $realm_digest = $realm; //As mentioned at : //If safe mode is enabled, the uid of the script is added to the realm part of //the WWW-Authenticate header (you cannot supress this!). Therefore we have to //do this here, too. if (6 > (int)PHP_VERSION //safe_mode will be removed in PHP 6.0 && (int)ini_get("safe_mode") !== 0) { $realm_digest .= "-".getmyuid(); } $digest = md5(md5($data["username"].":".$realm_digest.":".$users[$data["username"]]) //A1 .":".$data["nonce"].":".$data["nc"].":".$data["cnonce"].":".$data["qop"].":" .md5($_SERVER["REQUEST_METHOD"].":".$data["uri"])); //A2 } if (empty($digest) || $data["response"] !== $digest) { header("HTTP/1.1 401 Unauthorized"); header("WWW-Authenticate: Digest realm=\"".$realm."\",qop=\"auth\",nonce=\"".uniqid(mt_rand(), true)."\",opaque=\"".md5($realm."salt-for-opaque")."\""); die("wrong credentials"); } //if we are here, auth was successful return true; } ?>