OpenIDPlugin.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. <?php
  2. /**
  3. * StatusNet, the distributed open-source microblogging tool
  4. *
  5. * PHP version 5
  6. *
  7. * LICENCE: This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. * @category Plugin
  21. * @package StatusNet
  22. * @author Evan Prodromou <evan@status.net>
  23. * @author Craig Andrews <candrews@integralblue.com>
  24. * @copyright 2009-2010 StatusNet, Inc.
  25. * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
  26. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  27. * @link http://status.net/
  28. */
  29. if (!defined('STATUSNET')) {
  30. exit(1);
  31. }
  32. include("../plugins/OpenID/classes/User_openid.php");
  33. include("../plugins/OpenID/classes/User_openid_trustroot.php");
  34. include("../plugins/OpenID/classes/User_openid_prefs.php");
  35. /**
  36. * Plugin for OpenID authentication and identity
  37. *
  38. * This class enables consumer support for OpenID, the distributed authentication
  39. * and identity system.
  40. *
  41. * Depends on: WebFinger plugin for HostMeta-lookup (user@host format)
  42. *
  43. * @category Plugin
  44. * @package StatusNet
  45. * @author Evan Prodromou <evan@status.net>
  46. * @author Craig Andrews <candrews@integralblue.com>
  47. * @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
  48. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  49. * @link http://status.net/
  50. * @link http://openid.net/
  51. */
  52. class OpenIDPlugin extends Plugin
  53. {
  54. const PLUGIN_VERSION = '2.1.1';
  55. // Plugin parameter: set true to disallow non-OpenID logins
  56. // If set, overrides the setting in database or $config['site']['openidonly']
  57. public $openidOnly = null;
  58. function initialize()
  59. {
  60. parent::initialize();
  61. if ($this->openidOnly !== null) {
  62. global $config;
  63. $config['site']['openidonly'] = (bool)$this->openidOnly;
  64. }
  65. }
  66. /**
  67. * Add OpenID-related paths to the router table
  68. *
  69. * Hook for RouterInitialized event.
  70. *
  71. * @param URLMapper $m URL mapper
  72. *
  73. * @return boolean hook return
  74. */
  75. public function onStartInitializeRouter(URLMapper $m)
  76. {
  77. $m->connect('main/openid', array('action' => 'openidlogin'));
  78. $m->connect('main/openidtrust', array('action' => 'openidtrust'));
  79. $m->connect('settings/openid', array('action' => 'openidsettings'));
  80. $m->connect('index.php?action=finishopenidlogin',
  81. array('action' => 'finishopenidlogin'));
  82. $m->connect('index.php?action=finishaddopenid',
  83. array('action' => 'finishaddopenid'));
  84. $m->connect('index.php?action=finishsynchopenid',
  85. array('action' => 'finishsynchopenid'));
  86. $m->connect('main/openidserver', array('action' => 'openidserver'));
  87. $m->connect('panel/openid', array('action' => 'openidadminpanel'));
  88. return true;
  89. }
  90. /**
  91. * In OpenID-only mode, disable paths for password stuff
  92. *
  93. * @param string $path path to connect
  94. * @param array $defaults path defaults
  95. * @param array $rules path rules
  96. * @param array $result unused
  97. *
  98. * @return boolean hook return
  99. */
  100. function onStartConnectPath(&$path, &$defaults, &$rules, &$result)
  101. {
  102. if (common_config('site', 'openidonly')) {
  103. // Note that we should not remove the login and register
  104. // actions. Lots of auth-related things link to them,
  105. // such as when visiting a private site without a session
  106. // or revalidating a remembered login for admin work.
  107. //
  108. // We take those two over with redirects to ourselves
  109. // over in onArgsInitialize().
  110. static $block = array('main/recoverpassword',
  111. 'settings/password');
  112. if (in_array($path, $block)) {
  113. return false;
  114. }
  115. }
  116. return true;
  117. }
  118. /**
  119. * If we've been hit with password-login args, redirect
  120. *
  121. * @param array $args args (URL, Get, post)
  122. *
  123. * @return boolean hook return
  124. */
  125. function onArgsInitialize($args)
  126. {
  127. if (common_config('site', 'openidonly')) {
  128. if (array_key_exists('action', $args)) {
  129. $action = trim($args['action']);
  130. if (in_array($action, array('login', 'register'))) {
  131. common_redirect(common_local_url('openidlogin'));
  132. } else if ($action == 'passwordsettings') {
  133. common_redirect(common_local_url('openidsettings'));
  134. } else if ($action == 'recoverpassword') {
  135. // TRANS: Client exception thrown when an action is not available.
  136. throw new ClientException(_m('Unavailable action.'));
  137. }
  138. }
  139. }
  140. return true;
  141. }
  142. /**
  143. * Public XRDS output hook
  144. *
  145. * Puts the bits of code needed by some OpenID providers to show
  146. * we're good citizens.
  147. *
  148. * @param Action $action Action being executed
  149. * @param XMLOutputter &$xrdsOutputter Output channel
  150. *
  151. * @return boolean hook return
  152. */
  153. function onEndPublicXRDS(Action $action, &$xrdsOutputter)
  154. {
  155. $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
  156. 'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
  157. 'version' => '2.0'));
  158. $xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
  159. //consumer
  160. foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
  161. $xrdsOutputter->showXrdsService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
  162. common_local_url($finish));
  163. }
  164. //provider
  165. $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/server',
  166. common_local_url('openidserver'),
  167. null,
  168. null,
  169. 'http://specs.openid.net/auth/2.0/identifier_select');
  170. $xrdsOutputter->elementEnd('XRD');
  171. }
  172. /**
  173. * If we're in OpenID-only mode, hide all the main menu except OpenID login.
  174. *
  175. * @param Action $action Action being run
  176. *
  177. * @return boolean hook return
  178. */
  179. function onStartPrimaryNav($action)
  180. {
  181. if (common_config('site', 'openidonly') && !common_logged_in()) {
  182. // TRANS: Tooltip for main menu option "Login"
  183. $tooltip = _m('TOOLTIP', 'Login to the site.');
  184. $action->menuItem(common_local_url('openidlogin'),
  185. // TRANS: Main menu option when not logged in to log in
  186. _m('MENU', 'Login'),
  187. $tooltip,
  188. false,
  189. 'nav_login');
  190. // TRANS: Tooltip for main menu option "Help"
  191. $tooltip = _m('TOOLTIP', 'Help me!');
  192. $action->menuItem(common_local_url('doc', array('title' => 'help')),
  193. // TRANS: Main menu option for help on the StatusNet site
  194. _m('MENU', 'Help'),
  195. $tooltip,
  196. false,
  197. 'nav_help');
  198. if (!common_config('site', 'private')) {
  199. // TRANS: Tooltip for main menu option "Search"
  200. $tooltip = _m('TOOLTIP', 'Search for people or text.');
  201. $action->menuItem(common_local_url('peoplesearch'),
  202. // TRANS: Main menu option when logged in or when the StatusNet instance is not private
  203. _m('MENU', 'Search'), $tooltip, false, 'nav_search');
  204. }
  205. Event::handle('EndPrimaryNav', array($action));
  206. return false;
  207. }
  208. return true;
  209. }
  210. /**
  211. * Menu for login
  212. *
  213. * If we're in openidOnly mode, we disable the menu for all other login.
  214. *
  215. * @param Action $action Action being executed
  216. *
  217. * @return boolean hook return
  218. */
  219. function onStartLoginGroupNav($action)
  220. {
  221. if (common_config('site', 'openidonly')) {
  222. $this->showOpenIDLoginTab($action);
  223. // Even though we replace this code, we
  224. // DON'T run the End* hook, to keep others from
  225. // adding tabs. Not nice, but.
  226. return false;
  227. }
  228. return true;
  229. }
  230. /**
  231. * Menu item for login
  232. *
  233. * @param Action $action Action being executed
  234. *
  235. * @return boolean hook return
  236. */
  237. function onEndLoginGroupNav($action)
  238. {
  239. $this->showOpenIDLoginTab($action);
  240. return true;
  241. }
  242. /**
  243. * Show menu item for login
  244. *
  245. * @param Action $action Action being executed
  246. *
  247. * @return void
  248. */
  249. function showOpenIDLoginTab($action)
  250. {
  251. $action_name = $action->trimmed('action');
  252. $action->menuItem(common_local_url('openidlogin'),
  253. // TRANS: OpenID plugin menu item on site logon page.
  254. _m('MENU', 'OpenID'),
  255. // TRANS: OpenID plugin tooltip for logon menu item.
  256. _m('Login or register with OpenID.'),
  257. $action_name === 'openidlogin');
  258. }
  259. /**
  260. * Show menu item for password
  261. *
  262. * We hide it in openID-only mode
  263. *
  264. * @param Action $menu Widget for menu
  265. * @param void &$unused Unused value
  266. *
  267. * @return void
  268. */
  269. function onStartAccountSettingsPasswordMenuItem($menu, &$unused) {
  270. if (common_config('site', 'openidonly')) {
  271. return false;
  272. }
  273. return true;
  274. }
  275. /**
  276. * Menu item for OpenID settings
  277. *
  278. * @param Action $action Action being executed
  279. *
  280. * @return boolean hook return
  281. */
  282. function onEndAccountSettingsNav($action)
  283. {
  284. $action_name = $action->trimmed('action');
  285. $action->menuItem(common_local_url('openidsettings'),
  286. // TRANS: OpenID plugin menu item on user settings page.
  287. _m('MENU', 'OpenID'),
  288. // TRANS: OpenID plugin tooltip for user settings menu item.
  289. _m('Add or remove OpenIDs.'),
  290. $action_name === 'openidsettings');
  291. return true;
  292. }
  293. /**
  294. * Autoloader
  295. *
  296. * Loads our classes if they're requested.
  297. *
  298. * @param string $cls Class requested
  299. *
  300. * @return boolean hook return
  301. */
  302. function onAutoload($cls)
  303. {
  304. switch ($cls)
  305. {
  306. case 'Auth_OpenID_TeamsExtension':
  307. case 'Auth_OpenID_TeamsRequest':
  308. case 'Auth_OpenID_TeamsResponse':
  309. require_once dirname(__FILE__) . '/extlib/teams-extension.php';
  310. return false;
  311. }
  312. return parent::onAutoload($cls);
  313. }
  314. /**
  315. * Login actions
  316. *
  317. * These actions should be visible even when the site is marked private
  318. *
  319. * @param Action $action Action to show
  320. * @param boolean &$login Whether it's a login action
  321. *
  322. * @return boolean hook return
  323. */
  324. function onLoginAction($action, &$login)
  325. {
  326. switch ($action)
  327. {
  328. case 'openidlogin':
  329. case 'finishopenidlogin':
  330. case 'openidserver':
  331. $login = true;
  332. return false;
  333. default:
  334. return true;
  335. }
  336. }
  337. /**
  338. * We include a <meta> element linking to the webfinger resource page,
  339. * for OpenID client-side authentication.
  340. *
  341. * @param Action $action Action being shown
  342. *
  343. * @return void
  344. */
  345. function onEndShowHeadElements(Action $action)
  346. {
  347. if ($action instanceof ShowstreamAction) {
  348. $action->element('link', array('rel' => 'openid2.provider',
  349. 'href' => common_local_url('openidserver')));
  350. $action->element('link', array('rel' => 'openid2.local_id',
  351. 'href' => $action->getTarget()->getUrl()));
  352. $action->element('link', array('rel' => 'openid.server',
  353. 'href' => common_local_url('openidserver')));
  354. $action->element('link', array('rel' => 'openid.delegate',
  355. 'href' => $action->getTarget()->getUrl()));
  356. }
  357. if ($action instanceof SitestreamAction) {
  358. $action->element('meta', array('http-equiv' => 'X-XRDS-Location',
  359. 'content' => common_local_url('publicxrds')));
  360. }
  361. return true;
  362. }
  363. /**
  364. * Redirect to OpenID login if they have an OpenID
  365. *
  366. * @param Action $action Action being executed
  367. * @param User $user User doing the action
  368. *
  369. * @return boolean whether to continue
  370. */
  371. function onRedirectToLogin($action, $user)
  372. {
  373. if (common_config('site', 'openidonly') || (!empty($user) && User_openid::hasOpenID($user->id))) {
  374. common_redirect(common_local_url('openidlogin'), 303);
  375. }
  376. return true;
  377. }
  378. /**
  379. * Show some extra instructions for using OpenID
  380. *
  381. * @param Action $action Action being executed
  382. *
  383. * @return boolean hook value
  384. */
  385. function onEndShowPageNotice($action)
  386. {
  387. $name = $action->trimmed('action');
  388. switch ($name)
  389. {
  390. case 'register':
  391. if (common_logged_in()) {
  392. // TRANS: Page notice for logged in users to try and get them to add an OpenID account to their StatusNet account.
  393. // TRANS: This message contains Markdown links in the form (description)[link].
  394. $instr = _m('(Have an [OpenID](http://openid.net/)? ' .
  395. '[Add an OpenID to your account](%%action.openidsettings%%)!');
  396. } else {
  397. // TRANS: Page notice for anonymous users to try and get them to register with an OpenID account.
  398. // TRANS: This message contains Markdown links in the form (description)[link].
  399. $instr = _m('(Have an [OpenID](http://openid.net/)? ' .
  400. 'Try our [OpenID registration]'.
  401. '(%%action.openidlogin%%)!)');
  402. }
  403. break;
  404. case 'login':
  405. // TRANS: Page notice on the login page to try and get them to log on with an OpenID account.
  406. // TRANS: This message contains Markdown links in the form (description)[link].
  407. $instr = _m('(Have an [OpenID](http://openid.net/)? ' .
  408. 'Try our [OpenID login]'.
  409. '(%%action.openidlogin%%)!)');
  410. break;
  411. default:
  412. return true;
  413. }
  414. $output = common_markup_to_html($instr);
  415. $action->raw($output);
  416. return true;
  417. }
  418. /**
  419. * Load our document if requested
  420. *
  421. * @param string &$title Title to fetch
  422. * @param string &$output HTML to output
  423. *
  424. * @return boolean hook value
  425. */
  426. function onStartLoadDoc(&$title, &$output)
  427. {
  428. if ($title == 'openid') {
  429. $filename = INSTALLDIR.'/plugins/OpenID/doc-src/openid';
  430. $c = file_get_contents($filename);
  431. $output = common_markup_to_html($c);
  432. return false; // success!
  433. }
  434. return true;
  435. }
  436. /**
  437. * Add our document to the global menu
  438. *
  439. * @param string $title Title being fetched
  440. * @param string &$output HTML being output
  441. *
  442. * @return boolean hook value
  443. */
  444. function onEndDocsMenu(&$items) {
  445. $items[] = array('doc',
  446. array('title' => 'openid'),
  447. _m('MENU', 'OpenID'),
  448. _('Logging in with OpenID'),
  449. 'nav_doc_openid');
  450. return true;
  451. }
  452. /**
  453. * Data definitions
  454. *
  455. * Assure that our data objects are available in the DB
  456. *
  457. * @return boolean hook value
  458. */
  459. function onCheckSchema()
  460. {
  461. $schema = Schema::get();
  462. $schema->ensureTable('user_openid', User_openid::schemaDef());
  463. $schema->ensureTable('user_openid_trustroot', User_openid_trustroot::schemaDef());
  464. $schema->ensureTable('user_openid_prefs', User_openid_prefs::schemaDef());
  465. /* These are used by JanRain OpenID library */
  466. $schema->ensureTable('oid_associations',
  467. array(
  468. 'fields' => array(
  469. 'server_url' => array('type' => 'varchar', 'length' => 2047, 'not null' => true),
  470. 'handle' => array('type' => 'varchar', 'length' => 255, 'not null' => true, 'default' => ''),
  471. 'secret' => array('type' => 'blob'),
  472. 'issued' => array('type' => 'int', 'size' => 'big'),
  473. 'lifetime' => array('type' => 'int'),
  474. 'assoc_type' => array('type' => 'varchar', 'length' => 64),
  475. ),
  476. 'primary key' => array(array('server_url', 191), array('handle', 191)),
  477. ));
  478. $schema->ensureTable('oid_nonces',
  479. array(
  480. 'fields' => array(
  481. 'server_url' => array('type' => 'varchar', 'length' => 2047),
  482. 'timestamp' => array('type' => 'int', 'size' => 'big'),
  483. 'salt' => array('type' => 'char', 'length' => 40),
  484. ),
  485. 'unique keys' => array(
  486. 'oid_nonces_server_url_timestamp_salt_key' => array(array('server_url', 191), 'timestamp', 'salt'),
  487. ),
  488. ));
  489. return true;
  490. }
  491. /**
  492. * Add our tables to be deleted when a user is deleted
  493. *
  494. * @param User $user User being deleted
  495. * @param array &$tables Array of table names
  496. *
  497. * @return boolean hook value
  498. */
  499. function onUserDeleteRelated($user, &$tables)
  500. {
  501. $tables[] = 'User_openid';
  502. $tables[] = 'User_openid_trustroot';
  503. return true;
  504. }
  505. /**
  506. * Add an OpenID tab to the admin panel
  507. *
  508. * @param Widget $nav Admin panel nav
  509. *
  510. * @return boolean hook value
  511. */
  512. function onEndAdminPanelNav($nav)
  513. {
  514. if (AdminPanelAction::canAdmin('openid')) {
  515. $action_name = $nav->action->trimmed('action');
  516. $nav->out->menuItem(
  517. common_local_url('openidadminpanel'),
  518. // TRANS: OpenID configuration menu item.
  519. _m('MENU','OpenID'),
  520. // TRANS: Tooltip for OpenID configuration menu item.
  521. _m('OpenID configuration.'),
  522. $action_name == 'openidadminpanel',
  523. 'nav_openid_admin_panel'
  524. );
  525. }
  526. return true;
  527. }
  528. /**
  529. * Add OpenID information to the Account Management Control Document
  530. * Event supplied by the Account Manager plugin
  531. *
  532. * @param array &$amcd Array that expresses the AMCD
  533. *
  534. * @return boolean hook value
  535. */
  536. function onEndAccountManagementControlDocument(&$amcd)
  537. {
  538. $amcd['auth-methods']['openid'] = array(
  539. 'connect' => array(
  540. 'method' => 'POST',
  541. 'path' => common_local_url('openidlogin'),
  542. 'params' => array(
  543. 'identity' => 'openid_url'
  544. )
  545. )
  546. );
  547. }
  548. /**
  549. * Add our version information to output
  550. *
  551. * @param array &$versions Array of version-data arrays
  552. *
  553. * @return boolean hook value
  554. */
  555. public function onPluginVersion(array &$versions): bool
  556. {
  557. $versions[] = array('name' => 'OpenID',
  558. 'version' => self::PLUGIN_VERSION,
  559. 'author' => 'Evan Prodromou, Craig Andrews',
  560. 'homepage' => GNUSOCIAL_ENGINE_REPO_URL . 'tree/master/plugins/OpenID',
  561. 'rawdescription' =>
  562. // TRANS: Plugin description.
  563. _m('Use <a href="http://openid.net/">OpenID</a> to login to the site.'));
  564. return true;
  565. }
  566. function onStartOAuthLoginForm($action, &$button)
  567. {
  568. if (common_config('site', 'openidonly')) {
  569. // Cancel the regular password login form, we won't need it.
  570. $this->showOAuthLoginForm($action);
  571. // TRANS: button label for OAuth authorization page when needing OpenID authentication first.
  572. $button = _m('BUTTON', 'Continue');
  573. return false;
  574. } else {
  575. // Leave the regular password login form in place.
  576. // We'll add an OpenID link at bottom...?
  577. return true;
  578. }
  579. }
  580. /**
  581. * @fixme merge with common code for main OpenID login form
  582. * @param HTMLOutputter $action
  583. */
  584. protected function showOAuthLoginForm($action)
  585. {
  586. $action->elementStart('fieldset');
  587. // TRANS: OpenID plugin logon form legend.
  588. $action->element('legend', null, _m('LEGEND','OpenID login'));
  589. $action->elementStart('ul', 'form_data');
  590. $action->elementStart('li');
  591. $provider = common_config('openid', 'trusted_provider');
  592. $appendUsername = common_config('openid', 'append_username');
  593. if ($provider) {
  594. // TRANS: Field label.
  595. $action->element('label', array(), _m('OpenID provider'));
  596. $action->element('span', array(), $provider);
  597. if ($appendUsername) {
  598. $action->element('input', array('id' => 'openid_username',
  599. 'name' => 'openid_username',
  600. 'style' => 'float: none'));
  601. }
  602. $action->element('p', 'form_guide',
  603. // TRANS: Form guide.
  604. ($appendUsername ? _m('Enter your username.') . ' ' : '') .
  605. // TRANS: Form guide.
  606. _m('You will be sent to the provider\'s site for authentication.'));
  607. $action->hidden('openid_url', $provider);
  608. } else {
  609. // TRANS: OpenID plugin logon form field label.
  610. $action->input('openid_url', _m('OpenID URL'),
  611. '',
  612. // TRANS: OpenID plugin logon form field instructions.
  613. _m('Your OpenID URL.'));
  614. }
  615. $action->elementEnd('li');
  616. $action->elementEnd('ul');
  617. $action->elementEnd('fieldset');
  618. }
  619. /**
  620. * Handle a POST user credential check in apioauthauthorization.
  621. * If given an OpenID URL, we'll pass us over to the regular things
  622. * and then redirect back here on completion.
  623. *
  624. * @fixme merge with common code for main OpenID login form
  625. * @param HTMLOutputter $action
  626. */
  627. function onStartOAuthLoginCheck($action, &$user)
  628. {
  629. $provider = common_config('openid', 'trusted_provider');
  630. if ($provider) {
  631. $openid_url = $provider;
  632. if (common_config('openid', 'append_username')) {
  633. $openid_url .= $action->trimmed('openid_username');
  634. }
  635. } else {
  636. $openid_url = $action->trimmed('openid_url');
  637. }
  638. if ($openid_url) {
  639. require_once dirname(__FILE__) . '/openid.php';
  640. oid_assert_allowed($openid_url);
  641. $returnto = common_local_url(
  642. 'ApiOAuthAuthorize',
  643. array(),
  644. array(
  645. 'oauth_token' => $action->arg('oauth_token'),
  646. 'mode' => $action->arg('mode')
  647. )
  648. );
  649. common_set_returnto($returnto);
  650. // This will redirect if functional...
  651. $result = oid_authenticate($openid_url,
  652. 'finishopenidlogin');
  653. if (is_string($result)) { # error message
  654. throw new ServerException($result);
  655. } else {
  656. exit(0);
  657. }
  658. }
  659. return true;
  660. }
  661. /**
  662. * Add link in user's XRD file to allow OpenID login.
  663. *
  664. * This link in the XRD should let users log in with their
  665. * Webfinger identity to services that support it. See
  666. * http://webfinger.org/login for an example.
  667. *
  668. * @param XML_XRD $xrd Currently-displaying resource descriptor
  669. * @param Profile $target The profile that it's for
  670. *
  671. * @return boolean hook value (always true)
  672. */
  673. function onEndWebFingerProfileLinks(XML_XRD $xrd, Profile $target)
  674. {
  675. $xrd->links[] = new XML_XRD_Element_Link(
  676. 'http://specs.openid.net/auth/2.0/provider',
  677. $target->profileurl);
  678. return true;
  679. }
  680. /**
  681. * Add links in the user's profile block to their OpenID URLs.
  682. *
  683. * @param Profile $profile The profile being shown
  684. * @param Array &$links Writeable array of arrays (href, text, image).
  685. *
  686. * @return boolean hook value (true)
  687. */
  688. function onOtherAccountProfiles($profile, &$links)
  689. {
  690. $prefs = User_openid_prefs::getKV('user_id', $profile->id);
  691. if (empty($prefs) || !$prefs->hide_profile_link) {
  692. $oid = new User_openid();
  693. $oid->user_id = $profile->id;
  694. if ($oid->find()) {
  695. while ($oid->fetch()) {
  696. $links[] = array('href' => $oid->display,
  697. 'text' => _('OpenID'),
  698. 'image' => $this->path("icons/openid-16x16.gif"));
  699. }
  700. }
  701. }
  702. return true;
  703. }
  704. }