PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/OpenId/Provider.php

https://bitbucket.org/baruffaldi/website-2008-computer-shopping-3
PHP | 759 lines | 483 code | 55 blank | 221 comment | 140 complexity | e8734eb2c45ab4b01cf3e351c741512a MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_OpenId
  17. * @subpackage Zend_OpenId_Provider
  18. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Provider.php 10105 2008-07-15 16:56:48Z dmitry $
  21. */
  22. /**
  23. * @see Zend_OpenId
  24. */
  25. require_once "Zend/OpenId.php";
  26. /**
  27. * @see Zend_OpenId_Extension
  28. */
  29. require_once "Zend/OpenId/Extension.php";
  30. /**
  31. * OpenID provider (server) implementation
  32. *
  33. * @category Zend
  34. * @package Zend_OpenId
  35. * @subpackage Zend_OpenId_Provider
  36. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  37. * @license http://framework.zend.com/license/new-bsd New BSD License
  38. */
  39. class Zend_OpenId_Provider
  40. {
  41. /**
  42. * Reference to an implementation of storage object
  43. *
  44. * @var Zend_OpenId_Provider_Storage $_storage
  45. */
  46. private $_storage;
  47. /**
  48. * Reference to an implementation of user object
  49. *
  50. * @var Zend_OpenId_Provider_User $_user
  51. */
  52. private $_user;
  53. /**
  54. * Time to live of association session in secconds
  55. *
  56. * @var integer $_sessionTtl
  57. */
  58. private $_sessionTtl;
  59. /**
  60. * URL to peform interactive user login
  61. *
  62. * @var string $_loginUrl
  63. */
  64. private $_loginUrl;
  65. /**
  66. * URL to peform interactive validation of consumer by user
  67. *
  68. * @var string $_trustUrl
  69. */
  70. private $_trustUrl;
  71. /**
  72. * Constructs a Zend_OpenId_Provider object with given parameters.
  73. *
  74. * @param string $loginUrl is an URL that provides login screen for
  75. * end-user (by default it is the same URL with additional GET variable
  76. * openid.action=login)
  77. * @param string $trustUrl is an URL that shows a question if end-user
  78. * trust to given consumer (by default it is the same URL with additional
  79. * GET variable openid.action=trust)
  80. * @param Zend_OpenId_Provider_User $user is an object for communication
  81. * with User-Agent and store information about logged-in user (it is a
  82. * Zend_OpenId_Provider_User_Session object by default)
  83. * @param Zend_OpenId_Provider_Storage $storage is an object for keeping
  84. * persistent database (it is a Zend_OpenId_Provider_Storage_File object
  85. * by default)
  86. * @param integer $sessionTtl is a default time to live for association
  87. * session in seconds (1 hour by default). Consumer must reestablish
  88. * association after that time.
  89. */
  90. public function __construct($loginUrl = null,
  91. $trustUrl = null,
  92. Zend_OpenId_Provider_User $user = null,
  93. Zend_OpenId_Provider_Storage $storage = null,
  94. $sessionTtl = 3600)
  95. {
  96. if ($loginUrl === null) {
  97. $loginUrl = Zend_OpenId::selfUrl() . '?openid.action=login';
  98. } else {
  99. $loginUrl = Zend_OpenId::absoluteUrl($loginUrl);
  100. }
  101. $this->_loginUrl = $loginUrl;
  102. if ($trustUrl === null) {
  103. $trustUrl = Zend_OpenId::selfUrl() . '?openid.action=trust';
  104. } else {
  105. $trustUrl = Zend_OpenId::absoluteUrl($trustUrl);
  106. }
  107. $this->_trustUrl = $trustUrl;
  108. if ($user === null) {
  109. require_once "Zend/OpenId/Provider/User/Session.php";
  110. $this->_user = new Zend_OpenId_Provider_User_Session();
  111. } else {
  112. $this->_user = $user;
  113. }
  114. if ($storage === null) {
  115. require_once "Zend/OpenId/Provider/Storage/File.php";
  116. $this->_storage = new Zend_OpenId_Provider_Storage_File();
  117. } else {
  118. $this->_storage = $storage;
  119. }
  120. $this->_sessionTtl = $sessionTtl;
  121. }
  122. /**
  123. * Registers a new user with given $id and $password
  124. * Returns true in case of success and false if user with given $id already
  125. * exists
  126. *
  127. * @param string $id user identity URL
  128. * @param string $password encoded user password
  129. * @return bool
  130. */
  131. public function register($id, $password)
  132. {
  133. if (!Zend_OpenId::normalize($id) || empty($id)) {
  134. return false;
  135. }
  136. return $this->_storage->addUser($id, md5($id.$password));
  137. }
  138. /**
  139. * Returns true if user with given $id exists and false otherwise
  140. *
  141. * @param string $id user identity URL
  142. * @return bool
  143. */
  144. public function hasUser($id) {
  145. if (!Zend_OpenId::normalize($id)) {
  146. return false;
  147. }
  148. return $this->_storage->hasUser($id);
  149. }
  150. /**
  151. * Performs login of user with given $id and $password
  152. * Returns true in case of success and false otherwise
  153. *
  154. * @param string $id user identity URL
  155. * @param string $password user password
  156. * @return bool
  157. */
  158. public function login($id, $password)
  159. {
  160. if (!Zend_OpenId::normalize($id)) {
  161. return false;
  162. }
  163. if (!$this->_storage->checkUser($id, md5($id.$password))) {
  164. return false;
  165. }
  166. $this->_user->setLoggedInUser($id);
  167. return true;
  168. }
  169. /**
  170. * Performs logout. Clears information about logged in user.
  171. *
  172. * @return void
  173. */
  174. public function logout()
  175. {
  176. $this->_user->delLoggedInUser();
  177. return true;
  178. }
  179. /**
  180. * Returns identity URL of current logged in user or false
  181. *
  182. * @return mixed
  183. */
  184. public function getLoggedInUser() {
  185. return $this->_user->getLoggedInUser();
  186. }
  187. /**
  188. * Retrieve consumer's root URL from request query.
  189. * Returns URL or false in case of failure
  190. *
  191. * @param array $params query arguments
  192. * @return mixed
  193. */
  194. public function getSiteRoot($params)
  195. {
  196. $version = 1.1;
  197. if (isset($params['openid_ns']) &&
  198. $params['openid_ns'] == Zend_OpenId::NS_2_0) {
  199. $version = 2.0;
  200. }
  201. if ($version >= 2.0 && isset($params['openid_realm'])) {
  202. $root = $params['openid_realm'];
  203. } else if ($version < 2.0 && isset($params['openid_trust_root'])) {
  204. $root = $params['openid_trust_root'];
  205. } else if (isset($params['openid_return_to'])) {
  206. $root = $params['openid_return_to'];
  207. } else {
  208. return false;
  209. }
  210. if (Zend_OpenId::normalizeUrl($root) && !empty($root)) {
  211. return $root;
  212. }
  213. return false;
  214. }
  215. /**
  216. * Allows consumer with given root URL to authenticate current logged
  217. * in user. Returns true on success and false on error.
  218. *
  219. * @param string $root root URL
  220. * @param mixed $extensions extension object or array of extensions objects
  221. * @return bool
  222. */
  223. public function allowSite($root, $extensions=null)
  224. {
  225. $id = $this->getLoggedInUser();
  226. if ($id === false) {
  227. return false;
  228. }
  229. if ($extensions !== null) {
  230. $data = array();
  231. Zend_OpenId_Extension::forAll($extensions, 'getTrustData', $data);
  232. } else {
  233. $data = true;
  234. }
  235. $this->_storage->addSite($id, $root, $data);
  236. return true;
  237. }
  238. /**
  239. * Prohibit consumer with given root URL to authenticate current logged
  240. * in user. Returns true on success and false on error.
  241. *
  242. * @param string $root root URL
  243. * @return bool
  244. */
  245. public function denySite($root)
  246. {
  247. $id = $this->getLoggedInUser();
  248. if ($id === false) {
  249. return false;
  250. }
  251. $this->_storage->addSite($id, $root, false);
  252. return true;
  253. }
  254. /**
  255. * Delete consumer with given root URL from known sites of current logged
  256. * in user. Next time this consumer will try to authenticate the user,
  257. * Provider will ask user's confirmation.
  258. * Returns true on success and false on error.
  259. *
  260. * @param string $root root URL
  261. * @return bool
  262. */
  263. public function delSite($root)
  264. {
  265. $id = $this->getLoggedInUser();
  266. if ($id === false) {
  267. return false;
  268. }
  269. $this->_storage->addSite($id, $root, null);
  270. return true;
  271. }
  272. /**
  273. * Returns list of known consumers for current logged in user or false
  274. * if he is not logged in.
  275. *
  276. * @return mixed
  277. */
  278. public function getTrustedSites()
  279. {
  280. $id = $this->getLoggedInUser();
  281. if ($id === false) {
  282. return false;
  283. }
  284. return $this->_storage->getTrustedSites($id);
  285. }
  286. /**
  287. * Handles HTTP request from consumer
  288. *
  289. * @param array $params GET or POST variables. If this parameter is omited
  290. * or set to null, then $_GET or $_POST superglobal variable is used
  291. * according to REQUEST_METHOD.
  292. * @param mixed $extensions extension object or array of extensions objects
  293. * @param Zend_Controller_Response_Abstract $response an optional response
  294. * object to perform HTTP or HTML form redirection
  295. * @return mixed
  296. */
  297. public function handle($params=null, $extensions=null,
  298. Zend_Controller_Response_Abstract $response = null)
  299. {
  300. if ($params === null) {
  301. if ($_SERVER["REQUEST_METHOD"] == "GET") {
  302. $params = $_GET;
  303. } else if ($_SERVER["REQUEST_METHOD"] == "POST") {
  304. $params = $_POST;
  305. } else {
  306. return false;
  307. }
  308. }
  309. $version = 1.1;
  310. if (isset($params['openid_ns']) &&
  311. $params['openid_ns'] == Zend_OpenId::NS_2_0) {
  312. $version = 2.0;
  313. }
  314. if (isset($params['openid_mode'])) {
  315. if ($params['openid_mode'] == 'associate') {
  316. $response = $this->_associate($version, $params);
  317. $ret = '';
  318. foreach ($response as $key => $val) {
  319. $ret .= $key . ':' . $val . "\n";
  320. }
  321. return $ret;
  322. } else if ($params['openid_mode'] == 'checkid_immediate') {
  323. $ret = $this->_checkId($version, $params, 1, $extensions, $response);
  324. if (is_bool($ret)) return $ret;
  325. if (!empty($params['openid_return_to'])) {
  326. Zend_OpenId::redirect($params['openid_return_to'], $ret, $response);
  327. }
  328. return true;
  329. } else if ($params['openid_mode'] == 'checkid_setup') {
  330. $ret = $this->_checkId($version, $params, 0, $extensions, $response);
  331. if (is_bool($ret)) return $ret;
  332. if (!empty($params['openid_return_to'])) {
  333. Zend_OpenId::redirect($params['openid_return_to'], $ret, $response);
  334. }
  335. return true;
  336. } else if ($params['openid_mode'] == 'check_authentication') {
  337. $response = $this->_checkAuthentication($version, $params);
  338. $ret = '';
  339. foreach ($response as $key => $val) {
  340. $ret .= $key . ':' . $val . "\n";
  341. }
  342. return $ret;
  343. }
  344. }
  345. return false;
  346. }
  347. /**
  348. * Generates a secret key for given hash function, returns RAW key or false
  349. * if function is not supported
  350. *
  351. * @param string $func hash function (sha1 or sha256)
  352. * @return mixed
  353. */
  354. protected function _genSecret($func)
  355. {
  356. if ($func == 'sha1') {
  357. $macLen = 20; /* 160 bit */
  358. } else if ($func == 'sha256') {
  359. $macLen = 32; /* 256 bit */
  360. } else {
  361. return false;
  362. }
  363. return Zend_OpenId::randomBytes($macLen);
  364. }
  365. /**
  366. * Processes association request from OpenID consumerm generates secret
  367. * shared key and send it back using Diffie-Hellman encruption.
  368. * Returns array of variables to push back to consumer.
  369. *
  370. * @param float $version OpenID version
  371. * @param array $params GET or POST request variables
  372. * @return array
  373. */
  374. protected function _associate($version, $params)
  375. {
  376. $ret = array();
  377. if ($version >= 2.0) {
  378. $ret['ns'] = Zend_OpenId::NS_2_0;
  379. }
  380. if (isset($params['openid_assoc_type']) &&
  381. $params['openid_assoc_type'] == 'HMAC-SHA1') {
  382. $macFunc = 'sha1';
  383. } else if (isset($params['openid_assoc_type']) &&
  384. $params['openid_assoc_type'] == 'HMAC-SHA256' &&
  385. $version >= 2.0) {
  386. $macFunc = 'sha256';
  387. } else {
  388. $ret['error'] = 'Wrong "openid.assoc_type"';
  389. $ret['error-code'] = 'unsupported-type';
  390. return $ret;
  391. }
  392. $ret['assoc_type'] = $params['openid_assoc_type'];
  393. $secret = $this->_genSecret($macFunc);
  394. if (empty($params['openid_session_type']) ||
  395. $params['openid_session_type'] == 'no-encryption') {
  396. $ret['mac_key'] = base64_encode($secret);
  397. } else if (isset($params['openid_session_type']) &&
  398. $params['openid_session_type'] == 'DH-SHA1') {
  399. $dhFunc = 'sha1';
  400. } else if (isset($params['openid_session_type']) &&
  401. $params['openid_session_type'] == 'DH-SHA256' &&
  402. $version >= 2.0) {
  403. $dhFunc = 'sha256';
  404. } else {
  405. $ret['error'] = 'Wrong "openid.session_type"';
  406. $ret['error-code'] = 'unsupported-type';
  407. return $ret;
  408. }
  409. if (isset($params['openid_session_type'])) {
  410. $ret['session_type'] = $params['openid_session_type'];
  411. }
  412. if (isset($dhFunc)) {
  413. if (empty($params['openid_dh_consumer_public'])) {
  414. $ret['error'] = 'Wrong "openid.dh_consumer_public"';
  415. return $ret;
  416. }
  417. if (empty($params['openid_dh_gen'])) {
  418. $g = pack('H*', Zend_OpenId::DH_G);
  419. } else {
  420. $g = base64_decode($params['openid_dh_gen']);
  421. }
  422. if (empty($params['openid_dh_modulus'])) {
  423. $p = pack('H*', Zend_OpenId::DH_P);
  424. } else {
  425. $p = base64_decode($params['openid_dh_modulus']);
  426. }
  427. $dh = Zend_OpenId::createDhKey($p, $g);
  428. $dh_details = Zend_OpenId::getDhKeyDetails($dh);
  429. $sec = Zend_OpenId::computeDhSecret(
  430. base64_decode($params['openid_dh_consumer_public']), $dh);
  431. if ($sec === false) {
  432. $ret['error'] = 'Wrong "openid.session_type"';
  433. $ret['error-code'] = 'unsupported-type';
  434. return $ret;
  435. }
  436. $sec = Zend_OpenId::digest($dhFunc, $sec);
  437. $ret['dh_server_public'] = base64_encode(
  438. Zend_OpenId::btwoc($dh_details['pub_key']));
  439. $ret['enc_mac_key'] = base64_encode($secret ^ $sec);
  440. }
  441. $handle = uniqid();
  442. $expiresIn = $this->_sessionTtl;
  443. $ret['assoc_handle'] = $handle;
  444. $ret['expires_in'] = $expiresIn;
  445. $this->_storage->addAssociation($handle,
  446. $macFunc, $secret, time() + $expiresIn);
  447. return $ret;
  448. }
  449. /**
  450. * Performs authentication (or authentication check).
  451. *
  452. * @param float $version OpenID version
  453. * @param array $params GET or POST request variables
  454. * @param bool $immediate enables or disables interaction with user
  455. * @param mixed $extensions extension object or array of extensions objects
  456. * @param Zend_Controller_Response_Abstract $response
  457. * @return array
  458. */
  459. protected function _checkId($version, $params, $immediate, $extensions=null,
  460. Zend_Controller_Response_Abstract $response = null)
  461. {
  462. $ret = array();
  463. if ($version >= 2.0) {
  464. $ret['openid.ns'] = Zend_OpenId::NS_2_0;
  465. }
  466. $root = $this->getSiteRoot($params);
  467. if ($root === false) {
  468. return false;
  469. }
  470. if (isset($params['openid_identity']) &&
  471. !$this->_storage->hasUser($params['openid_identity'])) {
  472. $ret['openid.mode'] = ($immediate && $version >= 2.0) ? 'setup_needed': 'cancel';
  473. return $ret;
  474. }
  475. /* Check if user already logged in into the server */
  476. if (!isset($params['openid_identity']) ||
  477. $this->_user->getLoggedInUser() !== $params['openid_identity']) {
  478. $params2 = array();
  479. foreach ($params as $key => $val) {
  480. if (strpos($key, 'openid_ns_') === 0) {
  481. $key = 'openid.ns.' . substr($key, strlen('openid_ns_'));
  482. } else if (strpos($key, 'openid_sreg_') === 0) {
  483. $key = 'openid.sreg.' . substr($key, strlen('openid_sreg_'));
  484. } else if (strpos($key, 'openid_') === 0) {
  485. $key = 'openid.' . substr($key, strlen('openid_'));
  486. }
  487. $params2[$key] = $val;
  488. }
  489. if ($immediate) {
  490. $params2['openid.mode'] = 'checkid_setup';
  491. $ret['openid.mode'] = ($version >= 2.0) ? 'setup_needed': 'cancel';
  492. $ret['openid.user_setup_url'] = $this->_loginUrl
  493. . (strpos($this->_loginUrl, '?') === false ? '?' : '&')
  494. . Zend_OpenId::paramsToQuery($params2);
  495. return $ret;
  496. } else {
  497. /* Redirect to Server Login Screen */
  498. Zend_OpenId::redirect($this->_loginUrl, $params2, $response);
  499. return true;
  500. }
  501. }
  502. if (!Zend_OpenId_Extension::forAll($extensions, 'parseRequest', $params)) {
  503. $ret['openid.mode'] = ($immediate && $version >= 2.0) ? 'setup_needed': 'cancel';
  504. return $ret;
  505. }
  506. /* Check if user trusts to the consumer */
  507. $trusted = null;
  508. $sites = $this->_storage->getTrustedSites($params['openid_identity']);
  509. if (isset($params['openid_return_to'])) {
  510. $root = $params['openid_return_to'];
  511. }
  512. if (isset($sites[$root])) {
  513. $trusted = $sites[$root];
  514. } else {
  515. foreach ($sites as $site => $t) {
  516. if (strpos($root, $site) === 0) {
  517. $trusted = $t;
  518. break;
  519. } else {
  520. /* OpenID 2.0 (9.2) check for realm wild-card matching */
  521. $n = strpos($site, '://*.');
  522. if ($n != false) {
  523. $regex = '/^'
  524. . preg_quote(substr($site, 0, $n+3), '/')
  525. . '[A-Za-z1-9_\.]+?'
  526. . preg_quote(substr($site, $n+4), '/')
  527. . '/';
  528. if (preg_match($regex, $root)) {
  529. $trusted = $t;
  530. break;
  531. }
  532. }
  533. }
  534. }
  535. }
  536. if (is_array($trusted)) {
  537. if (!Zend_OpenId_Extension::forAll($extensions, 'checkTrustData', $trusted)) {
  538. $trusted = null;
  539. }
  540. }
  541. if ($trusted === false) {
  542. $ret['openid.mode'] = 'cancel';
  543. return $ret;
  544. } else if (is_null($trusted)) {
  545. /* Redirect to Server Trust Screen */
  546. $params2 = array();
  547. foreach ($params as $key => $val) {
  548. if (strpos($key, 'openid_ns_') === 0) {
  549. $key = 'openid.ns.' . substr($key, strlen('openid_ns_'));
  550. } else if (strpos($key, 'openid_sreg_') === 0) {
  551. $key = 'openid.sreg.' . substr($key, strlen('openid_sreg_'));
  552. } else if (strpos($key, 'openid_') === 0) {
  553. $key = 'openid.' . substr($key, strlen('openid_'));
  554. }
  555. $params2[$key] = $val;
  556. }
  557. if ($immediate) {
  558. $params2['openid.mode'] = 'checkid_setup';
  559. $ret['openid.mode'] = ($version >= 2.0) ? 'setup_needed': 'cancel';
  560. $ret['openid.user_setup_url'] = $this->_trustUrl
  561. . (strpos($this->_trustUrl, '?') === false ? '?' : '&')
  562. . Zend_OpenId::paramsToQuery($params2);
  563. return $ret;
  564. } else {
  565. Zend_OpenId::redirect($this->_trustUrl, $params2, $response);
  566. return true;
  567. }
  568. }
  569. return $this->_respond($version, $ret, $params, $extensions);
  570. }
  571. /**
  572. * Perepares information to send back to consumer's authentication request,
  573. * signs it using shared secret and send back through HTTP redirection
  574. *
  575. * @param array $params GET or POST request variables
  576. * @param mixed $extensions extension object or array of extensions objects
  577. * @param Zend_Controller_Response_Abstract $response an optional response
  578. * object to perform HTTP or HTML form redirection
  579. * @return bool
  580. */
  581. public function respondToConsumer($params, $extensions=null,
  582. Zend_Controller_Response_Abstract $response = null)
  583. {
  584. $version = 1.1;
  585. if (isset($params['openid_ns']) &&
  586. $params['openid_ns'] == Zend_OpenId::NS_2_0) {
  587. $version = 2.0;
  588. }
  589. $ret = array();
  590. if ($version >= 2.0) {
  591. $ret['openid.ns'] = Zend_OpenId::NS_2_0;
  592. }
  593. $ret = $this->_respond($version, $ret, $params, $extensions);
  594. if (!empty($params['openid_return_to'])) {
  595. Zend_OpenId::redirect($params['openid_return_to'], $ret, $response);
  596. }
  597. return true;
  598. }
  599. /**
  600. * Perepares information to send back to consumer's authentication request
  601. * and signs it using shared secret.
  602. *
  603. * @param float $version OpenID protcol version
  604. * @param array $ret arguments to be send back to consumer
  605. * @param array $params GET or POST request variables
  606. * @param mixed $extensions extension object or array of extensions objects
  607. * @return array
  608. */
  609. protected function _respond($version, $ret, $params, $extensions=null)
  610. {
  611. if (empty($params['openid_assoc_handle']) ||
  612. !$this->_storage->getAssociation($params['openid_assoc_handle'],
  613. $macFunc, $secret, $expires)) {
  614. /* Use dumb mode */
  615. if (!empty($params['openid_assoc_handle'])) {
  616. $ret['openid.invalidate_handle'] = $params['openid_assoc_handle'];
  617. }
  618. $macFunc = $version >= 2.0 ? 'sha256' : 'sha1';
  619. $secret = $this->_genSecret($macFunc);
  620. $handle = uniqid();
  621. $expiresIn = $this->_sessionTtl;
  622. $this->_storage->addAssociation($handle,
  623. $macFunc, $secret, time() + $expiresIn);
  624. $ret['openid.assoc_handle'] = $handle;
  625. } else {
  626. $ret['openid.assoc_handle'] = $params['openid_assoc_handle'];
  627. }
  628. if (isset($params['openid_return_to'])) {
  629. $ret['openid.return_to'] = $params['openid_return_to'];
  630. }
  631. if (isset($params['openid_claimed_id'])) {
  632. $ret['openid.claimed_id'] = $params['openid_claimed_id'];
  633. }
  634. if (isset($params['openid_identity'])) {
  635. $ret['openid.identity'] = $params['openid_identity'];
  636. }
  637. if ($version >= 2.0) {
  638. $ret['openid.op_endpoint'] = Zend_OpenId::selfUrl();
  639. }
  640. $ret['openid.response_nonce'] = gmdate('Y-m-d\TH:i:s\Z') . uniqid();
  641. $ret['openid.mode'] = 'id_res';
  642. Zend_OpenId_Extension::forAll($extensions, 'prepareResponse', $ret);
  643. $signed = '';
  644. $data = '';
  645. foreach ($ret as $key => $val) {
  646. if (strpos($key, 'openid.') === 0) {
  647. $key = substr($key, strlen('openid.'));
  648. if (!empty($signed)) {
  649. $signed .= ',';
  650. }
  651. $signed .= $key;
  652. $data .= $key . ':' . $val . "\n";
  653. }
  654. }
  655. $signed .= ',signed';
  656. $data .= 'signed:' . $signed . "\n";
  657. $ret['openid.signed'] = $signed;
  658. $ret['openid.sig'] = base64_encode(
  659. Zend_OpenId::hashHmac($macFunc, $data, $secret));
  660. return $ret;
  661. }
  662. /**
  663. * Performs authentication validation for dumb consumers
  664. * Returns array of variables to push back to consumer.
  665. * It MUST contain 'is_valid' variable with value 'true' or 'false'.
  666. *
  667. * @param float $version OpenID version
  668. * @param array $params GET or POST request variables
  669. * @return array
  670. */
  671. protected function _checkAuthentication($version, $params)
  672. {
  673. $ret = array();
  674. if ($version >= 2.0) {
  675. $ret['ns'] = Zend_OpenId::NS_2_0;
  676. }
  677. $ret['openid.mode'] = 'id_res';
  678. if (empty($params['openid_assoc_handle']) ||
  679. empty($params['openid_signed']) ||
  680. empty($params['openid_sig']) ||
  681. !$this->_storage->getAssociation($params['openid_assoc_handle'],
  682. $macFunc, $secret, $expires)) {
  683. $ret['is_valid'] = 'false';
  684. return $ret;
  685. }
  686. $signed = explode(',', $params['openid_signed']);
  687. $data = '';
  688. foreach ($signed as $key) {
  689. $data .= $key . ':';
  690. if ($key == 'mode') {
  691. $data .= "id_res\n";
  692. } else {
  693. $data .= $params['openid_' . strtr($key,'.','_')]."\n";
  694. }
  695. }
  696. if (base64_decode($params['openid_sig']) ===
  697. Zend_OpenId::hashHmac($macFunc, $data, $secret)) {
  698. $ret['is_valid'] = 'true';
  699. } else {
  700. $ret['is_valid'] = 'false';
  701. }
  702. return $ret;
  703. }
  704. }