diff options
-rw-r--r-- | Auth/OpenID/Association.php | 87 | ||||
-rw-r--r-- | Auth/OpenID/Consumer.php | 2 | ||||
-rw-r--r-- | Auth/OpenID/Server.php | 402 | ||||
-rw-r--r-- | Tests/Auth/OpenID/Consumer.php | 21 | ||||
-rw-r--r-- | Tests/Auth/OpenID/Server.php | 395 |
5 files changed, 395 insertions, 512 deletions
diff --git a/Auth/OpenID/Association.php b/Auth/OpenID/Association.php index 109a970..ef7b734 100644 --- a/Auth/OpenID/Association.php +++ b/Auth/OpenID/Association.php @@ -265,27 +265,69 @@ class Auth_OpenID_Association { * string => string pairs). * @return string $signature The signature, base64 encoded */ - function signDict($fields, $data, $prefix = 'openid.') + function signMessage($message) { - $pairs = array(); - foreach ($fields as $field) { - $pairs[] = array($field, $data[$prefix . $field]); + if ($message->hasKey(Auth_OpenID_OPENID_NS, 'sig') || + $message->hasKey(Auth_OpenID_OPENID_NS, 'signed')) { + // Already has a sig + return null; } - return base64_encode($this->sign($pairs)); + $extant_handle = $message->getArg(Auth_OpenID_OPENID_NS, + 'assoc_handle'); + + if ($extant_handle && ($extant_handle != $this->handle)) { + // raise ValueError("Message has a different association handle") + return null; + } + + $signed_message = $message; + $signed_message->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', + $this->handle); + + $message_keys = array_keys($signed_message->toPostArgs()); + $signed_list = array(); + $signed_prefix = 'openid.'; + + foreach ($message_keys as $k) { + if (strpos($k, $signed_prefix) === 0) { + $signed_list[] = substr($k, strlen($signed_prefix)); + } + } + + $signed_list[] = 'signed'; + sort($signed_list); + + $signed_message->setArg(Auth_OpenID_OPENID_NS, 'signed', + implode(',', $signed_list)); + $sig = $this->getMessageSignature($signed_message); + $signed_message->setArg(Auth_OpenID_OPENID_NS, 'sig', $sig); + return $signed_message; } - /** - * Add a signature to an array of fields - * - * @access private - */ - function addSignature($fields, &$data, $prefix = 'openid.') + function _makePairs(&$message) + { + $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed'); + if (!$signed) { + // raise ValueError('Message has no signed list: %s' % (message,)) + return null; + } + + $signed_list = explode(',', $signed); + $pairs = array(); + $data = $message->toPostArgs(); + foreach ($signed_list as $field) { + $pairs[] = array($field, Auth_OpenID::arrayGet($data, + 'openid.' . + $field, '')); + } + return $pairs; + } + + function getMessageSignature(&$message) { - $sig = $this->signDict($fields, $data, $prefix); - $signed = implode(",", $fields); - $data[$prefix . 'sig'] = $sig; - $data[$prefix . 'signed'] = $signed; + $pairs = $this->_makePairs($message); + return base64_encode($this->sign($pairs)); } /** @@ -294,14 +336,17 @@ class Auth_OpenID_Association { * * @access private */ - function checkSignature($data, $prefix = 'openid.') + function checkMessageSignature(&$message) { - $signed = $data[$prefix . 'signed']; - $fields = explode(",", $signed); - $expected_sig = $this->signDict($fields, $data, $prefix); - $request_sig = $data[$prefix . 'sig']; + $sig = $message->getArg(Auth_OpenID_OPENID_NS, + 'sig'); + + if (!$sig) { + return false; + } - return ($request_sig == $expected_sig); + $calculated_sig = $this->getMessageSignature($message); + return $calculated_sig == $sig; } } diff --git a/Auth/OpenID/Consumer.php b/Auth/OpenID/Consumer.php index 7f2d91f..35255ea 100644 --- a/Auth/OpenID/Consumer.php +++ b/Auth/OpenID/Consumer.php @@ -637,7 +637,7 @@ class Auth_OpenID_GenericConsumer { return new Auth_OpenID_FailureResponse($endpoint, $msg); } - $v_sig = $assoc->signDict($signed_list, $message->toPostArgs()); + $v_sig = $assoc->getMessageSignature($message); if ($v_sig != $sig) { return new Auth_OpenID_FailureResponse($endpoint, diff --git a/Auth/OpenID/Server.php b/Auth/OpenID/Server.php index 405727a..130f541 100644 --- a/Auth/OpenID/Server.php +++ b/Auth/OpenID/Server.php @@ -99,13 +99,13 @@ require_once "Auth/OpenID/DiffieHellman.php"; require_once "Auth/OpenID/KVForm.php"; require_once "Auth/OpenID/TrustRoot.php"; require_once "Auth/OpenID/ServerRequest.php"; +require_once "Auth/OpenID/Message.php"; define('AUTH_OPENID_HTTP_OK', 200); define('AUTH_OPENID_HTTP_REDIRECT', 302); define('AUTH_OPENID_HTTP_ERROR', 400); global $_Auth_OpenID_Request_Modes, - $_Auth_OpenID_OpenID_Prefix, $_Auth_OpenID_Encode_Kvform, $_Auth_OpenID_Encode_Url; @@ -118,11 +118,6 @@ $_Auth_OpenID_Request_Modes = array('checkid_setup', /** * @access private */ -$_Auth_OpenID_OpenID_Prefix = "openid."; - -/** - * @access private - */ $_Auth_OpenID_Encode_Kvform = array('kfvorm'); /** @@ -149,10 +144,10 @@ class Auth_OpenID_ServerError { /** * @access private */ - function Auth_OpenID_ServerError($query = null, $message = null) + function Auth_OpenID_ServerError($message, $text = null) { $this->message = $message; - $this->query = $query; + $this->text = $text; } /** @@ -161,10 +156,9 @@ class Auth_OpenID_ServerError { */ function hasReturnTo() { - global $_Auth_OpenID_OpenID_Prefix; - if ($this->query) { - return array_key_exists($_Auth_OpenID_OpenID_Prefix . - 'return_to', $this->query); + if ($this->message) { + return $this->message->hasKey(Auth_OpenID_OPENID_NS, + 'return_to'); } else { return false; } @@ -177,10 +171,8 @@ class Auth_OpenID_ServerError { */ function encodeToURL() { - global $_Auth_OpenID_OpenID_Prefix; - $return_to = Auth_OpenID::arrayGet($this->query, - $_Auth_OpenID_OpenID_Prefix . - 'return_to'); + $return_to = $this->message->getArg(Auth_OpenID_OPENID_NS, + 'return_to'); if (!$return_to) { return new Auth_OpenID_ServerError(null, "no return_to URL"); } @@ -218,7 +210,8 @@ class Auth_OpenID_ServerError { return $_Auth_OpenID_Encode_Url; } - $mode = Auth_OpenID::arrayGet($this->query, 'openid.mode'); + $mode = $this->message->getArg(Auth_OpenID_OPENID_NS, + 'mode'); if ($mode) { if (!in_array($mode, $_Auth_OpenID_Request_Modes)) { @@ -233,8 +226,8 @@ class Auth_OpenID_ServerError { */ function toString() { - if ($this->message) { - return $this->message; + if ($this->text) { + return $this->text; } else { return get_class($this) . " error"; } @@ -247,10 +240,10 @@ class Auth_OpenID_ServerError { * @package OpenID */ class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError { - function Auth_OpenID_MalformedReturnURL($query, $return_to) + function Auth_OpenID_MalformedReturnURL($message, $return_to) { $this->return_to = $return_to; - parent::Auth_OpenID_ServerError($query, "malformed return_to URL"); + parent::Auth_OpenID_ServerError($message, "malformed return_to URL"); } } @@ -286,85 +279,77 @@ class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request { var $mode = "check_authentication"; var $invalidate_handle = null; - function Auth_OpenID_CheckAuthRequest($assoc_handle, $sig, $signed, + function Auth_OpenID_CheckAuthRequest($assoc_handle, $signed, $invalidate_handle = null) { $this->assoc_handle = $assoc_handle; - $this->sig = $sig; $this->signed = $signed; if ($invalidate_handle !== null) { $this->invalidate_handle = $invalidate_handle; } + $this->namespace = Auth_OpenID_OPENID2_NS; + $this->message = null; } - function fromQuery($query) + function fromMessage($message) { - global $_Auth_OpenID_OpenID_Prefix; - $required_keys = array('assoc_handle', 'sig', 'signed'); foreach ($required_keys as $k) { - if (!array_key_exists($_Auth_OpenID_OpenID_Prefix . $k, - $query)) { - return new Auth_OpenID_ServerError($query, + if (!$message->getArg(Auth_OpenID_OPENID_NS, $k)) { + return new Auth_OpenID_ServerError($message, sprintf("%s request missing required parameter %s from \ query", "check_authentication", $k)); } } - $assoc_handle = $query[$_Auth_OpenID_OpenID_Prefix . 'assoc_handle']; - $sig = $query[$_Auth_OpenID_OpenID_Prefix . 'sig']; - $signed_list = $query[$_Auth_OpenID_OpenID_Prefix . 'signed']; + $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle'); + $sig = $message->getArg(Auth_OpenID_OPENID_NS, 'sig'); + $signed_list = $message->getArg(Auth_OpenID_OPENID_NS, 'signed'); $signed_list = explode(",", $signed_list); - $signed_pairs = array(); foreach ($signed_list as $field) { - if ($field == 'mode') { - // XXX KLUDGE HAX WEB PROTOCoL BR0KENNN - // - // openid.mode is currently check_authentication - // because that's the mode of this request. But the - // signature was made on something with a different - // openid.mode. - $value = "id_res"; - } else { - if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field, - $query)) { - $value = $query[$_Auth_OpenID_OpenID_Prefix . $field]; - } else { - return new Auth_OpenID_ServerError($query, - sprintf("Couldn't find signed field %r in query %s", - $field, var_export($query, true))); - } + if (!$message->hasKey(Auth_OpenID_OPENID_NS, $field)) { + return new Auth_OpenID_ServerError($message, + sprintf("Couldn't find signed field %s in query", + $field)); } - $signed_pairs[] = array($field, $value); } - $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $sig, - $signed_pairs); - $result->invalidate_handle = Auth_OpenID::arrayGet($query, - $_Auth_OpenID_OpenID_Prefix . 'invalidate_handle'); + $signed = $message; + if ($signed->hasKey(Auth_OpenID_OPENID_NS, 'mode')) { + $signed->setArg(Auth_OpenID_OPENID_NS, 'mode', 'id_res'); + } + + $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $signed); + $result->message = $message; + $result->sig = $sig; + $result->invalidate_handle = $message->getArg(Auth_OpenID_OPENID_NS, + 'invalidate_handle'); return $result; } function answer(&$signatory) { - $is_valid = $signatory->verify($this->assoc_handle, $this->sig, - $this->signed); + $is_valid = $signatory->verify($this->assoc_handle, $this->signed); // Now invalidate that assoc_handle so it this checkAuth // message cannot be replayed. $signatory->invalidate($this->assoc_handle, true); $response = new Auth_OpenID_ServerResponse($this); - $response->fields['is_valid'] = $is_valid ? "true" : "false"; + + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'is_valid', + ($is_valid ? "true" : "false")); if ($this->invalidate_handle) { $assoc = $signatory->getAssociation($this->invalidate_handle, false); if (!$assoc) { - $response->fields['invalidate_handle'] = - $this->invalidate_handle; + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'invalidate_handle', + $this->invalidate_handle); } } return $response; @@ -379,7 +364,7 @@ class Auth_OpenID_PlainTextServerSession { var $session_type = 'plaintext'; var $needs_math = false; - function fromQuery($unused_request) + function fromMessage($unused_request) { return new Auth_OpenID_PlainTextServerSession(); } @@ -405,10 +390,10 @@ class Auth_OpenID_DiffieHellmanServerSession { $this->consumer_pubkey = $consumer_pubkey; } - function fromQuery($query) + function fromMessage($message) { - $dh_modulus = Auth_OpenID::arrayGet($query, 'openid.dh_modulus'); - $dh_gen = Auth_OpenID::arrayGet($query, 'openid.dh_gen'); + $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus'); + $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen'); if ((($dh_modulus === null) && ($dh_gen !== null)) || (($dh_gen === null) && ($dh_modulus !== null))) { @@ -419,7 +404,7 @@ class Auth_OpenID_DiffieHellmanServerSession { $missing = 'generator'; } - return new Auth_OpenID_ServerError( + return new Auth_OpenID_ServerError($message, 'If non-default modulus or generator is '. 'supplied, both must be supplied. Missing '. $missing); @@ -433,17 +418,17 @@ class Auth_OpenID_DiffieHellmanServerSession { if ($lib->cmp($dh_modulus, 0) == 0 || $lib->cmp($dh_gen, 0) == 0) { return new Auth_OpenID_ServerError( - $query, "Failed to parse dh_mod or dh_gen"); + $message, "Failed to parse dh_mod or dh_gen"); } $dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen); } else { $dh = new Auth_OpenID_DiffieHellman(); } - $consumer_pubkey = Auth_OpenID::arrayGet($query, - 'openid.dh_consumer_public'); + $consumer_pubkey = $message->getArg(Auth_OpenID_OPENID_NS, + 'dh_consumer_public'); if ($consumer_pubkey === null) { - return new Auth_OpenID_ServerError( + return new Auth_OpenID_ServerError($message, 'Public key for DH-SHA1 session '. 'not found in query'); } @@ -452,7 +437,7 @@ class Auth_OpenID_DiffieHellmanServerSession { $lib->base64ToLong($consumer_pubkey); if ($consumer_pubkey === false) { - return new Auth_OpenID_ServerError($query, + return new Auth_OpenID_ServerError($message, "dh_consumer_public is not base64"); } @@ -484,26 +469,20 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { function Auth_OpenID_AssociateRequest(&$session) { $this->session =& $session; + $this->namespace = Auth_OpenID_OPENID2_NS; } - function fromQuery($query) + function fromMessage($message) { - global $_Auth_OpenID_OpenID_Prefix; - $session_classes = array( 'DH-SHA1' => 'Auth_OpenID_DiffieHellmanServerSession', null => 'Auth_OpenID_PlainTextServerSession'); - $session_type = null; - - if (array_key_exists($_Auth_OpenID_OpenID_Prefix . 'session_type', - $query)) { - $session_type = $query[$_Auth_OpenID_OpenID_Prefix . - 'session_type']; - } + $session_type = $message->getArg(Auth_OpenID_OPENID_NS, + 'session_type'); if (!array_key_exists($session_type, $session_classes)) { - return new Auth_OpenID_ServerError($query, + return new Auth_OpenID_ServerError($message, "Unknown session type $session_type"); } @@ -516,12 +495,12 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { $session_cls = $session_classes[null]; } } - $session = call_user_func_array(array($session_cls, 'fromQuery'), - array($query)); + $session = call_user_func_array(array($session_cls, 'fromMessage'), + array($message)); if (($session === null) || (Auth_OpenID_isError($session))) { - return new Auth_OpenID_ServerError($query, + return new Auth_OpenID_ServerError($message, "Error parsing $session_type session"); } @@ -532,17 +511,20 @@ class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request { { $response = new Auth_OpenID_ServerResponse($this); - $response->fields = array('expires_in' => $assoc->getExpiresIn(), - 'assoc_type' => 'HMAC-SHA1', - 'assoc_handle' => $assoc->handle); + $response->fields->updateArgs(Auth_OpenID_OPENID_NS, + array('expires_in' => $assoc->getExpiresIn(), + 'assoc_type' => 'HMAC-SHA1', + 'assoc_handle' => $assoc->handle)); $r = $this->session->answer($assoc->secret); foreach ($r as $k => $v) { - $response->fields[$k] = $v; + $response->fields->setArg(Auth_OpenID_OPENID_NS, $k, $v); } if ($this->session->session_type != 'plaintext') { - $response->fields['session_type'] = $this->session->session_type; + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'session_type', + $this->session->session_type); } return $response; @@ -560,19 +542,22 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { var $immediate = false; var $trust_root = null; - function make($query, $identity, $return_to, $trust_root = null, + function make(&$message, $identity, $return_to, $trust_root = null, $immediate = false, $assoc_handle = null) { if (!Auth_OpenID_TrustRoot::_parse($return_to)) { - return new Auth_OpenID_MalformedReturnURL($query, $return_to); + return new Auth_OpenID_MalformedReturnURL($message, $return_to); } $r = new Auth_OpenID_CheckIDRequest($identity, $return_to, $trust_root, $immediate, $assoc_handle); + $r->namespace = $message->getOpenIDNamespace(); + if (!$r->trustRootValid()) { - return new Auth_OpenID_UntrustedReturnURL($return_to, + return new Auth_OpenID_UntrustedReturnURL($message, + $return_to, $trust_root); } else { return $r; @@ -595,13 +580,13 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { $this->immediate = false; $this->mode = "checkid_setup"; } + + $this->namespace = Auth_OpenID_OPENID2_NS; } - function fromQuery($query) + function fromMessage(&$message) { - global $_Auth_OpenID_OpenID_Prefix; - - $mode = $query[$_Auth_OpenID_OpenID_Prefix . 'mode']; + $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); $immediate = null; if ($mode == "checkid_immediate") { @@ -621,11 +606,10 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { $values = array(); foreach ($required as $field) { - if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field, - $query)) { - $value = $query[$_Auth_OpenID_OpenID_Prefix . $field]; + if ($message->hasKey(Auth_OpenID_OPENID_NS, $field)) { + $value = $message->getArg(Auth_OpenID_OPENID_NS, $field); } else { - return new Auth_OpenID_ServerError($query, + return new Auth_OpenID_ServerError($message, sprintf("Missing required field %s from request", $field)); } @@ -633,22 +617,19 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { } foreach ($optional as $field) { - $value = null; - if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field, - $query)) { - $value = $query[$_Auth_OpenID_OpenID_Prefix. $field]; - } + $value = $message->getArg(Auth_OpenID_OPENID_NS, $field); + if ($value) { $values[$field] = $value; } } if (!Auth_OpenID_TrustRoot::_parse($values['return_to'])) { - return new Auth_OpenID_MalformedReturnURL($query, + return new Auth_OpenID_MalformedReturnURL($message, $values['return_to']); } - $obj = Auth_OpenID_CheckIDRequest::make($query, + $obj = Auth_OpenID_CheckIDRequest::make($message, $values['identity'], $values['return_to'], Auth_OpenID::arrayGet($values, @@ -689,17 +670,23 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { $mode = 'cancel'; } - $response = new Auth_OpenID_CheckIDResponse($this, $mode); + if (!$this->trustRootValid()) { + return new Auth_OpenID_UntrustedReturnURL(null, + $this->return_to, + $this->trust_root); + } + + $response = new Auth_OpenID_ServerResponse($this); if ($allow) { - $response->fields['identity'] = $this->identity; - $response->fields['return_to'] = $this->return_to; - if (!$this->trustRootValid()) { - return new Auth_OpenID_UntrustedReturnURL($this->return_to, - $this->trust_root); - } + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'identity', + $this->identity); + + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'return_to', + $this->return_to); } else { - $response->signed = array(); if ($this->immediate) { if (!$server_url) { return new Auth_OpenID_ServerError(null, @@ -716,17 +703,19 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { $setup_url = $setup_request->encodeToURL($server_url); - $response->fields['user_setup_url'] = $setup_url; + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'user_setup_url', + $setup_url); } } + $response->fields->setArg(Auth_OpenID_OPENID_NS, + 'mode', $mode); return $response; } function encodeToURL($server_url) { - global $_Auth_OpenID_OpenID_Prefix; - // Imported from the alternate reality where these classes are // used in both the client and server code, so Requests are // Encodable too. That's right, code imported from alternate @@ -744,18 +733,18 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { $q['assoc_handle'] = $this->assoc_handle; } - $_q = array(); + $response = new Auth_OpenID_Message($this->namespace); + $response->updateArgs($this->namespace, $q); - foreach ($q as $k => $v) { - $_q[$_Auth_OpenID_OpenID_Prefix . $k] = $v; - } - - return Auth_OpenID::appendArgs($server_url, $_q); + return $response->toURL($server_url); } function getCancelURL() { - global $_Auth_OpenID_OpenID_Prefix; + if (!$this->return_to) { + return new Auth_OpenID_ServerError(null, + "checkid request has no return_to"); + } if ($this->immediate) { return new Auth_OpenID_ServerError(null, @@ -764,9 +753,9 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { requests."); } - return Auth_OpenID::appendArgs($this->return_to, - array($_Auth_OpenID_OpenID_Prefix . 'mode' => - 'cancel')); + $response = new Auth_OpenID_Message($this->namespace); + $response->setArg(Auth_OpenID_OPENID_NS, 'mode', 'cancel'); + return $response->toURL($this->return_to); } } @@ -778,10 +767,10 @@ class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request { */ class Auth_OpenID_ServerResponse { - function Auth_OpenID_ServerResponse($request) + function Auth_OpenID_ServerResponse(&$request) { - $this->request = $request; - $this->fields = array(); + $this->request =& $request; + $this->fields = new Auth_OpenID_Message($this->request->namespace); } function whichEncoding() @@ -799,72 +788,18 @@ class Auth_OpenID_ServerResponse { function encodeToURL() { - global $_Auth_OpenID_OpenID_Prefix; - - $fields = array(); - - foreach ($this->fields as $k => $v) { - $fields[$_Auth_OpenID_OpenID_Prefix . $k] = $v; - } - - return Auth_OpenID::appendArgs($this->request->return_to, $fields); - } - - function encodeToKVForm() - { - return Auth_OpenID_KVForm::fromArray($this->fields); - } -} - -/** - * A response to a checkid request. - * - * @access private - * @package OpenID - */ -class Auth_OpenID_CheckIDResponse extends Auth_OpenID_ServerResponse { - - function Auth_OpenID_CheckIDResponse(&$request, $mode = 'id_res') - { - parent::Auth_OpenID_ServerResponse($request); - $this->fields['mode'] = $mode; - $this->signed = array(); - - if ($mode == 'id_res') { - array_push($this->signed, 'mode', 'identity', 'return_to'); - } + return $this->fields->toURL($this->request->return_to); } - function addField($namespace, $key, $value, $signed = true) + function needsSigning() { - if ($namespace) { - $key = sprintf('%s.%s', $namespace, $key); - } - $this->fields[$key] = $value; - if ($signed && !in_array($key, $this->signed)) { - $this->signed[] = $key; - } + return $this->fields->getArg(Auth_OpenID_OPENID_NS, + 'mode') == 'id_res'; } - function addFields($namespace, $fields, $signed = true) - { - foreach ($fields as $k => $v) { - $this->addField($namespace, $k, $v, $signed); - } - } - - function update($namespace, $other) + function encodeToKVForm() { - $namespaced_fields = array(); - - foreach ($other->fields as $k => $v) { - $name = sprintf('%s.%s', $namespace, $k); - - $namespaced_fields[$name] = $v; - } - - $this->fields = array_merge($this->fields, $namespaced_fields); - $this->signed = array_merge($this->signed, $other->signed); + return $this->fields->toKVForm(); } } @@ -928,7 +863,7 @@ class Auth_OpenID_Signatory { * Verify, using a given association handle, a signature with * signed key-value pairs from an HTTP request. */ - function verify($assoc_handle, $sig, $signed_pairs) + function verify($assoc_handle, $message) { $assoc = $this->getAssociation($assoc_handle, true); if (!$assoc) { @@ -937,9 +872,7 @@ class Auth_OpenID_Signatory { return false; } - $expected_sig = base64_encode($assoc->sign($signed_pairs)); - - return $sig == $expected_sig; + return $assoc->checkMessageSignature($message); } /** @@ -956,7 +889,8 @@ class Auth_OpenID_Signatory { $assoc = $this->getAssociation($assoc_handle, false); if (!$assoc) { // fall back to dumb mode - $signed_response->fields['invalidate_handle'] = $assoc_handle; + $signed_response->fields->setArg(Auth_OpenID_OPENID_NS, + 'invalidate_handle', $assoc_handle); $assoc = $this->createAssociation(true); } } else { @@ -964,9 +898,8 @@ class Auth_OpenID_Signatory { $assoc = $this->createAssociation(true); } - $signed_response->fields['assoc_handle'] = $assoc->handle; - $assoc->addSignature($signed_response->signed, - $signed_response->fields, ''); + $signed_response->fields = $assoc->signMessage( + $signed_response->fields); return $signed_response; } @@ -1071,18 +1004,6 @@ class Auth_OpenID_Encoder { } /** - * Returns true if the given response needs a signature. - * - * @access private - */ -function needsSigning($response) -{ - return (in_array($response->request->mode, array('checkid_setup', - 'checkid_immediate')) && - $response->signed); -} - -/** * An encoder which also takes care of signing fields when required. * * @package OpenID @@ -1103,17 +1024,19 @@ class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder { // the isinstance is a bit of a kludge... it means there isn't // really an adapter to make the interfaces quite match. if (!is_a($response, 'Auth_OpenID_ServerError') && - needsSigning($response)) { + $response->needsSigning()) { if (!$this->signatory) { return new Auth_OpenID_ServerError(null, "Must have a store to sign request"); } - if (array_key_exists('sig', $response->fields)) { + + if ($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')) { return new Auth_OpenID_AlreadySigned($response); } $response = $this->signatory->sign($response); } + return parent::encode($response); } } @@ -1128,9 +1051,6 @@ class Auth_OpenID_Decoder { function Auth_OpenID_Decoder() { - global $_Auth_OpenID_OpenID_Prefix; - $this->prefix = $_Auth_OpenID_OpenID_Prefix; - $this->handlers = array( 'checkid_setup' => 'Auth_OpenID_CheckIDRequest', 'checkid_immediate' => 'Auth_OpenID_CheckIDRequest', @@ -1149,39 +1069,29 @@ class Auth_OpenID_Decoder { return null; } - $myquery = array(); + $message = Auth_OpenID_Message::fromPostArgs($query); - foreach ($query as $k => $v) { - if (strpos($k, $this->prefix) === 0) { - $myquery[$k] = $v; - } - } - - if (!$myquery) { - return null; - } - - $mode = Auth_OpenID::arrayGet($myquery, $this->prefix . 'mode'); + $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); if (!$mode) { - return new Auth_OpenID_ServerError($query, - sprintf("No %s mode found in query", $this->prefix)); + return new Auth_OpenID_ServerError($message, + "No mode value in message"); } $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode, - $this->defaultDecoder($query)); + $this->defaultDecoder($message)); if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) { - return call_user_func_array(array($handlerCls, 'fromQuery'), - array($query)); + return call_user_func_array(array($handlerCls, 'fromMessage'), + array($message)); } else { return $handlerCls; } } - function defaultDecoder($query) + function defaultDecoder($message) { - $mode = $query[$this->prefix . 'mode']; - return new Auth_OpenID_ServerError($query, + $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); + return new Auth_OpenID_ServerError($message, sprintf("No decoder for mode %s", $mode)); } } @@ -1214,26 +1124,18 @@ class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError { * @package OpenID */ class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError { - function Auth_OpenID_UntrustedReturnURL($return_to, $trust_root) + function Auth_OpenID_UntrustedReturnURL($message, $return_to, + $trust_root) { - global $_Auth_OpenID_OpenID_Prefix; - - $query = array( - $_Auth_OpenID_OpenID_Prefix . 'return_to' => $return_to, - $_Auth_OpenID_OpenID_Prefix . 'trust_root' => $trust_root); - - parent::Auth_OpenID_ServerError($query); + parent::Auth_OpenID_ServerError($message); + $this->return_to = $return_to; + $this->trust_root = $trust_root; } function toString() { - global $_Auth_OpenID_OpenID_Prefix; - - $return_to = $this->query[$_Auth_OpenID_OpenID_Prefix . 'return_to']; - $trust_root = $this->query[$_Auth_OpenID_OpenID_Prefix . 'trust_root']; - return sprintf("return_to %s not under trust_root %s", - $return_to, $trust_root); + $this->return_to, $this->trust_root); } } diff --git a/Tests/Auth/OpenID/Consumer.php b/Tests/Auth/OpenID/Consumer.php index 7ff98bb..b135f9a 100644 --- a/Tests/Auth/OpenID/Consumer.php +++ b/Tests/Auth/OpenID/Consumer.php @@ -209,14 +209,7 @@ class Tests_Auth_OpenID_Consumer extends PHPUnit_TestCase { 'openid.assoc_handle'=> $fetcher->assoc_handle, ); - if ($consumer->_use_assocs) { - $assoc = $store->getAssociation($_Auth_OpenID_server_url, - $fetcher->assoc_handle); - - $assoc->addSignature(array('mode', 'return_to', - 'assoc_handle', 'identity'), - $query); - } else { + if (!$consumer->_use_assocs) { $query['openid.signed'] = 'assoc_handle,mode,signed,identity'; $query['openid.assoc_handle'] = $fetcher->assoc_handle; @@ -225,6 +218,12 @@ class Tests_Auth_OpenID_Consumer extends PHPUnit_TestCase { $message = Auth_OpenID_Message::fromPostArgs($query); + if ($consumer->_use_assocs) { + $assoc = $store->getAssociation($_Auth_OpenID_server_url, + $fetcher->assoc_handle); + $message = $assoc->signMessage($message); + } + $result = $consumer->complete($message, $result->endpoint); if ($result->status != Auth_OpenID_SUCCESS) { @@ -542,9 +541,8 @@ class Tests_Auth_OpenID_Consumer_TestCheckAuthTriggered extends _TestIdRes { 'openid.identity' => $this->server_id, 'openid.assoc_handle' => $good_handle); - $good_assoc->addSignature(array('return_to', 'identity'), $query); - $message = Auth_OpenID_Message::fromPostArgs($query); + $message = $good_assoc->signMessage($message); $info = $this->_doIdRes($message); $this->assertEquals($info->status, 'success'); @@ -983,8 +981,7 @@ class Tests_Auth_OpenID_ParseAssociation extends _TestIdRes { function _setUpDH() { list($sess, $message) = $this->consumer->_createAssociateRequest($this->server_url); - $args = $message->toPostArgs(); - $server_sess = Auth_OpenID_DiffieHellmanServerSession::fromQuery($args); + $server_sess = Auth_OpenID_DiffieHellmanServerSession::fromMessage($message); $server_resp = $server_sess->answer($this->secret); $server_resp['assoc_type'] = 'HMAC-SHA1'; $server_resp['assoc_handle'] = 'handle'; diff --git a/Tests/Auth/OpenID/Server.php b/Tests/Auth/OpenID/Server.php index 5bad281..aa6464e 100644 --- a/Tests/Auth/OpenID/Server.php +++ b/Tests/Auth/OpenID/Server.php @@ -64,7 +64,11 @@ class Tests_Auth_OpenID_Test_ServerError extends PHPUnit_TestCase { 'openid.mode' => 'monkeydance', 'openid.identity' => 'http://wagu.unittest/', 'openid.return_to' => $return_to); - $e = new Auth_OpenID_ServerError($args, "plucky"); + + $e = new Auth_OpenID_ServerError( + Auth_OpenID_Message::fromPostArgs($args), + "plucky"); + $this->assertTrue($e->hasReturnTo()); $expected_args = array( 'openid.mode' => 'error', @@ -91,7 +95,10 @@ class Tests_Auth_OpenID_Test_ServerError extends PHPUnit_TestCase { 'openid.mode' => 'zebradance', 'openid.identity' => 'http://wagu.unittest/'); - $e = new Auth_OpenID_ServerError($args, "waffles"); + $e = new Auth_OpenID_ServerError( + Auth_OpenID_Message::fromPostArgs($args), + "waffles"); + $this->assertFalse($e->hasReturnTo()); $expected = "error:waffles\nmode:error\n"; $this->assertEquals($e->encodeToKVForm(), $expected); @@ -123,7 +130,7 @@ class Tests_Auth_OpenID_Test_Decode extends PHPUnit_TestCase { $r = $this->decoder->decode($args); - $this->assertTrue($r === null); + $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError')); } function test_bad() @@ -187,7 +194,7 @@ class Tests_Auth_OpenID_Test_Decode extends PHPUnit_TestCase { $result = $this->decoder->decode($args); if (Auth_OpenID_isError($result)) { - $this->assertTrue($result->query); + $this->assertTrue($result->message); } else { $this->fail(sprintf("Expected Auth_OpenID_Error, instead " . "returned with %s", gettype($result))); @@ -218,7 +225,7 @@ class Tests_Auth_OpenID_Test_Decode extends PHPUnit_TestCase { $result = $this->decoder->decode($args);; if (Auth_OpenID_isError($result)) { - $this->assertTrue($result->query); + $this->assertTrue($result->message); } else { $this->fail(sprintf("Expected ProtocolError, instead " . "returned with %s", gettype($result))); @@ -240,10 +247,6 @@ class Tests_Auth_OpenID_Test_Decode extends PHPUnit_TestCase { $this->assertTrue(is_a($r, 'Auth_OpenID_CheckAuthRequest')); $this->assertEquals($r->mode, 'check_authentication'); $this->assertEquals($r->sig, 'sigblob'); - $this->assertEquals($r->signed, array( - array('foo', 'signedval1'), - array('bar', 'signedval2'), - array('mode', 'id_res'))); } function test_checkAuthMissingSignedField() @@ -464,11 +467,12 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { 'http://burr.unittest/999', false); - $response = new Auth_OpenID_CheckIDResponse($request); - $response->fields = array( - 'mode' => 'id_res', - 'identity' => $request->identity, - 'return_to' => $request->return_to); + $response = new Auth_OpenID_ServerResponse($request); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs( + array( + 'mode' => 'id_res', + 'identity' => $request->identity, + 'return_to' => $request->return_to)); $webresponse = $this->encoder->encode($response); $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT); @@ -482,15 +486,9 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { $parsed = parse_url($location); $query = array(); - parse_str($parsed['query'], $query); - $query = Auth_OpenID::fixArgs($query); - - $expected = array(); - - foreach ($response->fields as $k => $v) { - $expected['openid.' . $k] = $v; - } + $query = Auth_OpenID::parse_str($parsed['query']); + $expected = $response->fields->toPostArgs(); $this->assertEquals($query, $expected); } @@ -502,8 +500,8 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { 'http://burr.unittest/999', false); - $response = new Auth_OpenID_CheckIDResponse($request); - $response->fields = array('mode' => 'cancel'); + $response = new Auth_OpenID_ServerResponse($request); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array('mode' => 'cancel')); $webresponse = $this->encoder->encode($response); $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT); @@ -513,9 +511,11 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { function test_assocReply() { if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) { - $request = Auth_OpenID_AssociateRequest::fromQuery(array()); + $message = new Auth_OpenID_Message(); + $request = Auth_OpenID_AssociateRequest::fromMessage($message); $response = new Auth_OpenID_ServerResponse($request); - $response->fields = array('assoc_handle' => "every-zig"); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs( + array('assoc_handle' => "every-zig")); $webresponse = $this->encoder->encode($response); $body = "assoc_handle:every-zig\n"; $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_OK); @@ -530,9 +530,9 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { 'siggggg', array()); $response = new Auth_OpenID_ServerResponse($request); - $response->fields = array( + $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array( 'is_valid' => 'true', - 'invalidate_handle' => 'xXxX:xXXx'); + 'invalidate_handle' => 'xXxX:xXXx')); $body = "invalidate_handle:xXxX:xXXx\nis_valid:true\n"; $webresponse = $this->encoder->encode($response); @@ -545,7 +545,8 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { { $args = array('openid.identity' => 'http://limu.unittest/'); - $e = new Auth_OpenID_ServerError($args, "wet paint"); + $e = new Auth_OpenID_ServerError(Auth_OpenID_Message::fromPostArgs($args), + "wet paint"); $result = $this->encoder->encode($e); if (!Auth_OpenID_isError($result, 'Auth_OpenID_EncodingError')) { @@ -561,7 +562,9 @@ class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase { 'openid.identity' => 'http://limu.unittest/'); $body="error:snoot\nmode:error\n"; - $err = new Auth_OpenID_ServerError($args, "snoot"); + $err = new Auth_OpenID_ServerError(Auth_OpenID_Message::fromPostArgs($args), + "snoot"); + $webresponse = $this->encoder->encode($err); $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_ERROR); $this->assertEquals($webresponse->headers, array()); @@ -581,11 +584,11 @@ class Tests_Auth_OpenID_SigningEncode extends PHPUnit_TestCase { 'http://burr.unittest/999', false); - $this->response = new Auth_OpenID_CheckIDResponse($this->request); - $this->response->fields = array( + $this->response = new Auth_OpenID_ServerResponse($this->request); + $this->response->fields = Auth_OpenID_Message::fromOpenIDArgs(array( 'mode' => 'id_res', 'identity' => $this->request->identity, - 'return_to' => $this->request->return_to); + 'return_to' => $this->request->return_to)); $this->signatory = new Auth_OpenID_Signatory($this->store); $this->dumb_key = $this->signatory->dumb_key; @@ -651,7 +654,7 @@ class Tests_Auth_OpenID_SigningEncode extends PHPUnit_TestCase { 'http://burr.unittest/999', false); - $response = new Auth_OpenID_CheckIDResponse($request, 'cancel'); + $response = new Auth_OpenID_ServerResponse($request, 'cancel'); $webresponse = $this->encoder->encode($response); $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT); $this->assertTrue(array_key_exists('location', $webresponse->headers)); @@ -666,9 +669,11 @@ class Tests_Auth_OpenID_SigningEncode extends PHPUnit_TestCase { function test_assocReply() { if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) { - $request = Auth_OpenID_AssociateRequest::fromQuery(array()); + $message = new Auth_OpenID_Message(); + $request = Auth_OpenID_AssociateRequest::fromMessage($message); $response = new Auth_OpenID_ServerResponse($request); - $response->fields = array('assoc_handle' => "every-zig"); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs( + array('assoc_handle' => "every-zig")); $webresponse = $this->encoder->encode($response); $body = "assoc_handle:every-zig\n"; @@ -680,7 +685,7 @@ class Tests_Auth_OpenID_SigningEncode extends PHPUnit_TestCase { function test_alreadySigned() { - $this->response->fields['sig'] = 'priorSig=='; + $this->response->fields->setArg(Auth_OpenID_OPENID_NS, 'sig', 'priorSig=='); $result = $this->encoder->encode($this->response); if (!is_a($result, 'Auth_OpenID_AlreadySigned')) { $this->fail(sprintf("Expected Auth_OpenID_AlreadySigned " . @@ -697,6 +702,7 @@ class Tests_Auth_OpenID_CheckID extends PHPUnit_TestCase { 'http://bar.unittest/999', 'http://bar.unittest/', false); + $this->request->namespace = Auth_OpenID_OPENID1_NS; } function test_trustRootInvalid() @@ -735,13 +741,11 @@ class Tests_Auth_OpenID_CheckID extends PHPUnit_TestCase { } $this->assertEquals($answer->request, $this->request); - $this->assertEquals($answer->fields, array( + $this->assertEquals($answer->fields->getArgs(Auth_OpenID_OPENID1_NS), + array( 'mode' => 'id_res', 'identity' => $this->request->identity, 'return_to' => $this->request->return_to)); - - $this->assertEquals($answer->signed, - array("mode", "identity", "return_to")); } function test_answerAllowNoTrustRoot() @@ -749,37 +753,34 @@ class Tests_Auth_OpenID_CheckID extends PHPUnit_TestCase { $this->request->trust_root = null; $answer = $this->request->answer(true); $this->assertEquals($answer->request, $this->request); - $this->assertEquals($answer->fields, array( + $this->assertEquals($answer->fields->getArgs(Auth_OpenID_OPENID1_NS), + array( 'mode' => 'id_res', 'identity' => $this->request->identity, 'return_to' => $this->request->return_to)); - - $this->assertEquals($answer->signed, - array("mode", "identity", "return_to")); } function test_answerImmediateDeny() { $this->request->mode = 'checkid_immediate'; + $this->request->namespace = Auth_OpenID_OPENID1_NS; $this->request->immediate = true; $server_url = "http://setup-url.unittest/"; $answer = $this->request->answer(false, $server_url); $this->assertEquals($answer->request, $this->request); - $this->assertEquals(count($answer->fields), 2); - $this->assertEquals(Auth_OpenID::arrayGet($answer->fields, 'mode'), + $this->assertEquals(count($answer->fields->toPostArgs()), 2); + $this->assertEquals($answer->fields->getArg(Auth_OpenID_OPENID_NS, 'mode'), 'id_res'); - $this->assertTrue(strpos(Auth_OpenID::arrayGet($answer->fields, - 'user_setup_url'), + $this->assertTrue(strpos($answer->fields->getArg(Auth_OpenID_OPENID_NS, + 'user_setup_url'), $server_url) == 0); - - $this->assertEquals($answer->signed, array()); } function test_answerSetupDeny() { $answer = $this->request->answer(false); - $this->assertEquals($answer->fields, array('mode' => 'cancel')); - $this->assertEquals($answer->signed, array()); + $this->assertEquals($answer->fields->getArgs(Auth_OpenID_OPENID1_NS), + array('mode' => 'cancel')); } function test_getCancelURL() @@ -801,92 +802,6 @@ class Tests_Auth_OpenID_CheckID extends PHPUnit_TestCase { } } -class Tests_Auth_OpenID_CheckIDExtension extends PHPUnit_TestCase { - - function setUp() - { - $this->request = new Auth_OpenID_CheckIDRequest( - 'http://bambam.unittest/', - 'http://bar.unittest/', - 'http://bar.unittest/999', - false); - - $this->response = new Auth_OpenID_CheckIDResponse($this->request); - $this->response->fields['blue'] = 'star'; - } - - function test_addField() - { - $namespace = 'mj12'; - $this->response->addField($namespace, 'bright', 'potato'); - $this->assertEquals($this->response->fields, - array('blue' => 'star', - 'mode' => 'id_res', - 'mj12.bright' => 'potato')); - $this->assertEquals($this->response->signed, - array('mode', 'identity', 'return_to', - 'mj12.bright')); - } - - function test_addFieldUnsigned() - { - $namespace = 'mj12'; - $this->response->addField($namespace, 'dull', 'lemon', false); - $this->assertEquals($this->response->fields, - array('blue' => 'star', - 'mode' => 'id_res', - 'mj12.dull' => 'lemon')); - $this->assertEquals($this->response->signed, - array('mode', 'identity', 'return_to')); - } - - function test_addFields() - { - $namespace = 'mi5'; - $this->response->addFields($namespace, array('tangy' => 'suspenders', - 'bravo' => 'inclusion')); - $this->assertEquals($this->response->fields, - array('blue' => 'star', - 'mode' => 'id_res', - 'mi5.tangy' => 'suspenders', - 'mi5.bravo' => 'inclusion')); - $this->assertEquals($this->response->signed, - array('mode', 'identity', 'return_to', - 'mi5.tangy', 'mi5.bravo')); - } - - function test_addFieldsUnsigned() - { - $namespace = 'mi5'; - $this->response->addFields($namespace, array('strange' => 'conditioner', - 'elemental' => 'blender'), - false); - $this->assertEquals($this->response->fields, - array('blue' => 'star', - 'mode' => 'id_res', - 'mi5.strange' => 'conditioner', - 'mi5.elemental' => 'blender')); - $this->assertEquals($this->response->signed, - array('mode', 'identity', 'return_to')); - } - - function test_update() - { - $eresponse = new Auth_OpenID_ServerResponse(null); - $eresponse->fields = array('shape' => 'heart', - 'content' => 'strings,wire'); - $eresponse->signed = array('content'); - $this->response->update('box', $eresponse); - $this->assertEquals($this->response->fields, - array('blue' => 'star', - 'mode' => 'id_res', - 'box.shape' => 'heart', - 'box.content' => 'strings,wire')); - $this->assertEquals($this->response->signed, - array('mode', 'identity', 'return_to', 'content')); - } -} - class _MockSignatory { var $isValid = true; @@ -895,13 +810,9 @@ class _MockSignatory { $this->assocs = array($assoc); } - function verify($assoc_handle, $sig, $signed_pairs) + function verify($assoc_handle, $message) { - if (!$sig) { - return false; - } - - if (!is_array($signed_pairs)) { + if (!$message->hasKey(Auth_OpenID_OPENID_NS, 'sig')) { return false; } @@ -942,40 +853,50 @@ class Tests_Auth_OpenID_CheckAuth extends PHPUnit_TestCase { function setUp() { $this->assoc_handle = 'mooooooooo'; + $this->message = Auth_OpenID_Message::fromPostArgs( + array('openid.sig' => 'signarture', + 'one' => 'alpha', + 'two' => 'beta')); + $this->request = new Auth_OpenID_CheckAuthRequest( - $this->assoc_handle, 'signarture', - array(array('one', 'alpha'), - array('two', 'beta'))); + $this->assoc_handle, $this->message); $this->signatory = new _MockSignatory(array(true, $this->assoc_handle)); } function test_valid() { + $this->request->namespace = Auth_OpenID_OPENID1_NS; $r = $this->request->answer($this->signatory); - $this->assertEquals($r->fields, array('is_valid' => 'true')); + $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS), + array('is_valid' => 'true')); $this->assertEquals($r->request, $this->request); } function test_invalid() { + $this->request->namespace = Auth_OpenID_OPENID1_NS; $this->signatory->isValid = false; $r = $this->request->answer($this->signatory); - $this->assertEquals($r->fields, array('is_valid' => 'false')); + $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS), + array('is_valid' => 'false')); } function test_replay() { + $this->request->namespace = Auth_OpenID_OPENID1_NS; $r = $this->request->answer($this->signatory); $r = $this->request->answer($this->signatory); - $this->assertEquals($r->fields, array('is_valid' => 'false')); + $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS), + array('is_valid' => 'false')); } function test_invalidatehandle() { + $this->request->namespace = Auth_OpenID_OPENID1_NS; $this->request->invalidate_handle = "bogusHandle"; $r = $this->request->answer($this->signatory); - $this->assertEquals($r->fields, + $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS), array('is_valid' => 'true', 'invalidate_handle' => "bogusHandle")); $this->assertEquals($r->request, $this->request); @@ -983,11 +904,13 @@ class Tests_Auth_OpenID_CheckAuth extends PHPUnit_TestCase { function test_invalidatehandleNo() { + $this->request->namespace = Auth_OpenID_OPENID1_NS; $assoc_handle = 'goodhandle'; $this->signatory->assocs[] = array(false, 'goodhandle'); $this->request->invalidate_handle = $assoc_handle; $r = $this->request->answer($this->signatory); - $this->assertEquals($r->fields, array('is_valid' => 'true')); + $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS), + array('is_valid' => 'true')); } } @@ -998,7 +921,8 @@ class Tests_Auth_OpenID_Associate extends PHPUnit_TestCase { function setUp() { - $this->request = Auth_OpenID_AssociateRequest::fromQuery(array()); + $message = new Auth_OpenID_Message(); + $this->request = Auth_OpenID_AssociateRequest::fromMessage($message); $this->store = new Tests_Auth_OpenID_MemStore(); $this->signatory = new Auth_OpenID_Signatory($this->store); $this->assoc = $this->signatory->createAssociation(false); @@ -1019,32 +943,32 @@ class Tests_Auth_OpenID_Associate extends PHPUnit_TestCase { $response = $this->request->answer($this->assoc); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "assoc_type"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_type"), "HMAC-SHA1"); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "assoc_handle"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_handle"), $this->assoc->handle); $this->assertFalse( - Auth_OpenID::arrayGet($response->fields, "mac_key")); + $response->fields->getArg(Auth_OpenID_OPENID_NS, "mac_key")); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "session_type"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "session_type"), "DH-SHA1"); $this->assertTrue( - Auth_OpenID::arrayGet($response->fields, "enc_mac_key")); + $response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key")); $this->assertTrue( - Auth_OpenID::arrayGet($response->fields, + $response->fields->getArg(Auth_OpenID_OPENID_NS, "dh_server_public")); $enc_key = base64_decode( - Auth_OpenID::arrayGet($response->fields, "enc_mac_key")); + $response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key")); $spub = $ml->base64ToLong( - Auth_OpenID::arrayGet($response->fields, + $response->fields->getArg(Auth_OpenID_OPENID_NS, "dh_server_public")); $secret = $dh->xorSecret($spub, $enc_key); @@ -1058,28 +982,28 @@ class Tests_Auth_OpenID_Associate extends PHPUnit_TestCase { $response = $this->request->answer($this->assoc); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "assoc_type"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_type"), "HMAC-SHA1"); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "assoc_handle"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_handle"), $this->assoc->handle); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "expires_in"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "expires_in"), sprintf("%d", $this->signatory->SECRET_LIFETIME)); $this->assertEquals( - Auth_OpenID::arrayGet($response->fields, "mac_key"), + $response->fields->getArg(Auth_OpenID_OPENID_NS, "mac_key"), base64_encode($this->assoc->secret)); - $this->assertFalse(Auth_OpenID::arrayGet($response->fields, + $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS, "session_type")); - $this->assertFalse(Auth_OpenID::arrayGet($response->fields, + $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key")); - $this->assertFalse(Auth_OpenID::arrayGet($response->fields, + $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS, "dh_server_public")); } } @@ -1106,10 +1030,11 @@ class Tests_Auth_OpenID_ServerTest extends PHPUnit_TestCase { function test_associate() { if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) { - $request = Auth_OpenID_AssociateRequest::fromQuery(array()); + $message = new Auth_OpenID_Message(); + $request = Auth_OpenID_AssociateRequest::fromMessage($message); $response = $this->server->openid_associate($request); - $this->assertTrue(array_key_exists('assoc_handle', - $response->fields)); + $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, + 'assoc_handle')); } } @@ -1119,8 +1044,7 @@ class Tests_Auth_OpenID_ServerTest extends PHPUnit_TestCase { '0x3999', array()); $response = $this->server->openid_check_authentication($request); - $this->assertTrue(array_key_exists('is_valid', - $response->fields)); + $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'is_valid')); } } @@ -1136,53 +1060,57 @@ class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase { function test_sign() { $request = new Auth_OpenID_ServerRequest(); + $request->namespace = Auth_OpenID_OPENID1_NS; + $assoc_handle = '{assoc}{lookatme}'; $assoc = Auth_OpenID_Association::fromExpiresIn(60, $assoc_handle, 'sekrit', 'HMAC-SHA1'); $this->store->storeAssociation($this->normal_key, $assoc); $request->assoc_handle = $assoc_handle; - $response = new Auth_OpenID_CheckIDResponse($request); - $response->fields = array( + $request->namespace = Auth_OpenID_OPENID1_NS; + + $response = new Auth_OpenID_ServerResponse($request); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array( 'foo' => 'amsigned', 'bar' => 'notsigned', - 'azu' => 'alsosigned'); + 'azu' => 'alsosigned')); - $response->signed = array('foo', 'azu'); $sresponse = $this->signatory->sign($response); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, - 'assoc_handle'), + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'assoc_handle'), $assoc_handle); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, 'signed'), - 'foo,azu'); + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, 'signed'), + 'assoc_handle,azu,bar,foo,signed'); - $this->assertTrue(Auth_OpenID::arrayGet($sresponse->fields, 'sig')); + $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')); } function test_signDumb() { $request = new Auth_OpenID_ServerRequest(); $request->assoc_handle = null; - $response = new Auth_OpenID_CheckIDResponse($request); - $response->fields = array( + $request->namespace = Auth_OpenID_OPENID1_NS; + + $response = new Auth_OpenID_ServerResponse($request); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array( 'foo' => 'amsigned', 'bar' => 'notsigned', - 'azu' => 'alsosigned'); + 'azu' => 'alsosigned')); - $response->signed = array('foo', 'azu'); $sresponse = $this->signatory->sign($response); - $assoc_handle = Auth_OpenID::arrayGet($sresponse->fields, - 'assoc_handle'); + $assoc_handle = $sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'assoc_handle'); $this->assertTrue($assoc_handle); $assoc = $this->signatory->getAssociation($assoc_handle, true); $this->assertTrue($assoc); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, 'signed'), - 'foo,azu'); - $this->assertTrue(Auth_OpenID::arrayGet($sresponse->fields, 'sig')); + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, 'signed'), + 'assoc_handle,azu,bar,foo,signed'); + $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')); } function test_signExpired() @@ -1196,27 +1124,30 @@ class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase { $assoc_handle)); $request->assoc_handle = $assoc_handle; - $response = new Auth_OpenID_CheckIDResponse($request); - $response->fields = array( + $request->namespace = Auth_OpenID_OPENID1_NS; + + $response = new Auth_OpenID_ServerResponse($request); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array( 'foo' => 'amsigned', 'bar' => 'notsigned', - 'azu' => 'alsosigned'); + 'azu' => 'alsosigned')); - $response->signed = array('foo', 'azu'); $sresponse = $this->signatory->sign($response); - $new_assoc_handle = Auth_OpenID::arrayGet($sresponse->fields, - 'assoc_handle'); + $new_assoc_handle = $sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'assoc_handle'); $this->assertTrue($new_assoc_handle); $this->assertFalse($new_assoc_handle == $assoc_handle); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, - 'invalidate_handle'), + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'invalidate_handle'), $assoc_handle); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, 'signed'), - 'foo,azu'); - $this->assertTrue(Auth_OpenID::arrayGet($sresponse->fields, 'sig')); + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'signed'), + 'assoc_handle,azu,bar,foo,invalidate_handle,signed'); + $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS, + 'sig')); // make sure the expired association is gone $this->assertFalse($this->store->getAssociation($this->normal_key, @@ -1236,28 +1167,32 @@ class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase { $assoc_handle = '{bogus-assoc}{notvalid}'; $request->assoc_handle = $assoc_handle; - $response = new Auth_OpenID_CheckIDResponse($request); - $response->fields = array( + $request->namespace = Auth_OpenID_OPENID1_NS; + + $response = new Auth_OpenID_ServerResponse($request); + $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array( 'foo' => 'amsigned', 'bar' => 'notsigned', - 'azu' => 'alsosigned'); + 'azu' => 'alsosigned')); $response->signed = array('foo', 'azu'); $sresponse = $this->signatory->sign($response); - $new_assoc_handle = Auth_OpenID::arrayGet($sresponse->fields, - 'assoc_handle'); + $new_assoc_handle = $sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'assoc_handle'); $this->assertTrue($new_assoc_handle); $this->assertFalse($new_assoc_handle == $assoc_handle); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, - 'invalidate_handle'), + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'invalidate_handle'), $assoc_handle); - $this->assertEquals(Auth_OpenID::arrayGet($sresponse->fields, 'signed'), - 'foo,azu'); - $this->assertTrue(Auth_OpenID::arrayGet($sresponse->fields, 'sig')); + $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, + 'signed'), + 'assoc_handle,azu,bar,foo,invalidate_handle,signed'); + $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS, + 'sig')); // make sure the new key is a dumb mode association $this->assertTrue($this->store->getAssociation($this->dumb_key, @@ -1275,12 +1210,14 @@ class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase { $this->store->storeAssociation($this->dumb_key, $assoc); - $signed_pairs = array(array('foo', 'bar'), - array('apple', 'orange')); + $signed = Auth_OpenID_Message::fromPostArgs(array( + 'openid.foo' => 'bar', + 'openid.apple' => 'orange', + 'openid.assoc_handle' => $assoc_handle, + 'openid.signed' => 'apple,assoc_handle,foo,signed', + 'openid.sig' => 'uXoT1qm62/BB09Xbj98TQ8mlBco=')); - $sig = "Ylu0KcIR7PvNegB/K41KpnRgJl0="; - $verified = $this->signatory->verify($assoc_handle, $sig, - $signed_pairs); + $verified = $this->signatory->verify($assoc_handle, $signed); $this->assertTrue($verified); } @@ -1292,12 +1229,14 @@ class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase { $this->store->storeAssociation($this->dumb_key, $assoc); - $signed_pairs = array(array('foo', 'bar'), - array('apple', 'orange')); + $signed = Auth_OpenID_Message::fromPostArgs(array( + 'openid.foo' => 'bar', + 'openid.apple' => 'orange', + 'openid.assoc_handle' => $assoc_handle, + 'openid.signed' => 'apple,assoc_handle,foo,signed', + 'openid.sig' => str_rot13('uXoT1qm62/BB09Xbj98TQ8mlBco='))); - $sig = str_rot13("Ylu0KcIR7PvNegB/K41KpnRgJl0="); - $verified = $this->signatory->verify($assoc_handle, $sig, - $signed_pairs); + $verified = $this->signatory->verify($assoc_handle, $signed); $this->assertFalse($verified); } @@ -1305,12 +1244,12 @@ class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase { function test_verifyBadHandle() { $assoc_handle = '{vroom}{zoom}'; - $signed_pairs = array(array('foo', 'bar'), - array('apple', 'orange')); + $signed = Auth_OpenID_Message::fromPostArgs( + array('foo' => 'bar', + 'apple' => 'orange', + 'openid.sig' => "Ylu0KcIR7PvNegB/K41KpnRgJl0=")); - $sig = "Ylu0KcIR7PvNegB/K41KpnRgJl0="; - $verified = $this->signatory->verify($assoc_handle, $sig, - $signed_pairs); + $verified = $this->signatory->verify($assoc_handle, $signed); $this->assertFalse($verified); } |