function fromMessage(&$message, $server) { $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); $immediate = null; if ($mode == "checkid_immediate") { $immediate = true; $mode = "checkid_immediate"; } else { $immediate = false; $mode = "checkid_setup"; } $return_to = $message->getArg(Auth_OpenID_OPENID_NS, 'return_to'); if (($message->isOpenID1()) && (!$return_to)) { $fmt = "Missing required field 'return_to' from checkid request"; return new Auth_OpenID_ServerError($message, $fmt); } $identity = $message->getArg(Auth_OpenID_OPENID_NS, 'identity'); $claimed_id = $message->getArg(Auth_OpenID_OPENID_NS, 'claimed_id'); if ($message->isOpenID1()) { if ($identity === null) { $s = "OpenID 1 message did not contain openid.identity"; return new Auth_OpenID_ServerError($message, $s); } } else { if ($identity && !$claimed_id) { $s = "OpenID 2.0 message contained openid.identity but not " . "claimed_id"; return new Auth_OpenID_ServerError($message, $s); } else if ($claimed_id && !$identity) { $s = "OpenID 2.0 message contained openid.claimed_id " . "but not identity"; return new Auth_OpenID_ServerError($message, $s); } } // There's a case for making self.trust_root be a TrustRoot // here. But if TrustRoot isn't currently part of the // "public" API, I'm not sure it's worth doing. if ($message->isOpenID1()) { $trust_root_param = 'trust_root'; } else { $trust_root_param = 'realm'; } $trust_root = $message->getArg(Auth_OpenID_OPENID_NS, $trust_root_param); if (! $trust_root) { $trust_root = $return_to; } if (! $message->isOpenID1() && ($return_to === null) && ($trust_root === null)) { return new Auth_OpenID_ServerError($message, "openid.realm required when openid.return_to absent"); } $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle'); $obj = Auth_OpenID_CheckIDRequest::make($message, $identity, $return_to, $trust_root, $immediate, $assoc_handle, $server); if (is_a($obj, 'Auth_OpenID_ServerError')) { return $obj; } $obj->claimed_id = $claimed_id; return $obj; }
/** * Respond to this request. Return either an * {@link Auth_OpenID_ServerResponse} or * {@link Auth_OpenID_ServerError}. * * @param bool $allow Allow this user to claim this identity, and * allow the consumer to have this information? * * @param string $server_url DEPRECATED. Passing $op_endpoint to * the {@link Auth_OpenID_Server} constructor makes this optional. * * When an OpenID 1.x immediate mode request does not succeed, it * gets back a URL where the request may be carried out in a * not-so-immediate fashion. Pass my URL in here (the fully * qualified address of this server's endpoint, i.e. * http://example.com/server), and I will use it as a base for the * URL for a new request. * * Optional for requests where {@link $immediate} is false or * $allow is true. * * @param string $identity The OP-local identifier to answer with. * Only for use when the relying party requested identifier * selection. * * @param string $claimed_id The claimed identifier to answer * with, for use with identifier selection in the case where the * claimed identifier and the OP-local identifier differ, * i.e. when the claimed_id uses delegation. * * If $identity is provided but this is not, $claimed_id will * default to the value of $identity. When answering requests * that did not ask for identifier selection, the response * $claimed_id will default to that of the request. * * This parameter is new in OpenID 2.0. * * @return mixed */ function answer($allow, $server_url = null, $identity = null, $claimed_id = null) { if (!$this->return_to) { return new Auth_OpenID_NoReturnToError(); } if (!$server_url) { if (!$this->message->isOpenID1() && !$this->server->op_endpoint) { return new Auth_OpenID_ServerError(null, "server should be constructed with op_endpoint to " . "respond to OpenID 2.0 messages."); } $server_url = $this->server->op_endpoint; } if ($allow) { $mode = 'id_res'; } else { if ($this->message->isOpenID1()) { if ($this->immediate) { $mode = 'id_res'; } else { $mode = 'cancel'; } } else { if ($this->immediate) { $mode = 'setup_needed'; } else { $mode = 'cancel'; } } } if (!$this->trustRootValid()) { return new Auth_OpenID_UntrustedReturnURL(null, $this->return_to, $this->trust_root); } $response = new Auth_OpenID_ServerResponse($this); if ($claimed_id && $this->message->isOpenID1()) { return new Auth_OpenID_ServerError(null, "claimed_id is new in OpenID 2.0 and not " . "available for " . $this->namespace); } if ($identity && !$claimed_id) { $claimed_id = $identity; } if ($allow) { if ($this->identity == Auth_OpenID_IDENTIFIER_SELECT) { if (!$identity) { return new Auth_OpenID_ServerError(null, "This request uses IdP-driven identifier selection. " . "You must supply an identifier in the response."); } $response_identity = $identity; $response_claimed_id = $claimed_id; } else { if ($this->identity) { if ($identity && $this->identity != $identity) { $fmt = "Request was for %s, cannot reply with identity %s"; return new Auth_OpenID_ServerError(null, sprintf($fmt, $this->identity, $identity)); } $response_identity = $this->identity; $response_claimed_id = $this->claimed_id; } else { if ($identity) { return new Auth_OpenID_ServerError(null, "This request specified no identity and " . "you supplied " . $identity); } $response_identity = null; } } if ($this->message->isOpenID1() && $response_identity === null) { return new Auth_OpenID_ServerError(null, "Request was an OpenID 1 request, so response must " . "include an identifier."); } $response->fields->updateArgs(Auth_OpenID_OPENID_NS, array('mode' => $mode, 'return_to' => $this->return_to, 'response_nonce' => Auth_OpenID_mkNonce())); if (!$this->message->isOpenID1()) { $response->fields->setArg(Auth_OpenID_OPENID_NS, 'op_endpoint', $server_url); } if ($response_identity !== null) { $response->fields->setArg(Auth_OpenID_OPENID_NS, 'identity', $response_identity); if ($this->message->isOpenID2()) { $response->fields->setArg(Auth_OpenID_OPENID_NS, 'claimed_id', $response_claimed_id); } } } else { $response->fields->setArg(Auth_OpenID_OPENID_NS, 'mode', $mode); if ($this->immediate) { if ($this->message->isOpenID1() && !$server_url) { return new Auth_OpenID_ServerError(null, 'setup_url is required for $allow=false \\ in OpenID 1.x immediate mode.'); } $setup_request = new Auth_OpenID_CheckIDRequest($this->identity, $this->return_to, $this->trust_root, false, $this->assoc_handle, $this->server, $this->claimed_id); $setup_request->message = $this->message; $setup_url = $setup_request->encodeToURL($server_url); if ($setup_url === null) { return new Auth_OpenID_NoReturnToError(); } $response->fields->setArg(Auth_OpenID_OPENID_NS, 'user_setup_url', $setup_url); } } return $response; }
function test_encodeToURL() { $server_url = 'http://openid-server.unittest/'; $result = $this->request->encodeToURL($server_url); $this->assertFalse(is_a($result, 'Auth_OpenID_ServerError')); // How to check? How about a round-trip test. list($base, $result_args) = explode("?", $result, 2); $args = Auth_OpenID::getQuery($result_args); $message = Auth_OpenID_Message::fromPostArgs($args); $rebuilt_request = Auth_OpenID_CheckIDRequest::fromMessage($message, $this->server); // argh, lousy hack $this->assertTrue($rebuilt_request->equals($this->request)); }
function fromQuery($query) { global $_Auth_OpenID_OpenID_Prefix; $mode = $query[$_Auth_OpenID_OpenID_Prefix . 'mode']; $immediate = null; if ($mode == "checkid_immediate") { $immediate = true; $mode = "checkid_immediate"; } else { $immediate = false; $mode = "checkid_setup"; } $required = array('identity', 'return_to'); $optional = array('trust_root', 'assoc_handle'); $values = array(); foreach ($required as $field) { 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("Missing required field %s from request", $field)); } $values[$field] = $value; } foreach ($optional as $field) { $value = null; if (array_key_exists($_Auth_OpenID_OpenID_Prefix . $field, $query)) { $value = $query[$_Auth_OpenID_OpenID_Prefix . $field]; } if ($value) { $values[$field] = $value; } } if (!Auth_OpenID_TrustRoot::_parse($values['return_to'])) { return new Auth_OpenID_MalformedReturnURL($query, $values['return_to']); } $obj = Auth_OpenID_CheckIDRequest::make($query, $values['identity'], $values['return_to'], Auth_OpenID::arrayGet($values, 'trust_root', null), $immediate); if (is_a($obj, 'Auth_OpenID_ServerError')) { return $obj; } if (Auth_OpenID::arrayGet($values, 'assoc_handle')) { $obj->assoc_handle = $values['assoc_handle']; } return $obj; }
function answer($allow, $server_url = null) { if ($allow || $this->immediate) { $mode = 'id_res'; } else { $mode = 'cancel'; } $response = new Auth_OpenID_CheckIDResponse($this, $mode); 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); } } else { $response->signed = array(); if ($this->immediate) { if (!$server_url) { return new Auth_OpenID_ServerError(null, 'setup_url is required for $allow=false \\ in immediate mode.'); } $setup_request = new Auth_OpenID_CheckIDRequest($this->identity, $this->return_to, $this->trust_root, false, $this->assoc_handle); $setup_url = $setup_request->encodeToURL($server_url); $response->fields['user_setup_url'] = $setup_url; } } return $response; }