X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=plugins%2FOpenID%2FOpenIDPlugin.php;h=d1a6786fa8c6d9790dd78aae2607699a7d77d716;hb=bf0df016e568c2079c0842490aa52a6ddb4e9ca2;hp=7d6a5dc000e7c0d100d54c53ffadf3a894afc9a4;hpb=d88b208edcb75ec864e09bb3ab29785b35064400;p=quix0rs-gnu-social.git diff --git a/plugins/OpenID/OpenIDPlugin.php b/plugins/OpenID/OpenIDPlugin.php index 7d6a5dc000..4e5a0bfe0c 100644 --- a/plugins/OpenID/OpenIDPlugin.php +++ b/plugins/OpenID/OpenIDPlugin.php @@ -20,7 +20,7 @@ * @category Plugin * @package StatusNet * @author Evan Prodromou - * @author Craig Andrews + * @author Craig Andrews * @copyright 2009-2010 StatusNet, Inc. * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -37,6 +37,8 @@ if (!defined('STATUSNET')) { * This class enables consumer support for OpenID, the distributed authentication * and identity system. * + * Depends on: WebFinger plugin for HostMeta-lookup (user@host format) + * * @category Plugin * @package StatusNet * @author Evan Prodromou @@ -46,7 +48,6 @@ if (!defined('STATUSNET')) { * @link http://status.net/ * @link http://openid.net/ */ - class OpenIDPlugin extends Plugin { // Plugin parameter: set true to disallow non-OpenID logins @@ -60,7 +61,6 @@ class OpenIDPlugin extends Plugin global $config; $config['site']['openidonly'] = (bool)$this->openidOnly; } - } /** @@ -68,12 +68,11 @@ class OpenIDPlugin extends Plugin * * Hook for RouterInitialized event. * - * @param Net_URL_Mapper $m URL mapper + * @param URLMapper $m URL mapper * * @return boolean hook return */ - - function onStartInitializeRouter($m) + public function onStartInitializeRouter(URLMapper $m) { $m->connect('main/openid', array('action' => 'openidlogin')); $m->connect('main/openidtrust', array('action' => 'openidtrust')); @@ -83,7 +82,7 @@ class OpenIDPlugin extends Plugin $m->connect('index.php?action=finishaddopenid', array('action' => 'finishaddopenid')); $m->connect('main/openidserver', array('action' => 'openidserver')); - $m->connect('admin/openid', array('action' => 'openidadminpanel')); + $m->connect('panel/openid', array('action' => 'openidadminpanel')); return true; } @@ -98,13 +97,17 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - function onStartConnectPath(&$path, &$defaults, &$rules, &$result) { if (common_config('site', 'openidonly')) { - static $block = array('main/login', - 'main/register', - 'main/recoverpassword', + // Note that we should not remove the login and register + // actions. Lots of auth-related things link to them, + // such as when visiting a private site without a session + // or revalidating a remembered login for admin work. + // + // We take those two over with redirects to ourselves + // over in onArgsInitialize(). + static $block = array('main/recoverpassword', 'settings/password'); if (in_array($path, $block)) { @@ -122,7 +125,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - function onArgsInitialize($args) { if (common_config('site', 'openidonly')) { @@ -130,12 +132,11 @@ class OpenIDPlugin extends Plugin $action = trim($args['action']); if (in_array($action, array('login', 'register'))) { common_redirect(common_local_url('openidlogin')); - exit(0); } else if ($action == 'passwordsettings') { common_redirect(common_local_url('openidsettings')); - exit(0); } else if ($action == 'recoverpassword') { - throw new ClientException('Unavailable action'); + // TRANS: Client exception thrown when an action is not available. + throw new ClientException(_m('Unavailable action.')); } } } @@ -153,8 +154,7 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - - function onEndPublicXRDS($action, &$xrdsOutputter) + function onEndPublicXRDS(Action $action, &$xrdsOutputter) { $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', 'xmlns:simple' => 'http://xrds-simple.net/core/1.0', @@ -174,38 +174,6 @@ class OpenIDPlugin extends Plugin $xrdsOutputter->elementEnd('XRD'); } - /** - * User XRDS output hook - * - * Puts the bits of code needed to discover OpenID endpoints. - * - * @param Action $action Action being executed - * @param XMLOutputter &$xrdsOutputter Output channel - * - * @return boolean hook return - */ - - function onEndUserXRDS($action, &$xrdsOutputter) - { - $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)', - 'xml:id' => 'openid', - 'xmlns:simple' => 'http://xrds-simple.net/core/1.0', - 'version' => '2.0')); - $xrdsOutputter->element('Type', null, 'xri://$xrds*simple'); - - //consumer - $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/return_to', - common_local_url('finishopenidlogin')); - - //provider - $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/signon', - common_local_url('openidserver'), - null, - null, - common_profile_url($action->user->nickname)); - $xrdsOutputter->elementEnd('XRD'); - } - /** * If we're in OpenID-only mode, hide all the main menu except OpenID login. * @@ -213,12 +181,11 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - function onStartPrimaryNav($action) { if (common_config('site', 'openidonly') && !common_logged_in()) { // TRANS: Tooltip for main menu option "Login" - $tooltip = _m('TOOLTIP', 'Login to the site'); + $tooltip = _m('TOOLTIP', 'Login to the site.'); $action->menuItem(common_local_url('openidlogin'), // TRANS: Main menu option when not logged in to log in _m('MENU', 'Login'), @@ -235,7 +202,7 @@ class OpenIDPlugin extends Plugin 'nav_help'); if (!common_config('site', 'private')) { // TRANS: Tooltip for main menu option "Search" - $tooltip = _m('TOOLTIP', 'Search for people or text'); + $tooltip = _m('TOOLTIP', 'Search for people or text.'); $action->menuItem(common_local_url('peoplesearch'), // TRANS: Main menu option when logged in or when the StatusNet instance is not private _m('MENU', 'Search'), $tooltip, false, 'nav_search'); @@ -251,12 +218,11 @@ class OpenIDPlugin extends Plugin * * If we're in openidOnly mode, we disable the menu for all other login. * - * @param Action &$action Action being executed + * @param Action $action Action being executed * * @return boolean hook return */ - - function onStartLoginGroupNav(&$action) + function onStartLoginGroupNav($action) { if (common_config('site', 'openidonly')) { $this->showOpenIDLoginTab($action); @@ -272,12 +238,11 @@ class OpenIDPlugin extends Plugin /** * Menu item for login * - * @param Action &$action Action being executed + * @param Action $action Action being executed * * @return boolean hook return */ - - function onEndLoginGroupNav(&$action) + function onEndLoginGroupNav($action) { $this->showOpenIDLoginTab($action); @@ -291,7 +256,6 @@ class OpenIDPlugin extends Plugin * * @return void */ - function showOpenIDLoginTab($action) { $action_name = $action->trimmed('action'); @@ -300,7 +264,7 @@ class OpenIDPlugin extends Plugin // TRANS: OpenID plugin menu item on site logon page. _m('MENU', 'OpenID'), // TRANS: OpenID plugin tooltip for logon menu item. - _m('Login or register with OpenID'), + _m('Login or register with OpenID.'), $action_name === 'openidlogin'); } @@ -314,7 +278,6 @@ class OpenIDPlugin extends Plugin * * @return void */ - function onStartAccountSettingsPasswordMenuItem($menu, &$unused) { if (common_config('site', 'openidonly')) { return false; @@ -325,12 +288,11 @@ class OpenIDPlugin extends Plugin /** * Menu item for OpenID settings * - * @param Action &$action Action being executed + * @param Action $action Action being executed * * @return boolean hook return */ - - function onEndAccountSettingsNav(&$action) + function onEndAccountSettingsNav($action) { $action_name = $action->trimmed('action'); @@ -338,7 +300,7 @@ class OpenIDPlugin extends Plugin // TRANS: OpenID plugin menu item on user settings page. _m('MENU', 'OpenID'), // TRANS: OpenID plugin tooltip for user settings menu item. - _m('Add or remove OpenIDs'), + _m('Add or remove OpenIDs.'), $action_name === 'openidsettings'); return true; @@ -353,36 +315,18 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - function onAutoload($cls) { switch ($cls) { - case 'OpenidloginAction': - case 'FinishopenidloginAction': - case 'FinishaddopenidAction': - case 'XrdsAction': - case 'PublicxrdsAction': - case 'OpenidsettingsAction': - case 'OpenidserverAction': - case 'OpenidtrustAction': - case 'OpenidadminpanelAction': - require_once dirname(__FILE__) . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; - return false; - case 'User_openid': - require_once dirname(__FILE__) . '/User_openid.php'; - return false; - case 'User_openid_trustroot': - require_once dirname(__FILE__) . '/User_openid_trustroot.php'; - return false; case 'Auth_OpenID_TeamsExtension': case 'Auth_OpenID_TeamsRequest': case 'Auth_OpenID_TeamsResponse': require_once dirname(__FILE__) . '/extlib/teams-extension.php'; return false; - default: - return true; } + + return parent::onAutoload($cls); } /** @@ -395,7 +339,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - function onSensitiveAction($action, &$ssl) { switch ($action) @@ -419,7 +362,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook return */ - function onLoginAction($action, &$login) { switch ($action) @@ -435,25 +377,29 @@ class OpenIDPlugin extends Plugin } /** - * We include a element linking to the userxrds page, for OpenID - * client-side authentication. + * We include a element linking to the webfinger resource page, + * for OpenID client-side authentication. * * @param Action $action Action being shown * * @return void */ - - function onEndShowHeadElements($action) + function onEndShowHeadElements(Action $action) { if ($action instanceof ShowstreamAction) { $action->element('link', array('rel' => 'openid2.provider', 'href' => common_local_url('openidserver'))); $action->element('link', array('rel' => 'openid2.local_id', - 'href' => $action->profile->profileurl)); + 'href' => $action->getTarget()->getUrl())); $action->element('link', array('rel' => 'openid.server', 'href' => common_local_url('openidserver'))); $action->element('link', array('rel' => 'openid.delegate', - 'href' => $action->profile->profileurl)); + 'href' => $action->getTarget()->getUrl())); + } + + if ($action instanceof SitestreamAction) { + $action->element('meta', array('http-equiv' => 'X-XRDS-Location', + 'content' => common_local_url('publicxrds'))); } return true; } @@ -466,12 +412,10 @@ class OpenIDPlugin extends Plugin * * @return boolean whether to continue */ - function onRedirectToLogin($action, $user) { - if (common_config('site', 'openid_only') || (!empty($user) && User_openid::hasOpenID($user->id))) { + if (common_config('site', 'openidonly') || (!empty($user) && User_openid::hasOpenID($user->id))) { common_redirect(common_local_url('openidlogin'), 303); - return false; } return true; } @@ -483,7 +427,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - function onEndShowPageNotice($action) { $name = $action->trimmed('action'); @@ -492,18 +435,24 @@ class OpenIDPlugin extends Plugin { case 'register': if (common_logged_in()) { - $instr = '(Have an [OpenID](http://openid.net/)? ' . - '[Add an OpenID to your account](%%action.openidsettings%%)!'; + // TRANS: Page notice for logged in users to try and get them to add an OpenID account to their StatusNet account. + // TRANS: This message contains Markdown links in the form (description)[link]. + $instr = _m('(Have an [OpenID](http://openid.net/)? ' . + '[Add an OpenID to your account](%%action.openidsettings%%)!'); } else { - $instr = '(Have an [OpenID](http://openid.net/)? ' . + // TRANS: Page notice for anonymous users to try and get them to register with an OpenID account. + // TRANS: This message contains Markdown links in the form (description)[link]. + $instr = _m('(Have an [OpenID](http://openid.net/)? ' . 'Try our [OpenID registration]'. - '(%%action.openidlogin%%)!)'; + '(%%action.openidlogin%%)!)'); } break; case 'login': - $instr = '(Have an [OpenID](http://openid.net/)? ' . + // TRANS: Page notice on the login page to try and get them to log on with an OpenID account. + // TRANS: This message contains Markdown links in the form (description)[link]. + $instr = _m('(Have an [OpenID](http://openid.net/)? ' . 'Try our [OpenID login]'. - '(%%action.openidlogin%%)!)'; + '(%%action.openidlogin%%)!)'); break; default: return true; @@ -522,7 +471,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - function onStartLoadDoc(&$title, &$output) { if ($title == 'openid') { @@ -544,15 +492,12 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - - function onEndLoadDoc($title, &$output) - { - if ($title == 'help') { - $menuitem = '* [OpenID](%%doc.openid%%) - what OpenID is and how to use it with this service'; - - $output .= common_markup_to_html($menuitem); - } - + function onEndDocsMenu(&$items) { + $items[] = array('doc', + array('title' => 'openid'), + _m('MENU', 'OpenID'), + _('Logging in with OpenID'), + 'nav_doc_openid'); return true; } @@ -563,28 +508,39 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - function onCheckSchema() { $schema = Schema::get(); - $schema->ensureTable('user_openid', - array(new ColumnDef('canonical', 'varchar', - '255', false, 'PRI'), - new ColumnDef('display', 'varchar', - '255', false, 'UNI'), - new ColumnDef('user_id', 'integer', - null, false, 'MUL'), - new ColumnDef('created', 'datetime', - null, false), - new ColumnDef('modified', 'timestamp'))); - $schema->ensureTable('user_openid_trustroot', - array(new ColumnDef('trustroot', 'varchar', - '255', false, 'PRI'), - new ColumnDef('user_id', 'integer', - null, false, 'PRI'), - new ColumnDef('created', 'datetime', - null, false), - new ColumnDef('modified', 'timestamp'))); + $schema->ensureTable('user_openid', User_openid::schemaDef()); + $schema->ensureTable('user_openid_trustroot', User_openid_trustroot::schemaDef()); + $schema->ensureTable('user_openid_prefs', User_openid_prefs::schemaDef()); + + /* These are used by JanRain OpenID library */ + + $schema->ensureTable('oid_associations', + array( + 'fields' => array( + 'server_url' => array('type' => 'blob', 'not null' => true), + 'handle' => array('type' => 'varchar', 'length' => 191, 'not null' => true, 'default' => ''), // character set latin1, + 'secret' => array('type' => 'blob'), + 'issued' => array('type' => 'int'), + 'lifetime' => array('type' => 'int'), + 'assoc_type' => array('type' => 'varchar', 'length' => 64), + ), + 'primary key' => array(array('server_url', 191), 'handle'), + )); + $schema->ensureTable('oid_nonces', + array( + 'fields' => array( + 'server_url' => array('type' => 'varchar', 'length' => 2047), + 'timestamp' => array('type' => 'int'), + 'salt' => array('type' => 'char', 'length' => 40), + ), + 'unique keys' => array( + 'oid_nonces_server_url_timestamp_salt_key' => array(array('server_url', 191), 'timestamp', 'salt'), + ), + )); + return true; } @@ -596,7 +552,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - function onUserDeleteRelated($user, &$tables) { $tables[] = 'User_openid'; @@ -611,7 +566,6 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - function onEndAdminPanelNav($nav) { if (AdminPanelAction::canAdmin('openid')) { @@ -620,8 +574,10 @@ class OpenIDPlugin extends Plugin $nav->out->menuItem( common_local_url('openidadminpanel'), - _m('OpenID'), - _m('OpenID configuration'), + // TRANS: OpenID configuration menu item. + _m('MENU','OpenID'), + // TRANS: Tooltip for OpenID configuration menu item. + _m('OpenID configuration.'), $action_name == 'openidadminpanel', 'nav_openid_admin_panel' ); @@ -630,6 +586,28 @@ class OpenIDPlugin extends Plugin return true; } + /** + * Add OpenID information to the Account Management Control Document + * Event supplied by the Account Manager plugin + * + * @param array &$amcd Array that expresses the AMCD + * + * @return boolean hook value + */ + + function onEndAccountManagementControlDocument(&$amcd) + { + $amcd['auth-methods']['openid'] = array( + 'connect' => array( + 'method' => 'POST', + 'path' => common_local_url('openidlogin'), + 'params' => array( + 'identity' => 'openid_url' + ) + ) + ); + } + /** * Add our version information to output * @@ -637,16 +615,172 @@ class OpenIDPlugin extends Plugin * * @return boolean hook value */ - - function onPluginVersion(&$versions) + function onPluginVersion(array &$versions) { $versions[] = array('name' => 'OpenID', - 'version' => STATUSNET_VERSION, + 'version' => GNUSOCIAL_VERSION, 'author' => 'Evan Prodromou, Craig Andrews', 'homepage' => 'http://status.net/wiki/Plugin:OpenID', 'rawdescription' => - // TRANS: OpenID plugin description. + // TRANS: Plugin description. _m('Use OpenID to login to the site.')); return true; } + + function onStartOAuthLoginForm($action, &$button) + { + if (common_config('site', 'openidonly')) { + // Cancel the regular password login form, we won't need it. + $this->showOAuthLoginForm($action); + // TRANS: button label for OAuth authorization page when needing OpenID authentication first. + $button = _m('BUTTON', 'Continue'); + return false; + } else { + // Leave the regular password login form in place. + // We'll add an OpenID link at bottom...? + return true; + } + } + + /** + * @fixme merge with common code for main OpenID login form + * @param HTMLOutputter $action + */ + protected function showOAuthLoginForm($action) + { + $action->elementStart('fieldset'); + // TRANS: OpenID plugin logon form legend. + $action->element('legend', null, _m('LEGEND','OpenID login')); + + $action->elementStart('ul', 'form_data'); + $action->elementStart('li'); + $provider = common_config('openid', 'trusted_provider'); + $appendUsername = common_config('openid', 'append_username'); + if ($provider) { + // TRANS: Field label. + $action->element('label', array(), _m('OpenID provider')); + $action->element('span', array(), $provider); + if ($appendUsername) { + $action->element('input', array('id' => 'openid_username', + 'name' => 'openid_username', + 'style' => 'float: none')); + } + $action->element('p', 'form_guide', + // TRANS: Form guide. + ($appendUsername ? _m('Enter your username.') . ' ' : '') . + // TRANS: Form guide. + _m('You will be sent to the provider\'s site for authentication.')); + $action->hidden('openid_url', $provider); + } else { + // TRANS: OpenID plugin logon form field label. + $action->input('openid_url', _m('OpenID URL'), + '', + // TRANS: OpenID plugin logon form field instructions. + _m('Your OpenID URL.')); + } + $action->elementEnd('li'); + $action->elementEnd('ul'); + + $action->elementEnd('fieldset'); + } + + /** + * Handle a POST user credential check in apioauthauthorization. + * If given an OpenID URL, we'll pass us over to the regular things + * and then redirect back here on completion. + * + * @fixme merge with common code for main OpenID login form + * @param HTMLOutputter $action + */ + function onStartOAuthLoginCheck($action, &$user) + { + $provider = common_config('openid', 'trusted_provider'); + if ($provider) { + $openid_url = $provider; + if (common_config('openid', 'append_username')) { + $openid_url .= $action->trimmed('openid_username'); + } + } else { + $openid_url = $action->trimmed('openid_url'); + } + + if ($openid_url) { + require_once dirname(__FILE__) . '/openid.php'; + oid_assert_allowed($openid_url); + + $returnto = common_local_url( + 'ApiOAuthAuthorize', + array(), + array( + 'oauth_token' => $action->arg('oauth_token'), + 'mode' => $action->arg('mode') + ) + ); + common_set_returnto($returnto); + + // This will redirect if functional... + $result = oid_authenticate($openid_url, + 'finishopenidlogin'); + if (is_string($result)) { # error message + throw new ServerException($result); + } else { + exit(0); + } + } + + return true; + } + + /** + * Add link in user's XRD file to allow OpenID login. + * + * This link in the XRD should let users log in with their + * Webfinger identity to services that support it. See + * http://webfinger.org/login for an example. + * + * @param XML_XRD $xrd Currently-displaying resource descriptor + * @param Profile $target The profile that it's for + * + * @return boolean hook value (always true) + */ + + function onEndWebFingerProfileLinks(XML_XRD $xrd, Profile $target) + { + $xrd->links[] = new XML_XRD_Element_Link( + 'http://specs.openid.net/auth/2.0/provider', + $target->profileurl); + + return true; + } + + /** + * Add links in the user's profile block to their OpenID URLs. + * + * @param Profile $profile The profile being shown + * @param Array &$links Writeable array of arrays (href, text, image). + * + * @return boolean hook value (true) + */ + + function onOtherAccountProfiles($profile, &$links) + { + $prefs = User_openid_prefs::getKV('user_id', $profile->id); + + if (empty($prefs) || !$prefs->hide_profile_link) { + + $oid = new User_openid(); + + $oid->user_id = $profile->id; + + if ($oid->find()) { + while ($oid->fetch()) { + $links[] = array('href' => $oid->display, + 'text' => _('OpenID'), + 'image' => $this->path("icons/openid-16x16.gif")); + } + } + } + + return true; + } }