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'); } } }