PageRenderTime 149ms CodeModel.GetById 61ms app.highlight 52ms RepoModel.GetById 28ms app.codeStats 1ms

/library/Zend/OpenId/Provider.php

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