Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
/**
* Make a remote GET using DIGEST authentication.
*
* DIGEST authenticated requests require two GET requests:
* 1. GET the www-authenticate header for nonce, realm, opaque, and other values
* 2. GET the expected response body by constructing an 'Authorization' header
* with nonce, realm, and other values provided by the server.
*
* @license MIT
*
* @param string $url API URL supporting DIGEST authentication.
* @param string $username Username to be used in authentication.
* @param string $password Password to be used in authentication.
* @return string|false Response body on success, false on some form of failure.
*/
function hb_digest_auth_remote_get( $url, $username, $password ) {
/*
* Makes an initial request for the server's provided headers
*/
$response = wp_remote_get( $url, $request );
$header = wp_remote_retrieve_header( $response, 'www-authenticate' );
if ( empty( $header ) ) {
return false;
}
/*
* Parses the 'www-authenticate' header for nonce, realm and other values.
*/
preg_match_all( '#(([\w]+)=["]?([^\s"]+))#', $header, $matches );
$server_bits = array();
foreach( $matches[2] as $i => $key ) {
$server_bits[ $key ] = $matches[3][ $i ];
}
$nc = '00000001';
$path = parse_url( $url, PHP_URL_PATH );
$client_nonce = uniqid();
$ha1 = md5( $username . ':' . $server_bits['realm'] . ':' . $password );
$ha2 = md5( 'GET:' . $path );
// The order of this array matters, because it affects resulting hashed val
$response_bits = array(
$ha1,
$server_bits['nonce'],
$nc,
$client_nonce,
$server_bits['qop'],
$ha2
);
$digest_header_values = array(
'username' => '"' . $username . '"',
'realm' => '"' . $server_bits['realm'] . '"',
'nonce' => '"' . $server_bits['nonce'] . '"',
'uri' => '"' . $path . '"',
'response' => '"' . md5( implode( ':', $response_bits ) ) . '"',
'opaque' => '"' . $server_bits['opaque'] . '"',
'qop' => $server_bits['qop'],
'nc' => $nc,
'cnonce' => '"' . $client_nonce . '"',
);
$digest_header = 'Digest ';
foreach( $digest_header_values as $key => $value ) {
$digest_header .= $key . '=' . $value . ', ';
}
$digest_header = rtrim( $digest_header, ', ' );
$request = array(
'headers' => array(
'Authorization' => $digest_header,
),
);
$response = wp_remote_get( $url, $request );
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
return false;
}
return wp_remote_retrieve_body( $response );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment