Licence and jqmobile beta 3 upgrade
[busui.git] / lib / openid-php / Auth / OpenID / Consumer.php
blob:a/lib/openid-php/Auth/OpenID/Consumer.php -> blob:b/lib/openid-php/Auth/OpenID/Consumer.php
<
<?php <?php
   
/** /**
* This module documents the main interface with the OpenID consumer * This module documents the main interface with the OpenID consumer
* library. The only part of the library which has to be used and * library. The only part of the library which has to be used and
* isn't documented in full here is the store required to create an * isn't documented in full here is the store required to create an
* Auth_OpenID_Consumer instance. More on the abstract store type and * Auth_OpenID_Consumer instance. More on the abstract store type and
* concrete implementations of it that are provided in the * concrete implementations of it that are provided in the
* documentation for the Auth_OpenID_Consumer constructor. * documentation for the Auth_OpenID_Consumer constructor.
* *
* OVERVIEW * OVERVIEW
* *
* The OpenID identity verification process most commonly uses the * The OpenID identity verification process most commonly uses the
* following steps, as visible to the user of this library: * following steps, as visible to the user of this library:
* *
* 1. The user enters their OpenID into a field on the consumer's * 1. The user enters their OpenID into a field on the consumer's
* site, and hits a login button. * site, and hits a login button.
* 2. The consumer site discovers the user's OpenID server using the * 2. The consumer site discovers the user's OpenID server using the
* YADIS protocol. * YADIS protocol.
* 3. The consumer site sends the browser a redirect to the identity * 3. The consumer site sends the browser a redirect to the identity
* server. This is the authentication request as described in * server. This is the authentication request as described in
* the OpenID specification. * the OpenID specification.
* 4. The identity server's site sends the browser a redirect back * 4. The identity server's site sends the browser a redirect back
* to the consumer site. This redirect contains the server's * to the consumer site. This redirect contains the server's
* response to the authentication request. * response to the authentication request.
* *
* The most important part of the flow to note is the consumer's site * The most important part of the flow to note is the consumer's site
* must handle two separate HTTP requests in order to perform the full * must handle two separate HTTP requests in order to perform the full
* identity check. * identity check.
* *
* LIBRARY DESIGN * LIBRARY DESIGN
* *
* This consumer library is designed with that flow in mind. The goal * This consumer library is designed with that flow in mind. The goal
* is to make it as easy as possible to perform the above steps * is to make it as easy as possible to perform the above steps
* securely. * securely.
* *
* At a high level, there are two important parts in the consumer * At a high level, there are two important parts in the consumer
* library. The first important part is this module, which contains * library. The first important part is this module, which contains
* the interface to actually use this library. The second is the * the interface to actually use this library. The second is the
* Auth_OpenID_Interface class, which describes the interface to use * Auth_OpenID_Interface class, which describes the interface to use
* if you need to create a custom method for storing the state this * if you need to create a custom method for storing the state this
* library needs to maintain between requests. * library needs to maintain between requests.
* *
* In general, the second part is less important for users of the * In general, the second part is less important for users of the
* library to know about, as several implementations are provided * library to know about, as several implementations are provided
* which cover a wide variety of situations in which consumers may use * which cover a wide variety of situations in which consumers may use
* the library. * the library.
* *
* This module contains a class, Auth_OpenID_Consumer, with methods * This module contains a class, Auth_OpenID_Consumer, with methods
* corresponding to the actions necessary in each of steps 2, 3, and 4 * corresponding to the actions necessary in each of steps 2, 3, and 4
* described in the overview. Use of this library should be as easy * described in the overview. Use of this library should be as easy
* as creating an Auth_OpenID_Consumer instance and calling the * as creating an Auth_OpenID_Consumer instance and calling the
* methods appropriate for the action the site wants to take. * methods appropriate for the action the site wants to take.
* *
* STORES AND DUMB MODE * STORES AND DUMB MODE
* *
* OpenID is a protocol that works best when the consumer site is able * OpenID is a protocol that works best when the consumer site is able
* to store some state. This is the normal mode of operation for the * to store some state. This is the normal mode of operation for the
* protocol, and is sometimes referred to as smart mode. There is * protocol, and is sometimes referred to as smart mode. There is
* also a fallback mode, known as dumb mode, which is available when * also a fallback mode, known as dumb mode, which is available when
* the consumer site is not able to store state. This mode should be * the consumer site is not able to store state. This mode should be
* avoided when possible, as it leaves the implementation more * avoided when possible, as it leaves the implementation more
* vulnerable to replay attacks. * vulnerable to replay attacks.
* *
* The mode the library works in for normal operation is determined by * The mode the library works in for normal operation is determined by
* the store that it is given. The store is an abstraction that * the store that it is given. The store is an abstraction that
* handles the data that the consumer needs to manage between http * handles the data that the consumer needs to manage between http
* requests in order to operate efficiently and securely. * requests in order to operate efficiently and securely.
* *
* Several store implementation are provided, and the interface is * Several store implementation are provided, and the interface is
* fully documented so that custom stores can be used as well. See * fully documented so that custom stores can be used as well. See
* the documentation for the Auth_OpenID_Consumer class for more * the documentation for the Auth_OpenID_Consumer class for more
* information on the interface for stores. The implementations that * information on the interface for stores. The implementations that
* are provided allow the consumer site to store the necessary data in * are provided allow the consumer site to store the necessary data in
* several different ways, including several SQL databases and normal * several different ways, including several SQL databases and normal
* files on disk. * files on disk.
* *
* There is an additional concrete store provided that puts the system * There is an additional concrete store provided that puts the system
* in dumb mode. This is not recommended, as it removes the library's * in dumb mode. This is not recommended, as it removes the library's
* ability to stop replay attacks reliably. It still uses time-based * ability to stop replay attacks reliably. It still uses time-based
* checking to make replay attacks only possible within a small * checking to make replay attacks only possible within a small
* window, but they remain possible within that window. This store * window, but they remain possible within that window. This store
* should only be used if the consumer site has no way to retain data * should only be used if the consumer site has no way to retain data
* between requests at all. * between requests at all.
* *
* IMMEDIATE MODE * IMMEDIATE MODE
* *
* In the flow described above, the user may need to confirm to the * In the flow described above, the user may need to confirm to the
* lidentity server that it's ok to authorize his or her identity. * lidentity server that it's ok to authorize his or her identity.
* The server may draw pages asking for information from the user * The server may draw pages asking for information from the user
* before it redirects the browser back to the consumer's site. This * before it redirects the browser back to the consumer's site. This
* is generally transparent to the consumer site, so it is typically * is generally transparent to the consumer site, so it is typically
* ignored as an implementation detail. * ignored as an implementation detail.
* *
* There can be times, however, where the consumer site wants to get a * There can be times, however, where the consumer site wants to get a
* response immediately. When this is the case, the consumer can put * response immediately. When this is the case, the consumer can put
* the library in immediate mode. In immediate mode, there is an * the library in immediate mode. In immediate mode, there is an
* extra response possible from the server, which is essentially the * extra response possible from the server, which is essentially the
* server reporting that it doesn't have enough information to answer * server reporting that it doesn't have enough information to answer
* the question yet. * the question yet.
* *
* USING THIS LIBRARY * USING THIS LIBRARY
* *
* Integrating this library into an application is usually a * Integrating this library into an application is usually a
* relatively straightforward process. The process should basically * relatively straightforward process. The process should basically
* follow this plan: * follow this plan:
* *
* Add an OpenID login field somewhere on your site. When an OpenID * Add an OpenID login field somewhere on your site. When an OpenID
* is entered in that field and the form is submitted, it should make * is entered in that field and the form is submitted, it should make
* a request to the your site which includes that OpenID URL. * a request to the your site which includes that OpenID URL.
* *
* First, the application should instantiate the Auth_OpenID_Consumer * First, the application should instantiate the Auth_OpenID_Consumer
* class using the store of choice (Auth_OpenID_FileStore or one of * class using the store of choice (Auth_OpenID_FileStore or one of
* the SQL-based stores). If the application has a custom * the SQL-based stores). If the application has a custom
* session-management implementation, an object implementing the * session-management implementation, an object implementing the
* {@link Auth_Yadis_PHPSession} interface should be passed as the * {@link Auth_Yadis_PHPSession} interface should be passed as the
* second parameter. Otherwise, the default uses $_SESSION. * second parameter. Otherwise, the default uses $_SESSION.
* *
* Next, the application should call the Auth_OpenID_Consumer object's * Next, the application should call the Auth_OpenID_Consumer object's
* 'begin' method. This method takes the OpenID URL. The 'begin' * 'begin' method. This method takes the OpenID URL. The 'begin'
* method returns an Auth_OpenID_AuthRequest object. * method returns an Auth_OpenID_AuthRequest object.
* *
* Next, the application should call the 'redirectURL' method of the * Next, the application should call the 'redirectURL' method of the
* Auth_OpenID_AuthRequest object. The 'return_to' URL parameter is * Auth_OpenID_AuthRequest object. The 'return_to' URL parameter is
* the URL that the OpenID server will send the user back to after * the URL that the OpenID server will send the user back to after
* attempting to verify his or her identity. The 'trust_root' is the * attempting to verify his or her identity. The 'trust_root' is the
* URL (or URL pattern) that identifies your web site to the user when * URL (or URL pattern) that identifies your web site to the user when
* he or she is authorizing it. Send a redirect to the resulting URL * he or she is authorizing it. Send a redirect to the resulting URL
* to the user's browser. * to the user's browser.
* *
* That's the first half of the authentication process. The second * That's the first half of the authentication process. The second
* half of the process is done after the user's ID server sends the * half of the process is done after the user's ID server sends the
* user's browser a redirect back to your site to complete their * user's browser a redirect back to your site to complete their
* login. * login.
* *
* When that happens, the user will contact your site at the URL given * When that happens, the user will contact your site at the URL given
* as the 'return_to' URL to the Auth_OpenID_AuthRequest::redirectURL * as the 'return_to' URL to the Auth_OpenID_AuthRequest::redirectURL
* call made above. The request will have several query parameters * call made above. The request will have several query parameters
* added to the URL by the identity server as the information * added to the URL by the identity server as the information
* necessary to finish the request. * necessary to finish the request.
* *
* Lastly, instantiate an Auth_OpenID_Consumer instance as above and * Lastly, instantiate an Auth_OpenID_Consumer instance as above and
* call its 'complete' method, passing in all the received query * call its 'complete' method, passing in all the received query
* arguments. * arguments.
* *
* There are multiple possible return types possible from that * There are multiple possible return types possible from that
* method. These indicate the whether or not the login was successful, * method. These indicate the whether or not the login was successful,
* and include any additional information appropriate for their type. * and include any additional information appropriate for their type.
* *
* PHP versions 4 and 5 * PHP versions 4 and 5
* *
* LICENSE: See the COPYING file included in this distribution. * LICENSE: See the COPYING file included in this distribution.
* *
* @package OpenID * @package OpenID
* @author JanRain, Inc. <openid@janrain.com> * @author JanRain, Inc. <openid@janrain.com>
* @copyright 2005-2008 Janrain, Inc. * @copyright 2005-2008 Janrain, Inc.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
*/ */
   
/** /**
* Require utility classes and functions for the consumer. * Require utility classes and functions for the consumer.
*/ */
require_once "Auth/OpenID.php"; require_once "Auth/OpenID.php";
require_once "Auth/OpenID/Message.php"; require_once "Auth/OpenID/Message.php";
require_once "Auth/OpenID/HMAC.php"; require_once "Auth/OpenID/HMAC.php";
require_once "Auth/OpenID/Association.php"; require_once "Auth/OpenID/Association.php";
require_once "Auth/OpenID/CryptUtil.php"; require_once "Auth/OpenID/CryptUtil.php";
require_once "Auth/OpenID/DiffieHellman.php"; require_once "Auth/OpenID/DiffieHellman.php";
require_once "Auth/OpenID/KVForm.php"; require_once "Auth/OpenID/KVForm.php";
require_once "Auth/OpenID/Nonce.php"; require_once "Auth/OpenID/Nonce.php";
require_once "Auth/OpenID/Discover.php"; require_once "Auth/OpenID/Discover.php";
require_once "Auth/OpenID/URINorm.php"; require_once "Auth/OpenID/URINorm.php";
require_once "Auth/Yadis/Manager.php"; require_once "Auth/Yadis/Manager.php";
require_once "Auth/Yadis/XRI.php"; require_once "Auth/Yadis/XRI.php";
   
/** /**
* This is the status code returned when the complete method returns * This is the status code returned when the complete method returns
* successfully. * successfully.
*/ */
define('Auth_OpenID_SUCCESS', 'success'); define('Auth_OpenID_SUCCESS', 'success');
   
/** /**
* Status to indicate cancellation of OpenID authentication. * Status to indicate cancellation of OpenID authentication.
*/ */
define('Auth_OpenID_CANCEL', 'cancel'); define('Auth_OpenID_CANCEL', 'cancel');
   
/** /**
* This is the status code completeAuth returns when the value it * This is the status code completeAuth returns when the value it
* received indicated an invalid login. * received indicated an invalid login.
*/ */
define('Auth_OpenID_FAILURE', 'failure'); define('Auth_OpenID_FAILURE', 'failure');
   
/** /**
* This is the status code completeAuth returns when the * This is the status code completeAuth returns when the
* {@link Auth_OpenID_Consumer} instance is in immediate mode, and the * {@link Auth_OpenID_Consumer} instance is in immediate mode, and the
* identity server sends back a URL to send the user to to complete his * identity server sends back a URL to send the user to to complete his
* or her login. * or her login.
*/ */
define('Auth_OpenID_SETUP_NEEDED', 'setup needed'); define('Auth_OpenID_SETUP_NEEDED', 'setup needed');
   
/** /**
* This is the status code beginAuth returns when the page fetched * This is the status code beginAuth returns when the page fetched
* from the entered OpenID URL doesn't contain the necessary link tags * from the entered OpenID URL doesn't contain the necessary link tags
* to function as an identity page. * to function as an identity page.
*/ */
define('Auth_OpenID_PARSE_ERROR', 'parse error'); define('Auth_OpenID_PARSE_ERROR', 'parse error');
   
/** /**
* An OpenID consumer implementation that performs discovery and does * An OpenID consumer implementation that performs discovery and does
* session management. See the Consumer.php file documentation for * session management. See the Consumer.php file documentation for
* more information. * more information.
* *
* @package OpenID * @package OpenID
*/ */
class Auth_OpenID_Consumer { class Auth_OpenID_Consumer {
   
/** /**
* @access private * @access private
*/ */
var $discoverMethod = 'Auth_OpenID_discover'; var $discoverMethod = 'Auth_OpenID_discover';
   
/** /**
* @access private * @access private
*/ */
var $session_key_prefix = "_openid_consumer_"; var $session_key_prefix = "_openid_consumer_";
   
/** /**
* @access private * @access private
*/ */
var $_token_suffix = "last_token"; var $_token_suffix = "last_token";
   
/** /**
* Initialize a Consumer instance. * Initialize a Consumer instance.
* *
* You should create a new instance of the Consumer object with * You should create a new instance of the Consumer object with
* every HTTP request that handles OpenID transactions. * every HTTP request that handles OpenID transactions.
* *
* @param Auth_OpenID_OpenIDStore $store This must be an object * @param Auth_OpenID_OpenIDStore $store This must be an object
* that implements the interface in {@link * that implements the interface in {@link
* Auth_OpenID_OpenIDStore}. Several concrete implementations are * Auth_OpenID_OpenIDStore}. Several concrete implementations are
* provided, to cover most common use cases. For stores backed by * provided, to cover most common use cases. For stores backed by
* MySQL, PostgreSQL, or SQLite, see the {@link * MySQL, PostgreSQL, or SQLite, see the {@link
* Auth_OpenID_SQLStore} class and its sublcasses. For a * Auth_OpenID_SQLStore} class and its sublcasses. For a
* filesystem-backed store, see the {@link Auth_OpenID_FileStore} * filesystem-backed store, see the {@link Auth_OpenID_FileStore}
* module. As a last resort, if it isn't possible for the server * module. As a last resort, if it isn't possible for the server
* to store state at all, an instance of {@link * to store state at all, an instance of {@link
* Auth_OpenID_DumbStore} can be used. * Auth_OpenID_DumbStore} can be used.
* *
* @param mixed $session An object which implements the interface * @param mixed $session An object which implements the interface
* of the {@link Auth_Yadis_PHPSession} class. Particularly, this * of the {@link Auth_Yadis_PHPSession} class. Particularly, this
* object is expected to have these methods: get($key), set($key), * object is expected to have these methods: get($key), set($key),
* $value), and del($key). This defaults to a session object * $value), and del($key). This defaults to a session object
* which wraps PHP's native session machinery. You should only * which wraps PHP's native session machinery. You should only
* need to pass something here if you have your own sessioning * need to pass something here if you have your own sessioning
* implementation. * implementation.
* *
* @param str $consumer_cls The name of the class to instantiate * @param str $consumer_cls The name of the class to instantiate
* when creating the internal consumer object. This is used for * when creating the internal consumer object. This is used for
* testing. * testing.
*/ */
function Auth_OpenID_Consumer($store, $session = null, function Auth_OpenID_Consumer($store, $session = null,
$consumer_cls = null) $consumer_cls = null)
{ {
if ($session === null) { if ($session === null) {
$session = new Auth_Yadis_PHPSession(); $session = new Auth_Yadis_PHPSession();
} }
   
$this->session = $session; $this->session = $session;
   
if ($consumer_cls !== null) { if ($consumer_cls !== null) {
$this->consumer = new $consumer_cls($store); $this->consumer = new $consumer_cls($store);
} else { } else {
$this->consumer = new Auth_OpenID_GenericConsumer($store); $this->consumer = new Auth_OpenID_GenericConsumer($store);
} }
   
$this->_token_key = $this->session_key_prefix . $this->_token_suffix; $this->_token_key = $this->session_key_prefix . $this->_token_suffix;
} }
   
/** /**
* Used in testing to define the discovery mechanism. * Used in testing to define the discovery mechanism.
* *
* @access private * @access private
*/ */
function getDiscoveryObject($session, $openid_url, function getDiscoveryObject($session, $openid_url,
$session_key_prefix) $session_key_prefix)
{ {
return new Auth_Yadis_Discovery($session, $openid_url, return new Auth_Yadis_Discovery($session, $openid_url,
$session_key_prefix); $session_key_prefix);
} }
   
/** /**
* Start the OpenID authentication process. See steps 1-2 in the * Start the OpenID authentication process. See steps 1-2 in the
* overview at the top of this file. * overview at the top of this file.
* *
* @param string $user_url Identity URL given by the user. This * @param string $user_url Identity URL given by the user. This
* method performs a textual transformation of the URL to try and * method performs a textual transformation of the URL to try and
* make sure it is normalized. For example, a user_url of * make sure it is normalized. For example, a user_url of
* example.com will be normalized to http://example.com/ * example.com will be normalized to http://example.com/
* normalizing and resolving any redirects the server might issue. * normalizing and resolving any redirects the server might issue.
* *
* @param bool $anonymous True if the OpenID request is to be sent * @param bool $anonymous True if the OpenID request is to be sent
* to the server without any identifier information. Use this * to the server without any identifier information. Use this
* when you want to transport data but don't want to do OpenID * when you want to transport data but don't want to do OpenID
* authentication with identifiers. * authentication with identifiers.
* *
* @return Auth_OpenID_AuthRequest $auth_request An object * @return Auth_OpenID_AuthRequest $auth_request An object
* containing the discovered information will be returned, with a * containing the discovered information will be returned, with a
* method for building a redirect URL to the server, as described * method for building a redirect URL to the server, as described
* in step 3 of the overview. This object may also be used to add * in step 3 of the overview. This object may also be used to add
* extension arguments to the request, using its 'addExtensionArg' * extension arguments to the request, using its 'addExtensionArg'
* method. * method.
*/ */
function begin($user_url, $anonymous=false) function begin($user_url, $anonymous=false)
{ {
$openid_url = $user_url; $openid_url = $user_url;
   
$disco = $this->getDiscoveryObject($this->session, $disco = $this->getDiscoveryObject($this->session,
$openid_url, $openid_url,
$this->session_key_prefix); $this->session_key_prefix);
   
// Set the 'stale' attribute of the manager. If discovery // Set the 'stale' attribute of the manager. If discovery
// fails in a fatal way, the stale flag will cause the manager // fails in a fatal way, the stale flag will cause the manager
// to be cleaned up next time discovery is attempted. // to be cleaned up next time discovery is attempted.
   
$m = $disco->getManager(); $m = $disco->getManager();
$loader = new Auth_Yadis_ManagerLoader(); $loader = new Auth_Yadis_ManagerLoader();
   
if ($m) { if ($m) {
if ($m->stale) { if ($m->stale) {
$disco->destroyManager(); $disco->destroyManager();
} else { } else {
$m->stale = true; $m->stale = true;