aboutsummaryrefslogtreecommitdiff
path: root/classes/OpenID_ElggStore.php
diff options
context:
space:
mode:
Diffstat (limited to 'classes/OpenID_ElggStore.php')
-rw-r--r--classes/OpenID_ElggStore.php228
1 files changed, 228 insertions, 0 deletions
diff --git a/classes/OpenID_ElggStore.php b/classes/OpenID_ElggStore.php
new file mode 100644
index 000000000..de8aa226a
--- /dev/null
+++ b/classes/OpenID_ElggStore.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Uses Elgg data model to store OpenID associations
+ *
+ * Written to be compatible with the Elgg store written by Kevin Jardine for
+ * the original OpenID client plugin.
+ */
+class OpenID_ElggStore extends Auth_OpenID_OpenIDStore {
+
+ /**
+ * Store an association
+ *
+ * @param string $server_url The identity server endpoint
+ * @param Auth_OpenID_Association $association The association to store.
+ */
+ public function storeAssociation($server_url, $association) {
+
+ $object = new ElggObject();
+ $object->subtype = 'openid_client::association';
+ $object->owner_guid = 0;
+ $object->container_guid = 0;
+ $object->title = 'association';
+ $object->access_id = ACCESS_PUBLIC;
+ $object->server_url = $server_url;
+ $object->handle = $association->handle;
+ $object->secret = base64_encode($association->secret);
+ $object->issued = $association->issued;
+ $object->lifetime = $association->lifetime;
+ $object->assoc_type = $association->assoc_type;
+
+ $object->save();
+ }
+
+ /**
+ * Get an association
+ *
+ * @param string $server_url The identity server endpoint
+ * @param string $handle The association handle
+ * @return Auth_OpenID_Association
+ */
+ public function getAssociation($server_url, $handle = null) {
+
+ $assocs = $this->getAssociations($server_url, $handle);
+ if (!$assocs || count($assocs) == 0) {
+ return null;
+ } else {
+ $associations = array();
+
+ foreach ($assocs as $object) {
+ $assoc = new Auth_OpenID_Association(
+ $object->handle,
+ base64_decode($object->secret),
+ $object->issued,
+ $object->lifetime,
+ $object->assoc_type);
+
+ if ($assoc->getExpiresIn() == 0) {
+ $this->removeAssociation($server_url, $assoc->handle);
+ } else {
+ $associations[] = array($assoc->issued, $assoc);
+ }
+ }
+
+ if ($associations) {
+ $issued = array();
+ $assocs = array();
+ foreach ($associations as $key => $assoc) {
+ $issued[$key] = $assoc[0];
+ $assocs[$key] = $assoc[1];
+ }
+
+ array_multisort($issued, SORT_DESC, $assocs, SORT_DESC, $associations);
+
+ // return the most recently issued one.
+ list($issued, $assoc) = $associations[0];
+ return $assoc;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Remove selected associations from storage
+ *
+ * @param string $server_url The identity server endpoint
+ * @param string $handle The association handle
+ */
+ public function removeAssociation($server_url, $handle) {
+ $assocs = $this->getAssociations($server_url, $handle);
+ foreach ($assocs as $assoc) {
+ $assoc->delete();
+ }
+ }
+
+ /**
+ * Get all associations
+ *
+ * @param string $server_url The identity server endpoint
+ * @param string $handle The association handle
+ * @return array
+ */
+ protected function getAssociations($server_url, $handle) {
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'openid_client::association',
+ 'metadata_name_value_pairs' => array(
+ array('name' => 'server_url', 'value' => $server_url)
+ ),
+ 'limit' => 0,
+ );
+
+ if ($handle !== null) {
+ $options['metadata_name_value_pairs'][] = array(
+ 'name' => 'handle',
+ 'value' => $handle
+ );
+ }
+
+ return elgg_get_entities_from_metadata($options);
+ }
+
+ /**
+ * Cleanup associations that have expired
+ *
+ * @todo I think we need to store expire time ans use that here
+ *
+ * @return int
+ */
+ public function cleanupAssociations() {
+ $options = array(
+ 'type' => 'object',
+ 'subtype' => 'openid_client::association',
+ 'metadata_name_value_pairs' => array(
+ array('name' => 'lifetime', 'value' => time(), 'operand' => '<')
+ ),
+ 'limit' => 0,
+ );
+ $associations = elgg_get_entities_from_metadata($options);
+ $total = count($associations);
+
+ foreach ($associations as $association) {
+ $association->delete();
+ }
+
+ return $total;
+ }
+
+ /**
+ * Can we use this nonce?
+ *
+ * Checks time skew and replay
+ *
+ * @param type $server_url The identity server endpoint
+ * @param type $timestamp The timestamp from the nonce
+ * @param type $salt The salt from the nonce
+ * @return bool
+ */
+ public function useNonce($server_url, $timestamp, $salt) {
+ global $Auth_OpenID_SKEW;
+
+ if (abs($timestamp - time()) > $Auth_OpenID_SKEW) {
+ return false;
+ }
+
+ // @todo
+ // we should check if nonce has been used before to guard against replays
+ return true;
+ }
+
+ /**
+ * Cleanup nonces that would not pass the time skew test
+ *
+ * @return int
+ */
+ public function cleanupNonces() {
+ global $Auth_OpenID_SKEW;
+ $cutoff = time() - $Auth_OpenID_SKEW;
+
+ // @todo
+
+ return 0;
+ }
+
+ /**
+ * Does this storage class support cleanup?
+ *
+ * @return bool
+ */
+ public function supportsCleanup() {
+ return true;
+ }
+
+ /**
+ * Cleanup expired data in storage
+ *
+ * @return array
+ */
+ public function cleanup() {
+ return array($this->cleanupNonces(), $this->cleanupAssociations());
+ }
+
+ /**
+ * Remove everything from storage
+ *
+ * @return void
+ */
+ public function reset() {
+ $associations = elgg_get_entities(array(
+ 'type' => 'object',
+ 'subtype' => 'openid_client::association',
+ 'limit' => 0,
+ ));
+ foreach ($associations as $association) {
+ $association->delete();
+ }
+
+ $nonces = elgg_get_entities(array(
+ 'type' => 'object',
+ 'subtype' => 'openid_client::nonce',
+ 'limit' => 0,
+ ));
+
+ foreach ($nonces as $nonce) {
+ $nonce->delete();
+ }
+ }
+}