/lib/Molinos/OpenID/Handlers/Generic.php
PHP | 321 lines | 212 code | 42 blank | 67 comment | 25 complexity | 823b86d4cdf6b157c2ced4a2f5339cd6 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0
- <?php
- /**
- * ???? ? ??????? OpenID.
- *
- * @package Molinos_CMS
- * @subpackage OpenID
- * @author Justin Forest <justin.forest@gmail.com>
- * @copyright 2006-2011 molinos.ru
- * @license http://www.gnu.org/copyleft/gpl.html GPL
- */
- class Molinos_OpenID_Handlers_Generic extends Molinos_Auth_RequestHandler
- {
- public function get()
- {
- if ('return' != $this->arg('action'))
- return parent::get();
- try {
- $t = new Molinos_Database_Transaction();
- $user = $this->getUser();
- Molinos_Hook_Dispatcher::getInstance()
- ->call('ru_molinos_cms_hook_login', array($user));
- $this->ctx->session->login = array(
- 'id' => $user->id,
- 'groups' => $user->getGroups(),
- );
- $t->commit();
- return new Molinos_HTTP_Responses_Redirect($this->arg('destination'));
- } catch (Molinos_Base_Exceptions_NotFound $e) {
- throw new Molinos_HTTP_Exceptions_Forbidden(t('You were successfully authenticated, but the administrator of this web site had turned off creation of new accounts. Condolences.'));
- }
- return new Molinos_HTTP_Responses_Redirect('admin?openid=failed');
- }
- protected function getForm()
- {
- $form = Molinos_Core_API::getInstance('form')->createForm(array(
- 'title' => t('Log in using OpenID'),
- 'class' => 'autofocus',
- ));
- $form->addControl("TextLine", array(
- 'value' => 'id',
- 'label' => t('Your OpenID'),
- ));
- $form->addControl("Submit", array(
- 'text' => t('Log in'),
- ));
- return $form;
- }
- /**
- * ?????? ??????????? ?? OpenID.
- *
- * ???????? ?????????? ? ???? id ???????? ? {@link verify()}.
- */
- public function post()
- {
- return $this->verify($this->rarg('id'));
- }
- /**
- * ???????? ??????????????.
- *
- * @param string $id OpenID.
- */
- protected function verify($openid)
- {
- $this->include_openid();
- $consumer = $this->getConsumer();
- // Begin the OpenID authentication process.
- // No auth request means we can't begin OpenID.
- if (!($auth_request = $consumer->begin($openid))) {
- throw new RuntimeException(t('Could not reach your OpenID provider, please try again later.'));
- return new Molinos_HTTP_Responses_Redirect('user/logout');
- }
- $sreg_request = Auth_OpenID_SRegRequest::build(
- array('nickname'), // Required
- array('fullname', 'email') // Optional
- );
- if ($sreg_request)
- $auth_request->addExtension($sreg_request);
- $policy_uris = $this->arg('policies');
- $pape_request = new Auth_OpenID_PAPE_Request($policy_uris);
- if ($pape_request)
- $auth_request->addExtension($pape_request);
- $ax = new Auth_OpenID_AX_FetchRequest();
- $ax->add(Auth_OpenID_AX_AttrInfo::make('http://axschema.org/contact/email', 2, 1, 'email'));
- $ax->add(Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/first', 1, 1, 'firstname'));
- $ax->add(Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/last', 1, 1, 'lastname'));
- $ax->add(Auth_OpenID_AX_AttrInfo::make('http://axschema.org/pref/language', 1, 1, 'language'));
- $auth_request->addExtension($ax);
- $logger = Molinos_Core_Logger::getInstance();
- // Redirect the user to the OpenID server for authentication.
- // Store the token for this authentication so we can verify the
- // response.
- // For OpenID 1, send a redirect. For OpenID 2, use a Javascript
- // form to send a POST request to the server.
- if ($auth_request->shouldSendRedirect()) {
- $redirect_url = $auth_request->redirectURL($this->getTrustRoot(), $this->getReturnTo($openid));
- if (Auth_OpenID::isFailure($redirect_url)) {
- // If the redirect URL can't be built, display an error message.
- $logger->warning("Could not redirect to server: " . $redirect_url->message, 'openid');
- } else {
- return new Molinos_HTTP_Responses_Redirect($redirect_url);
- }
- } else {
- // Generate form markup and render it.
- $form_id = 'openid_message';
- $form_html = $auth_request->formMarkup($this->getTrustRoot(), $this->getReturnTo($openid), false, array('id' => $form_id));
- $logger->debug($form_html);
- // Display an error if the form markup couldn't be generated;
- // otherwise, render the HTML.
- if (Auth_OpenID::isFailure($form_html)) {
- $logger->warning("Could not redirect to server: " . $form_html->message, 'openid');
- } else {
- $page_contents = "<html><head><title>"
- . "OpenID transaction in progress"
- . "</title></head>"
- . "<body onload='document.getElementById(\"".$form_id."\").submit()'>"
- . $form_html
- . "</body></html>";
- return new Molinos_HTTP_Responses_Simple($page_contents);
- }
- }
- }
- protected function include_openid()
- {
- $path_extra = dirname(dirname(__FILE__));
- $path = ini_get('include_path');
- $path = $path_extra . PATH_SEPARATOR . $path;
- ini_set('include_path', $path);
- require_once "Auth/OpenID/Consumer.php";
- require_once "Auth/OpenID/FileStore.php";
- require_once "Auth/OpenID/AX.php";
- require_once "Auth/OpenID/SReg.php";
- require_once "Auth/OpenID/PAPE.php";
- }
- protected function getConsumer()
- {
- $store = $this->getStore();
- return new Auth_OpenID_Consumer($store, new Molinos_OpenID_Session($this->ctx->session));
- }
- protected function getStore()
- {
- $store_path = Molinos_Core_Utils::mkdir($path = Molinos_Core_Utils::path(Molinos_Core_Utils::tmpdir(), 'openid'), 'Could not create the FileStore directory (%path), please check the effective permissions.', array(
- '%path' => $path,
- ));
- return new Auth_OpenID_FileStore($store_path);
- }
- protected function getTrustRoot()
- {
- return $this->request->base_url;
- }
- protected function getScheme()
- {
- return 'http';
- }
- /**
- * ?????????? ???????? ?????.
- *
- * @param string $id OpenID.
- * @return string ?????, ?? ??????? ?????????? ??????? ??????? ????????????.
- */
- protected function getReturnTo($id)
- {
- $url = $this->ctx->request->base_url
- . $this->ctx->lp
- . $this->path
- . '?action=return&id=' . urlencode($id)
- . '&sid=' . $this->ctx->session->id
- . '&destination=' . urlencode($this->arg('destination'));
- Molinos_Core_Logger::getInstance()->debug($url, 'openid');
- return $url;
- }
- /**
- * ????? ????????????? ????????????.
- *
- * ????????? ??????? ????????????????? ????????????. ???? ???????
- * ?? ??????, ???????? ??????? ????? (???? ??? ?? ????????? ? ??????????).
- *
- * @return Molinos_Auth_Nodes_User ??????? ????????????.
- * @uses getAttributes() ??? ?????? ?? ????????? ?????????? OpenID.
- * @uses authExistingUser() ??? ??????????? ????????????? ????????????.
- * @uses registerNewUser() ??? ??????????? ?????? ????????????.
- */
- protected function getUser()
- {
- $logger = Molinos_Core_Logger::getInstance();
- if ('id_res' != $this->arg('openid_mode')) {
- $logger->debug('login cancelled ?!');
- throw new Molinos_Core_Exceptions_Response(new Molinos_HTTP_Responses_Redirect('user/logout'));
- }
- $data = $this->getAttributes();
- // ??????? ?????? ??? ??????? ???????? ????????????.
- $filter = array(
- 'class' => 'user',
- 'deleted' => 0,
- 'published' => 1,
- '#sort' => 'id',
- 'lang' => Molinos_I18n_Utils::getEnabledLanguages(),
- );
- // ????????? ?????????????.
- if (!empty($data['url']))
- $filter['url'] = $data['url'];
- elseif (!empty($data['email']))
- $filter['email'] = $data['email'];
- else {
- $logger->error(t('OpenID response has neither an URL nor an email.'));
- throw new Molinos_HTTP_Exceptions_BadRequest();
- }
- if (!count($nodes = Molinos_Core_API::getInstance('node')->find($filter)))
- $user = $this->registerNewUser($data);
- else
- $user = $this->authExistingUser(array_shift($nodes), $data);
- return new Molinos_Auth_User($user->id, $user->getLinkedTo('group', true));
- }
- /**
- * ??????????? ?????? ????????????.
- *
- * @param array $data ???????? ????????????, ?????????? ?? ??????????.
- * @return Molinos_Auth_Nodes_User ??????? ???????????? (???????????).
- */
- protected function registerNewUser(array $data)
- {
- $node = Molinos_Core_API::getInstance('node')->create(array_merge($data, array(
- 'class' => 'user',
- 'published' => true,
- )));
- if (!$node->checkPermission(Molinos_Auth_ACL::CREATE))
- throw new Molinos_HTTP_Exceptions_Forbidden(t('You were successfully authenticated, but the administrator of this web site had turned off creation of new accounts. Condolences.'));
- return $node->save();
- }
- /**
- * ???????? ??????? ????????????? ????????????.
- *
- * ???? ??????? ?????, ????????? ?????? 403.
- * @return Molinos_Auth_Nodes_User ??????? ????????????.
- */
- protected function authExistingUser(Molinos_Auth_Nodes_User $node, array $data)
- {
- if (!empty($data['url']) and $node->url == $data['url'])
- ;
- elseif (!empty($data['email']) and $node->email == $data['email'])
- ;
- else {
- Molinos_Core_Logger::getInstance()->error("OpenID auth failed: user id mismatch. Node: {$node}, data:" . var_export($data, true));
- throw new Molinos_HTTP_Exceptions_ServiceUnavailable();
- }
- if (!$node->published)
- throw new Molinos_HTTP_Exceptions_Forbidden(t('Your user profile was suspended.'));
- return $node;
- }
- /**
- * ???????? ?? ?????? ???????????? ????????.
- *
- * @return array ????????????? ?????? ?????????.
- */
- protected function getAttributes()
- {
- $map = array(
- 'openid1_claimed_id' => 'url',
- 'openid_claimed_id' => 'url',
- 'openid_identity' => 'url',
- 'sreg_email' => 'email',
- 'sreg_fullname' => 'name',
- 'sreg_nickname' => 'nickname',
- 'openid_ext1_value_firstname' => 'firstname',
- 'openid_ext1_value_email' => 'email',
- 'openid_ext1_value_lastname' => 'lastname',
- 'openid_ext1_value_language' => 'lang',
- );
- $result = array();
- foreach ($map as $k => $v)
- if (empty($result[$v]) and ($tmp = $this->arg($k)))
- $result[$v] = $tmp;
- // ????????? ????????? ???????.
- if (empty($result['lang']) or !in_array($result['lang'], Molinos_I18n_Utils::getEnabledLanguages()))
- $result['lang'] = Molinos_I18n_Utils::getDefaultLanguage();
- if (empty($result['name']) and !empty($result['firstname']) and !empty($result['lastname']))
- $result['lname'] = $result['firstname'] . ' ' . $result['lastname'];
- return $result;
- }
- }