Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to perform Digest Authentication With Requests #245

Open
devahsancreative opened this issue Oct 14, 2016 · 3 comments
Open

How to perform Digest Authentication With Requests #245

devahsancreative opened this issue Oct 14, 2016 · 3 comments

Comments

@devahsancreative
Copy link

$user = 'myusername';
$pass = 'mypass';
$BaseApiUrl     = 'myurl';

$headers = array('Accept' => 'application/json');
$options = array('auth' => new Requests_Auth_Basic(array($user, $pass)));
$request = Requests::get($BaseApiUrl, $headers, $options);
var_dump($request->status_code);
var_dump($request->body);

This is my code it gives error
int(401) string(28) "HTTP Digest: Access denied. "

You have
Basic/Digest Authentication

please provide step for Digest Authentication

@dd32
Copy link
Member

dd32 commented Oct 17, 2016

It doesn't look like Requests has Digest support at all at present (the readme is the only reference to it).
Depending on your api's Digest implementation (there's a few different implementations of it) you should be able to build the Authorization header directly yourself and pass it to Requests though (but it may require you to first do a HEAD against the site to get all the digest details to compute the hash).

(Note: If it's your own server, keep in mind that Digest Authentication isn't considered more secure than Basic + SSL, as most clients can be MITM'd to fall back to Basic Auth)

@soulseekah
Copy link
Contributor

Related #32

@mmethner
Copy link

Here is an example for the Digest Authentication. You need to create the auth header by yourself and that only works, if you fetch the auth request headers with an additional http request (the first wp_remote_get() call). The second call is the actual request you want to sent. The solution is based on this blog post with another regexp I found here

$url='?';
$username ='?';
$password ='?';

$response = wp_remote_get( $url, $request );
$header   = wp_remote_retrieve_header( $response, 'www-authenticate' );
if ( empty( $header ) ) {
	// handle error;
}

$matches     = [];
$server_bits = [];

/*
* Parses the 'www-authenticate' header for nonce, realm and other values.
*
* $header looks like
* Digest realm="your authentication",qop="auth",nonce="611...552",opaque="a707ae2edc...2f8d80a9af0fd335"
*/
preg_match_all(
	'#(realm|nonce|qop|opaque)=(?:([\'"])([^\2]+?)\2|([^\s,]+))#',
	$header,
	$matches,
	PREG_SET_ORDER
);

foreach ( $matches as $match ) {
	$server_bits[ $match[1] ] = $match[3] ?? $match[4];
}

$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 = [
	$ha1,
	$server_bits['nonce'],
	$nc,
	$client_nonce,
	$server_bits['qop'],
	$ha2
];

$digest_header_values = [
	'username' => sprintf( 'username="%s"', $username ),
	'realm'    => sprintf( 'realm="%s"', $server_bits['realm'] ),
	'nonce'    => sprintf( 'nonce="%s"', $server_bits['nonce'] ),
	'uri'      => sprintf( 'uri="%s"', $path ),
	'response' => sprintf( 'response="%s"', md5( implode( ':', $response_bits ) ) ),
	'opaque'   => sprintf( 'opaque="%s"', $server_bits['opaque'] ),
	'qop'      => sprintf( 'qop=%s', $server_bits['qop'] ),
	'nc'       => sprintf( 'nc=%s', $nc ),
	'cnonce'   => sprintf( 'cnonce="%s"', $client_nonce )
];

$digestHeader = implode( ', ', $digest_header_values );

$request  = [
	'headers' => [
		'Authorization' => 'Digest ' . $digestHeader,
	],
];
$response = wp_remote_get( $url, $request );

Probably there are other headers missing for your webserver configuration. You can add them to the regexp.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants