diff options
Diffstat (limited to 'mod/openid_client/classes')
-rw-r--r-- | mod/openid_client/classes/ElggOpenIDConsumer.php | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/mod/openid_client/classes/ElggOpenIDConsumer.php b/mod/openid_client/classes/ElggOpenIDConsumer.php new file mode 100644 index 000000000..098201343 --- /dev/null +++ b/mod/openid_client/classes/ElggOpenIDConsumer.php @@ -0,0 +1,238 @@ +<?php +/** + * Consumer for OpenID + */ + +class ElggOpenIDConsumer { + + protected $openIdUrl; + protected $returnURL; + + protected $store; + protected $consumer; + protected $request; + + /** + * Constructor + * + * @param Auth_OpenID_OpenIDStore $store Optional persistence store + */ + public function __construct(Auth_OpenID_OpenIDStore $store = null) { + if ($store) { + $this->store = $store; + } else { + // use the default store + $this->store = new OpenID_ElggStore(); + } + } + + /** + * Set the OpenID username + * + * @param string $username + */ + public function setURL($url) { + $this->openIdUrl = $url; + } + + /** + * Set the return URL + * + * @param string $url The URL the OpenID provider returns the user to + */ + public function setReturnURL($url) { + $this->returnURL = $url; + } + + /** + * Send a request to the provider for authentication + * + * @return mixed HTMl form on success and false for failure + */ + public function requestAuthentication() { + + if (!$this->store) { + return false; + } + + $this->consumer = new Auth_OpenID_Consumer($this->store); + if (!$this->consumer) { + return false; + } + + $url = $this->openIdUrl; + if (!$url) { + return false; + } + + // discovers the identity server + $this->request = $this->consumer->begin($url); + if (!$this->request) { + return false; + } + + // request user information + if (!$this->addAttributeRequests()) { + return false; + } + + // send browser for authentication + return $this->getForm(); + } + + /** + * Complete the OpenID authentication by parsing the response + * + * This returns an array of key value pairs about the user. + * + * @return array + */ + public function completeAuthentication() { + + if (!$this->store) { + return false; + } + + $this->consumer = new Auth_OpenID_Consumer($this->store); + if (!$this->consumer) { + return false; + } + + $response = $this->consumer->complete($this->returnURL); + switch ($response->status) { + case Auth_OpenID_SUCCESS: + $data = $this->getUserData($response); + break; + case Auth_OpenID_FAILURE: + case Auth_OpenID_CANCEL: + $data = array(); + break; + } + + return $data; + } + + /** + * Add attribute requests to the OpenID authentication request + * + * @return bool + */ + protected function addAttributeRequests() { + + // Simple Registration + $required = array(); + $optional = array('email', 'nickname', 'fullname', 'language'); + $sregRequest = Auth_OpenID_SRegRequest::build($required, $optional); + if (!$sregRequest) { + return false; + } + $this->request->addExtension($sregRequest); + + // Attribute Exchange + $axRequest = new Auth_OpenID_AX_FetchRequest(); + $attributes[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/contact/email', 1, true, 'email'); + $attributes[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/first', 1, true, 'firstname'); + $attributes[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/last', 1, true, 'lastname'); + foreach ($attributes as $attribute) { + $axRequest->add($attribute); + } + $this->request->addExtension($axRequest); + + return true; + } + + /** + * Gets the form to send the user to the provider to authenticate + * + * This implements OpenID 2.0 by submitting a form through JavaScript against + * the provider. If JavaScript is not enabled, a plain html form with a + * continue button is displayed. + * + * This also supports OpenID 1.x but has not been tested as thoroughly. + * + * @return mixed + */ + protected function getForm() { + if (!$this->request->shouldSendRedirect()) { + // OpenID 2.0 + $html = $this->request->htmlMarkup(elgg_get_site_url(), $this->returnURL, false); + return $html; + } else { + // OpenID 1.x + $redirect_url = $this->request->redirectURL(elgg_get_site_url(), $this->returnURL); + + if (Auth_OpenID::isFailure($redirect_url)) { + return false; + } else { + forward($redirect_url); + } + } + } + + /** + * Get user data from the OpenID response + * + * @param Auth_OpenID_ConsumerResponse $response + * @return array + */ + protected function getUserData($response) { + if (!$response) { + return array(); + } + + $sregResponse = Auth_OpenID_SRegResponse::fromSuccessResponse($response); + $sreg = $sregResponse->contents(); + + $axResponse = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($response); + $ax = $axResponse->data; + + $data = $this->extractUserData($sreg, $ax); + $data['openid_identifier'] = $response->getDisplayIdentifier(); + + return $data; + } + + /** + * Extract user data from the extensions in the response + * + * @param array $sreg Simple Registration data + * @param array $ax Attribute Exchange data + * @return array + */ + protected function extractUserData($sreg, $ax) { + $data = array(); + + // email + if (isset($sreg['email'])) { + $data['email'] = $sreg['email']; + } + if (isset($ax['http://axschema.org/contact/email'])) { + $data['email'] = $ax['http://axschema.org/contact/email'][0]; + } + + // display name + if (isset($sreg['fullname'])) { + $data['name'] = $sreg['fullname']; + } + if (isset($ax['http://axschema.org/namePerson/first'])) { + $data['name'] = $ax['http://axschema.org/namePerson/first'][0]; + } + if (isset($ax['http://axschema.org/namePerson/last'])) { + $data['name'] .= ' ' . $ax['http://axschema.org/namePerson/last'][0]; + $data['name'] = trim($data['name']); + } + + // username + if (isset($sreg['nickname'])) { + $data['username'] = $sreg['nickname']; + } + + // language + if (isset($sreg['language'])) { + $languages = get_installed_translations(); + // @todo - find out format + } + + return $data; + } +} |