summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Auth/OpenID/Discover.php28
-rw-r--r--Auth/OpenID/HTTPFetcher.php11
-rw-r--r--Auth/OpenID/ParanoidHTTPFetcher.php6
-rw-r--r--Auth/OpenID/PlainHTTPFetcher.php5
-rw-r--r--Tests/Auth/OpenID/Discover.php472
-rw-r--r--Tests/TestDriver.php1
6 files changed, 507 insertions, 16 deletions
diff --git a/Auth/OpenID/Discover.php b/Auth/OpenID/Discover.php
index 5fd2aa0..1b5aaaa 100644
--- a/Auth/OpenID/Discover.php
+++ b/Auth/OpenID/Discover.php
@@ -120,7 +120,7 @@ function filter_MatchesAnyOpenIDType(&$service)
return false;
}
-function Auth_OpenID_discoverWithYadis($uri)
+function Auth_OpenID_discoverWithYadis($uri, &$fetcher)
{
// Discover OpenID services for a URI. Tries Yadis and falls back
// on old-style <link rel='...'> discovery if Yadis fails.
@@ -131,15 +131,19 @@ function Auth_OpenID_discoverWithYadis($uri)
// to catch it.
$openid_services = array();
- $response = @Services_Yadis_Yadis::discover($uri);
+ $http_response = null;
+ $response = @Services_Yadis_Yadis::discover($uri, $http_response,
+ $fetcher);
if ($response) {
$identity_url = $response->uri;
$openid_services =
$response->xrds->services(array('filter_MatchesAnyOpenIDType'));
- } else {
+ }
+
+ if (!$openid_services) {
return @Auth_OpenID_discoverWithoutYadis($uri,
- Auth_OpenID::getHTTPFetcher());
+ $fetcher);
}
if (!$openid_services) {
@@ -179,38 +183,38 @@ function Auth_OpenID_discoverWithYadis($uri)
$openid_services = $s;
}
- return array($identity_url, $openid_services);
+ return array($identity_url, $openid_services, $http_response);
}
function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher)
{
$http_resp = @$fetcher->get($uri);
- list($code, $url, $body) = $http_resp;
- if ($code != 200) {
- return null;
+ if ($http_resp->status != 200) {
+ return array(null, array(), $http_resp);
}
- $identity_url = $url;
+ $identity_url = $http_resp->final_url;
// Try to parse the response as HTML to get OpenID 1.0/1.1 <link
// rel="...">
$endpoint =& new Auth_OpenID_ServiceEndpoint();
- $service = $endpoint->fromHTML($identity_url, $body);
+ $service = $endpoint->fromHTML($identity_url, $http_resp->body);
if ($service === null) {
$openid_services = array();
} else {
$openid_services = array($service);
}
- return array($identity_url, $openid_services);
+ return array($identity_url, $openid_services, $http_resp);
}
function Auth_OpenID_discover($uri, &$fetcher)
{
global $_yadis_available;
+
if ($_yadis_available) {
- return @Auth_OpenID_discoverWithYadis($uri);
+ return @Auth_OpenID_discoverWithYadis($uri, $fetcher);
} else {
return @Auth_OpenID_discoverWithoutYadis($uri, $fetcher);
}
diff --git a/Auth/OpenID/HTTPFetcher.php b/Auth/OpenID/HTTPFetcher.php
index fb6d1ab..f84e9ab 100644
--- a/Auth/OpenID/HTTPFetcher.php
+++ b/Auth/OpenID/HTTPFetcher.php
@@ -18,6 +18,17 @@
require_once "Auth/OpenID/Parse.php";
require_once "Auth/OpenID.php";
+class Auth_OpenID_HTTPResponse {
+ function Auth_OpenID_HTTPResponse($final_url = null, $status = null,
+ $headers = null, $body = null)
+ {
+ $this->final_url = $final_url;
+ $this->status = $status;
+ $this->headers = $headers;
+ $this->body = $body;
+ }
+}
+
/**
* This is the status code beginAuth returns when it is unable to
* fetch the OpenID URL the user entered.
diff --git a/Auth/OpenID/ParanoidHTTPFetcher.php b/Auth/OpenID/ParanoidHTTPFetcher.php
index c84457b..c4e11cb 100644
--- a/Auth/OpenID/ParanoidHTTPFetcher.php
+++ b/Auth/OpenID/ParanoidHTTPFetcher.php
@@ -111,7 +111,8 @@ class Auth_OpenID_ParanoidHTTPFetcher extends Auth_OpenID_HTTPFetcher {
} else {
$redir = false;
curl_close($c);
- return array($code, $url, $body);
+ return new Services_Yadis_HTTPResponse($url, $code,
+ $headers, $body);
}
$off = $stop - time();
@@ -155,7 +156,8 @@ class Auth_OpenID_ParanoidHTTPFetcher extends Auth_OpenID_HTTPFetcher {
$body = $this->data;
curl_close($c);
- return array($code, $url, $body);
+ return new Auth_OpenID_HTTPResponse($url, $code,
+ $this->headers, $body);
}
}
diff --git a/Auth/OpenID/PlainHTTPFetcher.php b/Auth/OpenID/PlainHTTPFetcher.php
index afb5ace..9dd3600 100644
--- a/Auth/OpenID/PlainHTTPFetcher.php
+++ b/Auth/OpenID/PlainHTTPFetcher.php
@@ -118,7 +118,7 @@ class Auth_OpenID_PlainHTTPFetcher extends Auth_OpenID_HTTPFetcher {
$off = $stop - time();
}
- return array($code, $url, $body);
+ return new Auth_OpenID_HTTPResponse($url, $code, $headers, $body);
}
function post($url, $body)
@@ -203,7 +203,8 @@ class Auth_OpenID_PlainHTTPFetcher extends Auth_OpenID_HTTPFetcher {
$http_code = explode(" ", $headers[0]);
$code = $http_code[1];
- return array($code, $url, $response_body);
+ return new Auth_OpenID_HTTPResponse($url, $code,
+ $headers, $response_body);
}
}
diff --git a/Tests/Auth/OpenID/Discover.php b/Tests/Auth/OpenID/Discover.php
new file mode 100644
index 0000000..4574477
--- /dev/null
+++ b/Tests/Auth/OpenID/Discover.php
@@ -0,0 +1,472 @@
+<?php
+
+require_once 'PHPUnit.php';
+
+require_once 'Auth/OpenID.php';
+require_once 'Auth/OpenID/Discover.php';
+
+/**
+ * Tests for the core of the PHP Yadis library discovery logic.
+ */
+
+class _SimpleMockFetcher {
+ function _SimpleMockFetcher($responses)
+ {
+ $this->responses = $responses;
+ }
+
+ function get($url)
+ {
+ $response = array_pop($this->responses);
+ assert($response[1] == $url);
+ return $response;
+ }
+}
+
+class Tests_Services_Yadis_DiscoveryFailure extends PHPUnit_TestCase {
+
+ function Tests_Services_Yadis_DiscoveryFailure($responses)
+ {
+ // Response is ($code, $url, $body).
+ $this->cases = array(
+ array(null, 'http://network.error/', ''),
+ array(404, 'http://not.found/', ''),
+ array(400, 'http://bad.request/', ''),
+ array(500, 'http://server.error/', ''),
+ array(200, 'http://header.found/', 200,
+ array('x-xrds-location' => 'http://xrds.missing/')),
+ array(404, 'http://xrds.missing/', ''));
+
+ $this->url = $responses[0]->final_url;
+ $this->responses = $responses;
+ $this->fetcher = new _SimpleMockFetcher($this->responses);
+ }
+
+ function runTest()
+ {
+ foreach ($this->cases as $case) {
+ list($status, $url, $body) = $case;
+ $expected_status = $status;
+
+ $result = Auth_OpenID_discover($this->url, $this->fetcher);
+ list($id_url, $svclist, $http_response) = $result;
+
+ $this->assertEquals($http_response->status, $expected_status);
+ }
+ }
+}
+
+### Tests for raising/catching exceptions from the fetcher through the
+### discover function
+
+class _ErrorRaisingFetcher {
+ // Just raise an exception when fetch is called
+
+ function _ErrorRaisingFetcher($thing_to_raise)
+ {
+ $this->thing_to_raise = $thing_to_raise;
+ }
+
+ function post($body = null)
+ {
+ __raiseError($this->thing_to_raise);
+ }
+
+ function get($url)
+ {
+ __raiseError($this->thing_to_raise);
+ }
+}
+
+define('E_AUTH_OPENID_EXCEPTION', 'e_exception');
+define('E_AUTH_OPENID_DIDFETCH', 'e_didfetch');
+define('E_AUTH_OPENID_VALUE_ERROR', 'e_valueerror');
+define('E_AUTH_OPENID_RUNTIME_ERROR', 'e_runtimeerror');
+define('E_AUTH_OPENID_OI', 'e_oi');
+
+class Tests_Auth_OpenID_Discover_FetchException extends PHPUnit_TestCase {
+ // Make sure exceptions get passed through discover function from
+ // fetcher.
+
+ function Tests_Auth_OpenID_Discover_FetchException($exc)
+ {
+ $this->cases = array(E_AUTH_OPENID_EXCEPTION,
+ E_AUTH_OPENID_DIDFETCH,
+ E_AUTH_OPENID_VALUE_ERROR,
+ E_AUTH_OPENID_RUNTIME_ERROR,
+ E_AUTH_OPENID_OI);
+ }
+
+ function runTest()
+ {
+ foreach ($this->cases as $thing_to_raise) {
+ $fetcher = ErrorRaisingFetcher($thing_to_raise);
+ Auth_OpenID_discover('http://doesnt.matter/', $fetcher);
+ $exc = __getError();
+
+ if ($exc !== $thing_to_raise) {
+ $this->fail('FetchException expected %s to be raised',
+ $thing_to_raise);
+ }
+ }
+ }
+}
+
+
+// Tests for openid.consumer.discover.discover
+
+class _DiscoveryMockFetcher {
+ function _DiscoveryMockFetcher(&$documents)
+ {
+ $this->redirect = null;
+ $this->documents = &$documents;
+ $this->fetchlog = array();
+ }
+
+ function post($url, $body = null, $headers = null)
+ {
+ return $this->get($url, $headers, $body);
+ }
+
+ function get($url, $headers = null, $body = null)
+ {
+ $this->fetchlog[] = array($url, $body, $headers);
+
+ if ($this->redirect) {
+ $final_url = $this->redirect;
+ } else {
+ $final_url = $url;
+ }
+
+ if (array_key_exists($url, $this->documents)) {
+ list($ctype, $body) = $this->documents[$url];
+ $status = 200;
+ } else {
+ $status = 404;
+ $ctype = 'text/plain';
+ $body = '';
+ }
+
+ return new Auth_OpenID_HTTPResponse($final_url, $status,
+ array('content-type' => $ctype), $body);
+ }
+}
+
+define('DISCOVERYBASE_ID_URL', "http://someuser.unittest/");
+
+class _DiscoveryBase extends PHPUnit_TestCase {
+ var $id_url = DISCOVERYBASE_ID_URL;
+ var $documents = array();
+
+ function setUp()
+ {
+ $this->fetcher = new _DiscoveryMockFetcher($this->documents);
+ }
+}
+
+$__yadis_2entries = '<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS xmlns:xrds="xri://$xrds"
+ xmlns="xri://$xrd*($v*2.0)"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ >
+ <XRD>
+
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ <openid:Delegate>http://smoker.myopenid.com/</openid:Delegate>
+ </Service>
+
+ <Service priority="20">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.livejournal.com/openid/server.bml</URI>
+ <openid:Delegate>http://frank.livejournal.com/</openid:Delegate>
+ </Service>
+
+ </XRD>
+</xrds:XRDS>
+';
+
+$__yadis_another = '<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS xmlns:xrds="xri://$xrds"
+ xmlns="xri://$xrd*($v*2.0)"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ >
+ <XRD>
+
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://vroom.unittest/server</URI>
+ <openid:Delegate>http://smoker.myopenid.com/</openid:Delegate>
+ </Service>
+ </XRD>
+</xrds:XRDS>
+';
+
+$__yadis_0entries = '<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS xmlns:xrds="xri://$xrds"
+ xmlns="xri://$xrd*($v*2.0)"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ >
+ <XRD>
+ <Service >
+ <Type>http://is-not-openid.unittest/</Type>
+ <URI>http://noffing.unittest./</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
+';
+
+$__yadis_no_delegate = '<?xml version="1.0" encoding="UTF-8"?>
+<xrds:XRDS xmlns:xrds="xri://$xrds"
+ xmlns="xri://$xrd*($v*2.0)"
+ >
+ <XRD>
+ <Service priority="10">
+ <Type>http://openid.net/signon/1.0</Type>
+ <URI>http://www.myopenid.com/server</URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
+';
+
+$__openid_html = '
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <title>Identity Page for Smoker</title>
+<link rel="openid.server" href="http://www.myopenid.com/server" />
+<link rel="openid.delegate" href="http://smoker.myopenid.com/" />
+ </head><body><p>foo</p></body></html>
+';
+
+$__openid_html_no_delegate = '
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <title>Identity Page for Smoker</title>
+<link rel="openid.server" href="http://www.myopenid.com/server" />
+ </head><body><p>foo</p></body></html>
+';
+
+$__openid_and_yadis_html = '
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+ <head>
+ <title>Identity Page for Smoker</title>
+<meta http-equiv="X-XRDS-Location" content="http://someuser.unittest/xrds" />
+<link rel="openid.server" href="http://www.myopenid.com/server" />
+<link rel="openid.delegate" href="http://smoker.myopenid.com/" />
+ </head><body><p>foo</p></body></html>
+';
+
+class Tests_Auth_OpenID_Discover extends _DiscoveryBase {
+ function _usedYadis($service)
+ {
+ $this->assertTrue($service->used_yadis,
+ "Expected to use Yadis");
+ }
+
+ function _notUsedYadis($service)
+ {
+ $this->assertFalse($service->used_yadis,
+ "Expected to use old-style discovery");
+ }
+
+ function test_404()
+ {
+ $result = Auth_OpenID_discover($this->id_url . '/404',
+ $this->fetcher);
+
+ list($id_url, $svclist, $http_response) = $result;
+
+ $this->assertTrue($http_response->status == 404,
+ "Expected 404 status from /404 discovery");
+ }
+
+ function test_noYadis()
+ {
+ global $__openid_html;
+
+ $this->documents[$this->id_url] = array('text/html', $__openid_html);
+
+ list($id_url, $services, $http_response) =
+ Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertEquals(count($services), 1,
+ "More than one service");
+
+ $this->assertEquals($services[0]->server_url,
+ "http://www.myopenid.com/server");
+
+ $this->assertEquals($services[0]->delegate,
+ "http://smoker.myopenid.com/");
+
+ $this->assertEquals($services[0]->identity_url, $this->id_url);
+ $this->_notUsedYadis($services[0]);
+ }
+
+ function test_noOpenID()
+ {
+ $this->fetcher->documents = array(
+ $this->id_url => array('text/plain', "junk"));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertFalse(count($services) > 0);
+ }
+
+ function test_yadis()
+ {
+ global $__yadis_2entries;
+
+ $this->fetcher->documents = array(
+ DISCOVERYBASE_ID_URL => array('application/xrds+xml',
+ $__yadis_2entries));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertEquals(count($services), 2,
+ "Not 2 services");
+
+ $this->assertEquals($services[0]->server_url,
+ "http://www.myopenid.com/server");
+
+ $this->_usedYadis($services[0]);
+
+ $this->assertEquals($services[1]->server_url,
+ "http://www.livejournal.com/openid/server.bml");
+
+ $this->_usedYadis($services[1]);
+ }
+
+ function test_redirect()
+ {
+ global $__openid_html;
+
+ $expected_final_url = "http://elsewhere.unittest/";
+
+ $this->fetcher->redirect = $expected_final_url;
+ $this->fetcher->documents = array(
+ $this->id_url => array('text/html', $__openid_html));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($expected_final_url, $id_url);
+
+ $this->assertEquals(count($services), 1,
+ "More than one service");
+
+ $this->assertEquals($services[0]->server_url,
+ "http://www.myopenid.com/server");
+
+ $this->assertEquals($services[0]->delegate,
+ "http://smoker.myopenid.com/");
+
+ $this->assertEquals($services[0]->identity_url,
+ $expected_final_url);
+
+ $this->_notUsedYadis($services[0]);
+ }
+
+ function test_emptyList()
+ {
+ global $__yadis_0entries;
+
+ $this->fetcher->documents = array(
+ $this->id_url =>
+ array('application/xrds+xml', $__yadis_0entries));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertTrue(count($services) == 0);
+ }
+
+ function test_emptyListWithLegacy()
+ {
+ global $__openid_and_yadis_html,
+ $__yadis_0entries;
+
+ $this->fetcher->documents = array(
+ $this->id_url => array('text/html', $__openid_and_yadis_html),
+ $this->id_url . 'xrds' => array('application/xrds+xml', $__yadis_0entries));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertEquals(count($services), 1,
+ "Not one service");
+
+ $this->assertEquals($services[0]->server_url,
+ "http://www.myopenid.com/server");
+
+ $this->assertEquals($services[0]->identity_url, $this->id_url);
+
+ $this->_notUsedYadis($services[0]);
+ }
+
+ function test_yadisNoDelegate()
+ {
+ global $__yadis_no_delegate;
+
+ $this->fetcher->documents = array(
+ $this->id_url => array('application/xrds+xml', $__yadis_no_delegate));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertEquals(count($services), 1,
+ "Not 1 service");
+
+ $this->assertEquals($services[0]->server_url,
+ "http://www.myopenid.com/server");
+
+ $this->assertEquals($services[0]->delegate, null,
+ 'Delegate should be null');
+
+ $this->_usedYadis($services[0]);
+ }
+
+ function test_openidNoDelegate()
+ {
+ global $__openid_html_no_delegate;
+
+ $this->fetcher->documents = array(
+ $this->id_url => array('text/html',
+ $__openid_html_no_delegate));
+
+ list($id_url, $services, $http) = Auth_OpenID_discover($this->id_url,
+ $this->fetcher);
+
+ $this->assertEquals($this->id_url, $id_url);
+
+ $this->assertEquals($services[0]->server_url,
+ "http://www.myopenid.com/server");
+
+ $this->assertEquals($services[0]->identity_url, $this->id_url);
+
+ $this->assertEquals($services[0]->delegate, null,
+ 'Delegate should be null');
+
+ $this->_notUsedYadis($services[0]);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/Tests/TestDriver.php b/Tests/TestDriver.php
index 7677691..1162516 100644
--- a/Tests/TestDriver.php
+++ b/Tests/TestDriver.php
@@ -116,6 +116,7 @@ $_test_names = array(
'StoreTest',
'Server',
'TrustRoot',
+ 'Discover'
);
function selectTests($names)