summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Auth/OpenID/Message.php4
-rw-r--r--Auth/OpenID/Server.php80
-rw-r--r--Tests/Auth/OpenID/Server.php155
3 files changed, 222 insertions, 17 deletions
diff --git a/Auth/OpenID/Message.php b/Auth/OpenID/Message.php
index 95d1103..6bfc5f8 100644
--- a/Auth/OpenID/Message.php
+++ b/Auth/OpenID/Message.php
@@ -42,6 +42,10 @@ define('Auth_OpenID_BARE_NS', 'Bare namespace');
// return null instead of returning a default.
define('Auth_OpenID_NO_DEFAULT', 'NO DEFAULT ALLOWED');
+// Limit, in bytes, of identity provider and return_to URLs, including
+// response payload. See OpenID 1.1 specification, Appendix D.
+define('Auth_OpenID_OPENID1_URL_LIMIT', 2047);
+
// All OpenID protocol fields. Used to check namespace aliases.
global $Auth_OpenID_OPENID_PROTOCOL_FIELDS;
$Auth_OpenID_OPENID_PROTOCOL_FIELDS = array(
diff --git a/Auth/OpenID/Server.php b/Auth/OpenID/Server.php
index 58501cc..bd2619a 100644
--- a/Auth/OpenID/Server.php
+++ b/Auth/OpenID/Server.php
@@ -127,6 +127,11 @@ define(Auth_OpenID_ENCODE_URL, 'URL/redirect');
/**
* @access private
*/
+define(Auth_OpenID_ENCODE_HTML_FORM, 'HTML form');
+
+/**
+ * @access private
+ */
function Auth_OpenID_isError($obj, $cls = 'Auth_OpenID_ServerError')
{
return is_a($obj, $cls);
@@ -152,18 +157,24 @@ class Auth_OpenID_ServerError {
$this->reference = $reference;
}
+ function getReturnTo()
+ {
+ if ($this->message &&
+ $this->message->hasKey(Auth_OpenID_OPENID_NS, 'return_to')) {
+ return $this->message->getArg(Auth_OpenID_OPENID_NS,
+ 'return_to');
+ } else {
+ return false;
+ }
+ }
+
/**
* Returns the return_to URL for the request which caused this
* error.
*/
function hasReturnTo()
{
- if ($this->message) {
- return $this->message->hasKey(Auth_OpenID_OPENID_NS,
- 'return_to');
- } else {
- return false;
- }
+ return $this->getReturnTo() !== false;
}
/**
@@ -177,15 +188,7 @@ class Auth_OpenID_ServerError {
return null;
}
- $return_to = $this->message->getArg(Auth_OpenID_OPENID_NS,
- 'return_to');
- if (!$return_to) {
- return null;
- }
-
- return Auth_OpenID::appendArgs($return_to,
- array('openid.mode' => 'error',
- 'openid.error' => $this->toString()));
+ return $this->toMessage()->toURL($this->getReturnTo());
}
/**
@@ -201,6 +204,11 @@ class Auth_OpenID_ServerError {
'error' => $this->toString()));
}
+ function toFormMarkup()
+ {
+ return $this->toMessage()->toFormMarkup($this->getReturnTo());
+ }
+
function toMessage()
{
// Generate a Message object for sending to the relying party,
@@ -232,7 +240,13 @@ class Auth_OpenID_ServerError {
global $_Auth_OpenID_Request_Modes;
if ($this->hasReturnTo()) {
- return Auth_OpenID_ENCODE_URL;
+ if ($this->message->isOpenID2() &&
+ (strlen($this->encodeToURL()) >
+ Auth_OpenID_OPENID1_URL_LIMIT)) {
+ return Auth_OpenID_ENCODE_HTML_FORM;
+ } else {
+ return Auth_OpenID_ENCODE_URL;
+ }
}
if (!$this->message) {
@@ -1135,12 +1149,41 @@ class Auth_OpenID_ServerResponse {
global $_Auth_OpenID_Request_Modes;
if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
- return Auth_OpenID_ENCODE_URL;
+ if ($this->fields->isOpenID2() &&
+ (strlen($this->encodeToURL()) >
+ Auth_OpenID_OPENID1_URL_LIMIT)) {
+ return Auth_OpenID_ENCODE_HTML_FORM;
+ } else {
+ return Auth_OpenID_ENCODE_URL;
+ }
} else {
return Auth_OpenID_ENCODE_KVFORM;
}
}
+ /*
+ * Returns the form markup for this response.
+ *
+ * @return str
+ */
+ function toFormMarkup()
+ {
+ return $this->fields->toFormMarkup(
+ $this->fields->getArg(Auth_OpenID_OPENID_NS, 'return_to'));
+ }
+
+ /*
+ * Returns True if this response's encoding is ENCODE_HTML_FORM.
+ * Convenience method for server authors.
+ *
+ * @return bool
+ */
+ function renderAsForm()
+ {
+ return $this->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM;
+ }
+
+
function encodeToURL()
{
return $this->fields->toURL($this->request->return_to);
@@ -1364,6 +1407,9 @@ class Auth_OpenID_Encoder {
$location = $response->encodeToURL();
$wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
array('location' => $location));
+ } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) {
+ $wr = new $cls(AUTH_OPENID_HTTP_OK, array(),
+ $response->toFormMarkup());
} else {
return new Auth_OpenID_EncodingError($response);
}
diff --git a/Tests/Auth/OpenID/Server.php b/Tests/Auth/OpenID/Server.php
index 41cfcab..49e21a5 100644
--- a/Tests/Auth/OpenID/Server.php
+++ b/Tests/Auth/OpenID/Server.php
@@ -89,6 +89,78 @@ class Tests_Auth_OpenID_Test_ServerError extends PHPUnit_TestCase {
$this->assertEquals($result_args, $expected_args);
}
+ function test_browserWithReturnTo_OpenID2_GET()
+ {
+ $return_to = "http://rp.unittest/consumer";
+ // will be a ProtocolError raised by Decode or
+ // CheckIDRequest.answer
+ $args = Auth_OpenID_Message::fromPostArgs(array(
+ 'openid.ns' => Auth_OpenID_OPENID2_NS,
+ 'openid.mode' => 'monkeydance',
+ 'openid.identity' => 'http://wagu.unittest/',
+ 'openid.claimed_id' => 'http://wagu.unittest/',
+ 'openid.return_to' => $return_to));
+
+ $e = new Auth_OpenID_ServerError($args, "plucky");
+ $this->assertTrue($e->hasReturnTo());
+ $expected_args = array('openid.ns' => Auth_OpenID_OPENID2_NS,
+ 'openid.mode' => 'error',
+ 'openid.error' => 'plucky');
+
+ list($rt_base, $result_args_s) = explode('?', $e->encodeToURL(), 2);
+ $result_args = Auth_OpenID::parse_str($result_args_s);
+
+ $this->assertEquals($result_args, $expected_args);
+ }
+
+ function test_browserWithReturnTo_OpenID2_POST()
+ {
+ $return_to = "http://rp.unittest/consumer" . str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT);
+ // will be a ProtocolError raised by Decode or
+ // CheckIDRequest.answer
+ $args = Auth_OpenID_Message::fromPostArgs(array(
+ 'openid.ns' => Auth_OpenID_OPENID2_NS,
+ 'openid.mode' => 'monkeydance',
+ 'openid.identity' => 'http://wagu.unittest/',
+ 'openid.claimed_id' => 'http://wagu.unittest/',
+ 'openid.return_to' => $return_to));
+
+ $e = new Auth_OpenID_ServerError($args, "plucky");
+ $this->assertTrue($e->hasReturnTo());
+ $expected_args = array('openid.ns' => Auth_OpenID_OPENID2_NS,
+ 'openid.mode' => 'error',
+ 'openid.error' => 'plucky');
+
+ $this->assertTrue($e->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM);
+
+ $this->assertTrue($e->toFormMarkup() ==
+ $e->toMessage()->toFormMarkup($args->getArg(Auth_OpenID_OPENID_NS, 'return_to')));
+ }
+
+ function test_browserWithReturnTo_OpenID1_exceeds_limit()
+ {
+ $return_to = "http://rp.unittest/consumer" . str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT);
+ // will be a ProtocolError raised by Decode or
+ // CheckIDRequest.answer
+ $args = Auth_OpenID_Message::fromPostArgs(array(
+ 'openid.mode' => 'monkeydance',
+ 'openid.identity' => 'http://wagu.unittest/',
+ 'openid.return_to' => $return_to));
+
+ $this->assertTrue($args->isOpenID1());
+
+ $e = new Auth_OpenID_ServerError($args, "plucky");
+ $this->assertTrue($e->hasReturnTo());
+ $expected_args = array('openid.mode' => 'error',
+ 'openid.error' => 'plucky');
+
+ $this->assertTrue($e->whichEncoding() == Auth_OpenID_ENCODE_URL);
+
+ list($rt_base, $result_args_s) = explode('?', $e->encodeToURL(), 2);
+ $result_args = Auth_OpenID::parse_str($result_args_s);
+ $this->assertEquals($result_args, $expected_args);
+ }
+
function test_noReturnTo()
{
// will be a ProtocolError raised by Decode or CheckIDRequest.answer
@@ -547,6 +619,89 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase {
$this->op_endpoint);
}
+ function encode($thing) {
+ return $this->encoder->encode($thing);
+ }
+
+ function test_id_res_OpenID2_GET()
+ {
+ /* Check that when an OpenID 2 response does not exceed the
+ OpenID 1 message size, a GET response (i.e., redirect) is
+ issued. */
+ $request = new Auth_OpenID_CheckIDRequest(
+ 'http://bombom.unittest/',
+ 'http://burr.unittest/999',
+ 'http://burr.unittest/',
+ false,
+ $this->server->op_endpoint);
+
+ $response = new Auth_OpenID_ServerResponse($request);
+ $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
+ 'ns' => Auth_OpenID_OPENID2_NS,
+ 'mode' => 'id_res',
+ 'identity' => $request->identity,
+ 'claimed_id' => $request->identity,
+ 'return_to' => $request->return_to));
+
+ $this->assertFalse($response->renderAsForm());
+ $this->assertTrue($response->whichEncoding() == Auth_OpenID_ENCODE_URL);
+ $webresponse = $this->encode($response);
+ $this->assertTrue(array_key_exists('location', $webresponse->headers));
+ }
+
+ function test_id_res_OpenID2_POST()
+ {
+ /* Check that when an OpenID 2 response exceeds the OpenID 1
+ message size, a POST response (i.e., an HTML form) is
+ returned. */
+ $request = new Auth_OpenID_CheckIDRequest(
+ 'http://bombom.unittest/',
+ 'http://burr.unittest/999',
+ 'http://burr.unittest/',
+ false,
+ $this->server->op_endpoint);
+
+ $response = new Auth_OpenID_ServerResponse($request);
+ $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
+ 'ns' => Auth_OpenID_OPENID2_NS,
+ 'mode' => 'id_res',
+ 'identity' => $request->identity,
+ 'claimed_id' => $request->identity,
+ 'return_to' => str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT)));
+
+ $this->assertTrue($response->renderAsForm());
+ $this->assertTrue(strlen($response->encodeToURL()) > Auth_OpenID_OPENID1_URL_LIMIT);
+ $this->assertTrue($response->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM);
+ $webresponse = $this->encode($response);
+ $this->assertEquals($webresponse->body, $response->toFormMarkup());
+ }
+
+ function test_id_res_OpenID1_exceeds_limit()
+ {
+ /* Check that when an OpenID 1 response exceeds the OpenID 1
+ message size, a GET response is issued. Technically, this
+ shouldn't be permitted by the library, but this test is in
+ place to preserve the status quo for OpenID 1. */
+ $request = new Auth_OpenID_CheckIDRequest(
+ 'http://bombom.unittest/',
+ 'http://burr.unittest/999',
+ 'http://burr.unittest/',
+ false,
+ $this->server->op_endpoint);
+
+ $response = new Auth_OpenID_ServerResponse($request);
+ $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
+ 'mode' => 'id_res',
+ 'identity' => $request->identity,
+ 'return_to' => str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT)));
+
+ $this->assertFalse($response->renderAsForm());
+ $this->assertTrue(strlen($response->encodeToURL()) > Auth_OpenID_OPENID1_URL_LIMIT);
+ $this->assertTrue($response->whichEncoding() == Auth_OpenID_ENCODE_URL);
+ $webresponse = $this->encode($response);
+ $this->assertEquals($webresponse->headers['location'], $response->encodeToURL());
+ }
+
function test_id_res()
{
$request = new Auth_OpenID_CheckIDRequest(