123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- <?php
- /**
- * Simple registration request and response parsing and object
- * representation.
- *
- * This module contains objects representing simple registration
- * requests and responses that can be used with both OpenID relying
- * parties and OpenID providers.
- *
- * 1. The relying party creates a request object and adds it to the
- * {@link Auth_OpenID_AuthRequest} object before making the
- * checkid request to the OpenID provider:
- *
- * $sreg_req = Auth_OpenID_SRegRequest::build(array('email'));
- * $auth_request->addExtension($sreg_req);
- *
- * 2. The OpenID provider extracts the simple registration request
- * from the OpenID request using {@link
- * Auth_OpenID_SRegRequest::fromOpenIDRequest}, gets the user's
- * approval and data, creates an {@link Auth_OpenID_SRegResponse}
- * object and adds it to the id_res response:
- *
- * $sreg_req = Auth_OpenID_SRegRequest::fromOpenIDRequest(
- * $checkid_request);
- * // [ get the user's approval and data, informing the user that
- * // the fields in sreg_response were requested ]
- * $sreg_resp = Auth_OpenID_SRegResponse::extractResponse(
- * $sreg_req, $user_data);
- * $sreg_resp->toMessage($openid_response->fields);
- *
- * 3. The relying party uses {@link
- * Auth_OpenID_SRegResponse::fromSuccessResponse} to extract the data
- * from the OpenID response:
- *
- * $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse(
- * $success_response);
- *
- * @package OpenID
- */
- /**
- * Import message and extension internals.
- */
- require_once 'Auth/OpenID/Message.php';
- require_once 'Auth/OpenID/Extension.php';
- // The data fields that are listed in the sreg spec
- global $Auth_OpenID_sreg_data_fields;
- $Auth_OpenID_sreg_data_fields = array(
- 'fullname' => 'Full Name',
- 'nickname' => 'Nickname',
- 'dob' => 'Date of Birth',
- 'email' => 'E-mail Address',
- 'gender' => 'Gender',
- 'postcode' => 'Postal Code',
- 'country' => 'Country',
- 'language' => 'Language',
- 'timezone' => 'Time Zone');
- /**
- * Check to see that the given value is a valid simple registration
- * data field name. Return true if so, false if not.
- */
- function Auth_OpenID_checkFieldName($field_name)
- {
- global $Auth_OpenID_sreg_data_fields;
- if (!in_array($field_name, array_keys($Auth_OpenID_sreg_data_fields))) {
- return false;
- }
- return true;
- }
- // URI used in the wild for Yadis documents advertising simple
- // registration support
- define('Auth_OpenID_SREG_NS_URI_1_0', 'http://openid.net/sreg/1.0');
- // URI in the draft specification for simple registration 1.1
- // <http://openid.net/specs/openid-simple-registration-extension-1_1-01.html>
- define('Auth_OpenID_SREG_NS_URI_1_1', 'http://openid.net/extensions/sreg/1.1');
- // This attribute will always hold the preferred URI to use when
- // adding sreg support to an XRDS file or in an OpenID namespace
- // declaration.
- define('Auth_OpenID_SREG_NS_URI', Auth_OpenID_SREG_NS_URI_1_1);
- Auth_OpenID_registerNamespaceAlias(Auth_OpenID_SREG_NS_URI_1_1, 'sreg');
- /**
- * Does the given endpoint advertise support for simple
- * registration?
- *
- * $endpoint: The endpoint object as returned by OpenID discovery.
- * returns whether an sreg type was advertised by the endpoint
- */
- function Auth_OpenID_supportsSReg($endpoint)
- {
- return ($endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_1) ||
- $endpoint->usesExtension(Auth_OpenID_SREG_NS_URI_1_0));
- }
- /**
- * A base class for classes dealing with Simple Registration protocol
- * messages.
- *
- * @package OpenID
- */
- class Auth_OpenID_SRegBase extends Auth_OpenID_Extension {
- /**
- * Extract the simple registration namespace URI from the given
- * OpenID message. Handles OpenID 1 and 2, as well as both sreg
- * namespace URIs found in the wild, as well as missing namespace
- * definitions (for OpenID 1)
- *
- * $message: The OpenID message from which to parse simple
- * registration fields. This may be a request or response message.
- *
- * Returns the sreg namespace URI for the supplied message. The
- * message may be modified to define a simple registration
- * namespace.
- *
- * @access private
- */
- static function _getSRegNS($message)
- {
- $alias = null;
- $found_ns_uri = null;
- // See if there exists an alias for one of the two defined
- // simple registration types.
- foreach (array(Auth_OpenID_SREG_NS_URI_1_1,
- Auth_OpenID_SREG_NS_URI_1_0) as $sreg_ns_uri) {
- $alias = $message->namespaces->getAlias($sreg_ns_uri);
- if ($alias !== null) {
- $found_ns_uri = $sreg_ns_uri;
- break;
- }
- }
- if ($alias === null) {
- // There is no alias for either of the types, so try to
- // add one. We default to using the modern value (1.1)
- $found_ns_uri = Auth_OpenID_SREG_NS_URI_1_1;
- if ($message->namespaces->addAlias(Auth_OpenID_SREG_NS_URI_1_1,
- 'sreg') === null) {
- // An alias for the string 'sreg' already exists, but
- // it's defined for something other than simple
- // registration
- return null;
- }
- }
- return $found_ns_uri;
- }
- }
- /**
- * An object to hold the state of a simple registration request.
- *
- * required: A list of the required fields in this simple registration
- * request
- *
- * optional: A list of the optional fields in this simple registration
- * request
- *
- * @package OpenID
- */
- class Auth_OpenID_SRegRequest extends Auth_OpenID_SRegBase {
- var $ns_alias = 'sreg';
- /**
- * Initialize an empty simple registration request.
- */
- static function build($required=null, $optional=null,
- $policy_url=null,
- $sreg_ns_uri=Auth_OpenID_SREG_NS_URI,
- $cls='Auth_OpenID_SRegRequest')
- {
- $obj = new $cls();
- $obj->required = array();
- $obj->optional = array();
- $obj->policy_url = $policy_url;
- $obj->ns_uri = $sreg_ns_uri;
- if ($required) {
- if (!$obj->requestFields($required, true, true)) {
- return null;
- }
- }
- if ($optional) {
- if (!$obj->requestFields($optional, false, true)) {
- return null;
- }
- }
- return $obj;
- }
- /**
- * Create a simple registration request that contains the fields
- * that were requested in the OpenID request with the given
- * arguments
- *
- * $request: The OpenID authentication request from which to
- * extract an sreg request.
- *
- * $cls: name of class to use when creating sreg request object.
- * Used for testing.
- *
- * Returns the newly created simple registration request
- */
- static function fromOpenIDRequest($request, $cls='Auth_OpenID_SRegRequest')
- {
- $obj = call_user_func_array(array($cls, 'build'),
- array(null, null, null, Auth_OpenID_SREG_NS_URI, $cls));
- // Since we're going to mess with namespace URI mapping, don't
- // mutate the object that was passed in.
- $m = $request->message;
- $obj->ns_uri = $obj->_getSRegNS($m);
- $args = $m->getArgs($obj->ns_uri);
- if ($args === null || Auth_OpenID::isFailure($args)) {
- return null;
- }
- $obj->parseExtensionArgs($args);
- return $obj;
- }
- /**
- * Parse the unqualified simple registration request parameters
- * and add them to this object.
- *
- * This method is essentially the inverse of
- * getExtensionArgs. This method restores the serialized simple
- * registration request fields.
- *
- * If you are extracting arguments from a standard OpenID
- * checkid_* request, you probably want to use fromOpenIDRequest,
- * which will extract the sreg namespace and arguments from the
- * OpenID request. This method is intended for cases where the
- * OpenID server needs more control over how the arguments are
- * parsed than that method provides.
- *
- * $args == $message->getArgs($ns_uri);
- * $request->parseExtensionArgs($args);
- *
- * $args: The unqualified simple registration arguments
- *
- * strict: Whether requests with fields that are not defined in
- * the simple registration specification should be tolerated (and
- * ignored)
- */
- function parseExtensionArgs($args, $strict=false)
- {
- foreach (array('required', 'optional') as $list_name) {
- $required = ($list_name == 'required');
- $items = Auth_OpenID::arrayGet($args, $list_name);
- if ($items) {
- foreach (explode(',', $items) as $field_name) {
- if (!$this->requestField($field_name, $required, $strict)) {
- if ($strict) {
- return false;
- }
- }
- }
- }
- }
- $this->policy_url = Auth_OpenID::arrayGet($args, 'policy_url');
- return true;
- }
- /**
- * A list of all of the simple registration fields that were
- * requested, whether they were required or optional.
- */
- function allRequestedFields()
- {
- return array_merge($this->required, $this->optional);
- }
- /**
- * Have any simple registration fields been requested?
- */
- function wereFieldsRequested()
- {
- return count($this->allRequestedFields());
- }
- /**
- * Was this field in the request?
- */
- function contains($field_name)
- {
- return (in_array($field_name, $this->required) ||
- in_array($field_name, $this->optional));
- }
- /**
- * Request the specified field from the OpenID user
- *
- * $field_name: the unqualified simple registration field name
- *
- * required: whether the given field should be presented to the
- * user as being a required to successfully complete the request
- *
- * strict: whether to raise an exception when a field is added to
- * a request more than once
- */
- function requestField($field_name,
- $required=false, $strict=false)
- {
- if (!Auth_OpenID_checkFieldName($field_name)) {
- return false;
- }
- if ($strict) {
- if ($this->contains($field_name)) {
- return false;
- }
- } else {
- if (in_array($field_name, $this->required)) {
- return true;
- }
- if (in_array($field_name, $this->optional)) {
- if ($required) {
- unset($this->optional[array_search($field_name,
- $this->optional)]);
- } else {
- return true;
- }
- }
- }
- if ($required) {
- $this->required[] = $field_name;
- } else {
- $this->optional[] = $field_name;
- }
- return true;
- }
- /**
- * Add the given list of fields to the request
- *
- * field_names: The simple registration data fields to request
- *
- * required: Whether these values should be presented to the user
- * as required
- *
- * strict: whether to raise an exception when a field is added to
- * a request more than once
- */
- function requestFields($field_names, $required=false, $strict=false)
- {
- if (!is_array($field_names)) {
- return false;
- }
- foreach ($field_names as $field_name) {
- if (!$this->requestField($field_name, $required, $strict=$strict)) {
- return false;
- }
- }
- return true;
- }
- /**
- * Get a dictionary of unqualified simple registration arguments
- * representing this request.
- *
- * This method is essentially the inverse of
- * C{L{parseExtensionArgs}}. This method serializes the simple
- * registration request fields.
- */
- function getExtensionArgs()
- {
- $args = array();
- if ($this->required) {
- $args['required'] = implode(',', $this->required);
- }
- if ($this->optional) {
- $args['optional'] = implode(',', $this->optional);
- }
- if ($this->policy_url) {
- $args['policy_url'] = $this->policy_url;
- }
- return $args;
- }
- }
- /**
- * Represents the data returned in a simple registration response
- * inside of an OpenID C{id_res} response. This object will be created
- * by the OpenID server, added to the C{id_res} response object, and
- * then extracted from the C{id_res} message by the Consumer.
- *
- * @package OpenID
- */
- class Auth_OpenID_SRegResponse extends Auth_OpenID_SRegBase {
- var $ns_alias = 'sreg';
- function Auth_OpenID_SRegResponse($data=null,
- $sreg_ns_uri=Auth_OpenID_SREG_NS_URI)
- {
- if ($data === null) {
- $this->data = array();
- } else {
- $this->data = $data;
- }
- $this->ns_uri = $sreg_ns_uri;
- }
- /**
- * Take a C{L{SRegRequest}} and a dictionary of simple
- * registration values and create a C{L{SRegResponse}} object
- * containing that data.
- *
- * request: The simple registration request object
- *
- * data: The simple registration data for this response, as a
- * dictionary from unqualified simple registration field name to
- * string (unicode) value. For instance, the nickname should be
- * stored under the key 'nickname'.
- */
- static function extractResponse($request, $data)
- {
- $obj = new Auth_OpenID_SRegResponse();
- $obj->ns_uri = $request->ns_uri;
- foreach ($request->allRequestedFields() as $field) {
- $value = Auth_OpenID::arrayGet($data, $field);
- if ($value !== null) {
- $obj->data[$field] = $value;
- }
- }
- return $obj;
- }
- /**
- * Create a C{L{SRegResponse}} object from a successful OpenID
- * library response
- * (C{L{openid.consumer.consumer.SuccessResponse}}) response
- * message
- *
- * success_response: A SuccessResponse from consumer.complete()
- *
- * signed_only: Whether to process only data that was
- * signed in the id_res message from the server.
- *
- * Returns a simple registration response containing the data that
- * was supplied with the C{id_res} response.
- */
- static function fromSuccessResponse($success_response, $signed_only=true)
- {
- global $Auth_OpenID_sreg_data_fields;
- $obj = new Auth_OpenID_SRegResponse();
- $obj->ns_uri = $obj->_getSRegNS($success_response->message);
- if ($signed_only) {
- $args = $success_response->getSignedNS($obj->ns_uri);
- } else {
- $args = $success_response->message->getArgs($obj->ns_uri);
- }
- if ($args === null || Auth_OpenID::isFailure($args)) {
- return null;
- }
- foreach ($Auth_OpenID_sreg_data_fields as $field_name => $desc) {
- if (in_array($field_name, array_keys($args))) {
- $obj->data[$field_name] = $args[$field_name];
- }
- }
- return $obj;
- }
- function getExtensionArgs()
- {
- return $this->data;
- }
- // Read-only dictionary interface
- function get($field_name, $default=null)
- {
- if (!Auth_OpenID_checkFieldName($field_name)) {
- return null;
- }
- return Auth_OpenID::arrayGet($this->data, $field_name, $default);
- }
- function contents()
- {
- return $this->data;
- }
- }
|