So I could only find one other PHP based HTTP digest auth example on the internet…and it looked as though it might not even work. I wrote an abstract class as a base that allows you to easily build your own implementation.
You’d use it like so:
class MyAuth extends HTTPDigestAuth {
// Implementation of abstract methods
}
$authenticator = new MyAuth();
$user = $authenticator->authenticate();
if(!$user) {
die();
}
The HTTPDigestAuth class looks like:
/*
Copyright 2010 Alan Shaw
http://freestyle-developments.co.uk
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations
under the License.
*/
/**
* Object orientated PHP HTTP digest authentication.
*
* Extend this class and implement abstract functions to create your own
* HTTP digest authentication implementation.
*/
abstract class HTTPDigestAuth {
////////////////////////////////////////////////////////////////////////
// @public
/**
* @return an authenticated user object on success, null otherwise.
*/
public function authenticate() {
if(empty($_SERVER['PHP_AUTH_DIGEST'])) {
$this->setHeadersUnauthorized();
$this->getResponseBodyUnauthorized();
return null;
}
$authClientData = new HTTPDigestAuthClientData($_SERVER['PHP_AUTH_DIGEST']);
// Check for stale nonce
if($this->isStaleNonce($authClientData->nonce)) {
$this->setHeadersUnauthorized(true);
$this->getResponseBodyUnauthorized();
return null;
}
// Check for correct nonce count
if($authClientData->nc != $this->getNonceCount($authClientData->nonce) + 1) {
$this->setHeadersBadRequest();
$this->getResponseBodyBadRequest('Incorrect nonce count');
return null;
}
$this->incrementNonceCount($authClientData->nonce);
// Check request URI is the same as the auth digest uri
if($authClientData->uri != $_SERVER['REQUEST_URI']) {
$this->setHeadersBadRequest();
$this->getResponseBodyBadRequest('Digest auth URI != request URI');
return null;
}
// Check opaque is correct
if($authClientData->opaque != $this->getOpaque()) {
$this->setHeadersBadRequest();
$this->getResponseBodyBadRequest('Incorrect opaque');
return null;
}
// Check user exists
if(!$this->userExists($authClientData->username)) {
$this->setHeadersUnauthorized();
$this->getResponseBodyUnauthorized();
return null;
}
$ha1 = $this->getHA1ForUser($authClientData->username);
// Generate A2 hash
if($authClientData->qop == 'auth-int') {
$a2 = $_SERVER['REQUEST_METHOD'] . ':' . stripslashes($_SERVER['REQUEST_URI']) . ':' . file_get_contents('php://input');
$ha2 = md5($a2);
} else {
$a2 = $_SERVER['REQUEST_METHOD'] . ':' . stripslashes($_SERVER['REQUEST_URI']);
$ha2 = md5($a2);
}
// Generate the expected response
if($authClientData->qop == 'auth' || $authClientData->qop == 'auth-int') {
$expectedResponse = md5($ha1 . ':' . $authClientData->nonce . ':' . $authClientData->nc . ':' . $authClientData->cnonce . ':' . $authClientData->qop . ':' . $ha2);
} else {
$expectedResponse = md5($expectedResponse = $ha1 . ':' . $authClientData->nonce . ':' . $ha2);
}
// Check request contained the expected response
if($authClientData->response != $expectedResponse) {
$this->setHeadersBadRequest();
$this->getResponseBodyBadRequest();
return null;
}
return $this->getUser($authClientData->username);
}
////////////////////////////////////////////////////////////////////////
// @private
private function setHeadersUnauthorized($stale = false) {
header('HTTP/1.1 401 Unauthorized');
$authHeader = 'WWW-Authenticate: Digest realm="' . $this->getAuthRealm() . '",qop="auth-int,auth",algorithm="MD5",nonce="' . $this->createNonce() . '",opaque="' . $this->getOpaque() . '"';
if($stale) {
$authHeader .= ',stale=TRUE';
}
header($authHeader);
}
private static function setHeadersBadRequest() {
header('HTTP/1.1 400 Bad Request');
}
////////////////////////////////////////////////////////////////////////
// @optional
protected function getResponseBodyUnauthorized($reason = '') {
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error</title>
</head>
<body>
<h1>401 Unauthorized.</h1>
<?php
if($reason) {
?>
<p><?php echo htmlspecialchars($reason); ?></p>
<?php
}
?>
</body>
</HTML>
<?php
}
protected function getResponseBodyBadRequest($reason = '') {
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Error</title>
</head>
<body>
<h1>400 Bad Request.</h1>
<?php
if($reason) {
?>
<p><?php echo htmlspecialchars($reason); ?></p>
<?php
}
?>
</body>
</HTML>
<?php
}
////////////////////////////////////////////////////////////////////////
// @required
/**
* Gets the authentication realm for this class
*
* @return String
*/
abstract protected function getAuthRealm();
/**
* Gets the opaque for this class
*
* @return String
*/
abstract protected function getOpaque();
/**
* Creates a new nonce to send to the client
*
* @return String
*/
abstract protected function createNonce();
/**
* Returns whether or not this nonce has expired. Should return true for
* non existent nonce.
*
* @param String $nonce
* @return Boolean
*/
abstract protected function isStaleNonce($nonce);
/**
* Gets the current request count for a particular nonce
*
* @param String $nonce The nonce to get the count of
* @return uint The current nonce count
*/
abstract protected function getNonceCount($nonce);
/**
* Increments the nonce count by 1
*
* @param String $nonce The nonce to increment
*/
abstract protected function incrementNonceCount($nonce);
/**
* Returns a boolean indicating whether or not a user with the specified
* username exists.
*
* @param String $username
* @return Boolean
*/
abstract protected function userExists($username);
/**
* Returns the A1 hash for the specified user.
* i.e. return md5('username:realm:password')
*
* @param String $username
* @return String
*/
abstract protected function getHA1ForUser($username);
/**
* Returns a user instance that belongs to the user with the username
* provided.
*
* @param String $username
* @return ???
*/
abstract protected function getUser($username);
}
/**
* @private
*/
class HTTPDigestAuthClientData {
public $username;
public $nonce;
public $nc;
public $cnonce;
public $qop;
public $uri;
public $response;
public $opaque;
public function __construct($header) {
preg_match_all('@(username|nonce|uri|nc|cnonce|qop|response|opaque)=[\'"]?([^\'",]+)@', $header, $t);
$data = array_combine($t[1], $t[2]);
$this->username = $data['username'];
$this->nonce = $data['nonce'];
$this->nc = $data['nc'];
$this->cnonce = $data['cnonce'];
$this->qop = $data['qop'];
$this->uri = $data['uri'];
$this->response = $data['response'];
$this->opaque = $data['opaque'];
}
}
You can download the full source here: github.com/alanshaw/php-http-digest-auth
Invest in your health by choosing URL=https://airjamaicacharter.com/hydroxychloroquine/hydroxychloroquine fast shipment/URL for premium cholesterol management solutions. This medication is formulated to reduce your cholesterol levels safely. In need of effective antibiotic treatment? doxycycline 100 mg pills for sale to combat infections caused by bacteria. This budget-friendly solution is simple to obtain and can help in managing numerous of medical conditions. Discover the most cost-effective options for managing intermittent claudication with https://tacticaltrappingservices.com/drugs/retin-a/ . Secure your health without depleting your wallet today. Ive found the URL=https://mnsmiles.com/non-prescription-priligy/canada and priligy/URL for addressing hair loss.
Your quest for authentic arrhythmia treatment ends today. Discover our wide array of heart medications including URL=https://csicls.org/drugs/lasix/lasix generic canada/URL offered online. Questioning where to purchase your next medication? Explore the options and benefits of finasteride for comprehensive HIV treatment solutions. A comprehensive guide to managing hypertension and preventing heart issues is available; find out about your options by visiting https://jomsabah.com/prednisolone/ which provides an accessible way to better health. You can easily obtain your URL=https://center4family.com/ventolin/ventolin/URL online offering alleviation from nasal congestion.
If managing your heart health has become a priority consider lowest price generic viagra as your go-to option ensuring effective prevention against heart attacks and cerebrovascular accidents. Facing respiratory challenges? asthalin hfa inhaler can be your relief partner. Secure simple and quick its your gateway to improve breathing. Discover cost-effective options for managing your pain with https://profitplusfinancial.com/item/priligy/ . Whether youre looking to buy this treatment online we offer a range of choices to meet your needs. Explore reliable options to buy your medication: buy cheap generic nizagara uk offers a user-friendly approach for those in need.