Using JanRain OpenID with Zend Framework
January 28, 2008 – 4:35 pmOk, I know Zend_OpenId is on the way, but for those of us who don’t like to wait here’s a way to get OpenID working with Zend Framework. Besides, JanRain’s libraries tend to be pretty solid and up to date so you won’t go wrong using this in place of Zend_OpenId if you choose to in the future.
This implementation is pretty simple. They only thing thrown in is support for saving the last page the user visited on your site so you can return them there once authentication is finished.
I didn’t include any extension support for the simplicity sake, but if you wanted to add Simple Registration or something the examples that come with the JanRain libraries are fairly straightforward.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | <?php // Make sure these files from the JainRain libraries // are in your path. require_once "Auth/OpenID/Consumer.php"; require_once "Auth/OpenID/FileStore.php"; require_once "Auth/OpenID/SReg.php"; /** * OpenID login controller using JanRain OpenID 2.0 * libraries. * * By: Steven Osborn - http://steven.bitsetters.com */ class LoginController extends Zend_Controller_Action { protected $consumer = null; protected $store = null; protected $domain = 'example.com'; protected $session = null; protected $openid = null; /** * Setup some resources we'll need later for storing * and retrieving data. */ public function init() { $this->session = Zend_Registry::getInstance()->get('session'); $this->store = $this->getFileStore(); $this->consumer = new Auth_OpenID_Consumer($this->store); } /** * Create a file store object for consumer */ public function getFileStore() { $store_path = "/tmp/openid"; if(!file_exists($store_path) && !mkdir($store_path) ) { echo "Could not create file store."; exit; } return new Auth_OpenId_FileStore($store_path); } /** * This is the default action for the controller. Which * does two basic things. * 1. Records what page the user came from so we can return * them there after login. * 2. Renders the index view. (Login form). Since this is the * index action it will automatically render * views/scripts/login/index.phtml without explicitly calling * $this->view->render('index'); */ public function indexAction() { // Save the page the user was last at and return them to it // after authentication. $return_url = parse_url($_SERVER['HTTP_REFERER']); if($return_url['host'] == $this->domain) { $return = $return_url['path']; if(strlen($return_url['query'])) { $return .= "?" . $return_url['query']; } if(strlen($return_url['fragment'])>0) { $return .= "#" . $return_url['fragment']; } $this->session->loginReturn = $return; } } /** * The login view from the index action posts to this action, then * we call consumer->begin() whichs starts the openid login process * with the open id from the form post. */ public function tryAction() { try { // Make sure the user entered something. if(strlen($this->openid) == 0) { throw new Exception('OpenID is empty.'); } // Try to start an openid authentication. $auth_request = $this->consumer->begin($this->openid); if(!$auth_request) { throw new Exception("No Auth Request"); } $redirect_url = $auth_request ->RedirectURL($this->getTrustRoot(),$this->getReturnTo()); if (Auth_OpenID::isFailure($redirect_url)) { throw new Exception("Could not redirect to server: " . $redirect_url->message); } } catch (Exception $e) { $this->view->error = $e->getMessage(); $this->render('index'); return; } header("Location: ".$redirect_url); $this->render('index'); } /** * When the identity provider is done having their * moment with the user they get returned to this action. * Here we look at the response status codes to decide * to if they were authenticated or not. */ public function finishAction() { $return_to = $this->getReturnTo(); $response = $this->consumer->complete($return_to); if($response->status == Auth_OpenID_CANCEL) { $this->view->error = 'Verification cancelled.'; } else if ($response->status == Auth_OpenID_FAILURE) { $this->view->error = "OpenID authentication failed: " . $response->message; } else if ($response->status == Auth_OpenID_SUCCESS) { $this->view->error = "Success"; if(isset($this->session->loginReturn) && strlen($this->session->loginReturn) > 0) { $user = new User($response->identity_url); if($user->isEnrolled()) { // TODO: Vodoo for setup up a user session and // logging them in. // If the user is enrolled, return them to the page // they visited before the header("Location: " . $this->session->loginReturn); exit; } // The user was logged in successfully, but this is // their first time on your site, so send them through // enrollment. header("Location: /enroll"); } } $this->render('index'); } ////////////////////////////////////// // HELPER FUNCTIONS ///////////////////////////////////// /** * Returns http or https depending on the current protocol */ private function getScheme() { $scheme = 'http'; if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') { $scheme .= 's'; } return $scheme; } /** * Answers the URL we wish for the identity provider to return * a user to once the authentication process is finished. */ private function getReturnTo() { return sprintf("%s://%s/login/finish", $this->getScheme(), $_SERVER['SERVER_NAME']); } /** * Answers the trust root for this domain. */ private function getTrustRoot() { return sprintf("%s://%s/", $this->getScheme(), $_SERVER['SERVER_NAME']); } } ?> |
You must be logged in to post a comment.