Ejemplo n.º 1
0
 public function authenticateExternalAction()
 {
     // get an instace of Zend_Auth
     $auth = Zend_Auth::getInstance();
     $authSess = new Zend_Session_Namespace('Auth');
     // check if a user is already logged
     if ($auth->hasIdentity()) {
         $this->_helper->FlashMessenger('You are already logged in.');
         return $this->_helper->redirector()->gotoRoute(array(), 'home');
     }
     // if the user is not logged, the do the logging
     // $openid_identifier will be set when users 'clicks' on the account provider
     $openid_identifier = $this->getRequest()->getParam('openid_identifier', null);
     if ($openid_identifier) {
         $authSess->identifier = $openid_identifier;
     }
     //echo 'ID: '.$openid_identifier.'<br>'; exit;
     // $openid_mode will be set after first query to the openid provider
     $openid_mode = $this->getRequest()->getParam('openid_mode', null);
     // this one will be set by facebook connect
     $code = $this->getRequest()->getParam('code', null);
     // while this one will be set by twitter
     $oauth_token = $this->getRequest()->getParam('oauth_token', null);
     // do the first query to an authentication provider
     if ($openid_identifier) {
         $this->log('Authenticating using external source: ' . $openid_identifier);
         if ('https://www.twitter.com' == $openid_identifier) {
             $adapter = $this->_getTwitterAdapter();
         } else {
             if ('https://www.facebook.com' == $openid_identifier) {
                 $adapter = $this->_getFacebookAdapter();
             } else {
                 // for openid
                 $adapter = $this->_getOpenIdAdapter($openid_identifier);
                 // specify what to grab from the provider and what extension to use
                 // for this purpose
                 $toFetch = $this->_keys->openid->tofetch->toArray();
                 // for google and yahoo use AtributeExchange Extension
                 if ('https://www.google.com/accounts/o8/id' == $openid_identifier || 'http://me.yahoo.com/' == $openid_identifier) {
                     $ext = $this->_getOpenIdExt('ax', $toFetch);
                 } else {
                     $ext = $this->_getOpenIdExt('sreg', $toFetch);
                 }
                 $adapter->setExtensions($ext);
             }
         }
         // here a user is redirect to the provider for loging
         $result = $auth->authenticate($adapter);
         $this->log('Login redirection failed.');
         $this->log(print_r($result, true));
         // the following two lines should never be executed unless the redirection faild.
         //$this->_helper->FlashMessenger('Redirection failed');
         //$this->_redirect('/login');
         $form = $this->getLoginForm();
         $this->view->form = $form;
         $form->addError('Something went wrong while authenticating you! Please email help@practicalplants.org for assistance.');
         return $this->render('login');
     } else {
         if ($openid_mode || $code || $oauth_token) {
             // this will be exectued after provider redirected the user back to us
             if ($code) {
                 $this->log('Facebook response: ' . $code);
                 // for facebook
                 $adapter = $this->_getFacebookAdapter();
             } else {
                 if ($oauth_token) {
                     $this->log('Twitter  response: ' . $oauth_token);
                     // for twitter
                     $adapter = $this->_getTwitterAdapter();
                 } else {
                     // for openid
                     $adapter = $this->_getOpenIdAdapter(null);
                     // specify what to grab from the provider and what extension to use
                     // for this purpose
                     $ext = null;
                     $toFetch = $this->_keys->openid->tofetch->toArray();
                     $this->log('OpenID response: ' . $toFetch);
                     // for google and yahoo use AtributeExchange Extension
                     if (isset($_GET['openid_ns_ext1']) || isset($_GET['openid_ns_ax'])) {
                         $ext = $this->_getOpenIdExt('ax', $toFetch);
                     } else {
                         if (isset($_GET['openid_ns_sreg'])) {
                             $ext = $this->_getOpenIdExt('sreg', $toFetch);
                         }
                     }
                     if ($ext) {
                         $ext->parseResponse($_GET);
                         $adapter->setExtensions($ext);
                     }
                 }
             }
             $result = $auth->authenticate($adapter);
             $this->log('Auth result: ' . (string) $result->isValid());
             if ($result->isValid()) {
                 $externalData = array('identity' => $auth->getIdentity());
                 $this->log('Auth identity: ' . print_r($auth->getIdentity(), true));
                 if (isset($ext)) {
                     // for openId
                     $externalData['properties'] = $ext->getProperties();
                     $externalData['provider'] = 'OpenID';
                 } else {
                     if ($code) {
                         // for facebook
                         $msgs = $result->getMessages();
                         $externalData['properties'] = (array) $msgs['user'];
                         $externalData['provider'] = 'Facebook';
                     } else {
                         if ($oauth_token) {
                             // for twitter
                             $identity = $result->getIdentity();
                             // get user info
                             $twitterUserData = (array) $adapter->verifyCredentials();
                             $externalData = array('identity' => $identity['user_id']);
                             $externalData['properties'] = $twitterUserData;
                             $externalData['provider'] = 'Twitter';
                         } else {
                             //we don't have external data!
                             $externalData['provider'] = 'OpenID';
                         }
                     }
                 }
                 $this->log('External auth valid: ' . $externalData);
                 /* Process after external auth is valid:
                    	- See if there's already a local user which matches the auth method & identity
                    	- If not, make sure the auth provider gave us an email address
                    	- Check to see if there are any local users with that email address
                    	- If so, then inform the user if they'd like to associate the two accounts, they can do so by entering the local password
                    	- If not, register the user a local account with the email address from the external auth, and allow them to choose a username and display name, prefilling the data where provided from the external auth
                    */
                 //print_r($ext);
                 //print_r($externalData);
                 //print_r($authSess->identifier);
                 //print_r($openid_mode);
                 //exit;
                 if (!is_array($externalData) || !isset($externalData['properties'])) {
                     // || !is_array($externalData['properties']) || !isset($externalData['properties']['email'])){
                     //$auth->clearIdentity();
                     //print_r($externalData); exit;
                     //$this->view->external_provider = $externalData['provider'];
                     //return $this->render('authenticate-external-insufficient');
                 } else {
                     //$auth->getStorage()->write($externalData);
                     $authSess->external = $externalData;
                 }
                 $users = new Application_Model_Users();
                 //print_r($externalData); exit;
                 //check if a user can be found associated with this external identity
                 if (!($user = $users->getUserByAuthIdentity($externalData['provider'], $externalData['identity']))) {
                     //store auth data to session
                     /*$sess = new Zend_Session_Namespace('CreateUserFromExternal');
                      	$sess->provider = $externalData['provider'];
                      	$sess->identity = $externalData['identity'];
                      	$auth->clearIdentity();*/
                     //echo 'no auth user - ';
                     //echo 'No local user'; exit;
                     //no local user attached to this auth provider
                     if (isset($externalData['properties']['email'])) {
                         $user = $users->getUserBy('email', $externalData['properties']['email']);
                     }
                     if (isset($user) && $user !== false) {
                         //local user with matching email, but not logged in with this auth before, attempt to link!
                         //$auth->getStorage()->write($user->email); //change identity to email address
                         //$user->associateNewProvider();
                         return $this->_forward('associate-provider');
                         //echo 'found email user';
                     } else {
                         //no user found, redirect to form to create new local user
                         //$this->_redirect()->gotoRoute(array(),'create-from-external');
                         //clear identity - user has been successfully externally authenticated, but no local user account exists yet
                         $auth->clearIdentity();
                         return $this->_forward('create-from-external');
                     }
                 } else {
                     $authSess = new Zend_Session_Namespace('Auth');
                     //echo 'Local authed';print_r($user->toArray()); exit;
                     //user has authenticated externally and has local account, so change identity to local
                     $auth->getStorage()->write($user->email);
                     $authSess->identity = $auth->getIdentity();
                     $authSess->user = $user->toArray();
                     //echo 'DONE'; exit;
                     //tell integrated services the user is logged in
                     $integrations = new Application_Model_Integrations();
                     $integrations->onAuthenticate();
                     if (isset($authSess->redirect) && !empty($authSess->redirect)) {
                         //whitelist domain here?
                         $this->view->redirect = $authSess->redirect;
                         return $this->render('redirect');
                         //header('Location: '.$authSess->redirect);
                         //exit;
                         //$this->_helper->redirector()->gotoUrl($authSess->redirect);
                     }
                     $this->_helper->redirector()->gotoRoute(array(), 'home');
                 }
             } else {
                 //echo 'Failed auth<pre>';
                 //print_r($result);
                 //exit;
                 //$this->_helper->FlashMessenger('Failed authentication');
                 //$this->_helper->FlashMessenger($result->getMessages());
                 $this->view->message = implode(' - ', $result->getMessages()) || 'Authentication failed.';
                 $this->log('External auth failed: ' . print_r($result->getMessages(), true));
                 return $this->render('error');
             }
         } else {
             $this->view->message = 'No OpenID authentication URL provided.';
             return $this->render('error');
         }
     }
 }